如何检查`IEnumerable <T1>`covariant到`IEnumerable <T2>`?

Ast*_*tor 7 c# ienumerable covariance

检查是否IEnumerable<T1>协变的常见规则是什么IEnumerable<T2>

我做了一些实验:


1.

Object Obj = "Test string";
IEnumerable<Object> Objs = new String[100];
Run Code Online (Sandbox Code Playgroud)

因为IEnumerable<out T>协变和String继承而起作用Object.

2.

interface MyInterface{}
struct MyStruct:MyInterface{}
.....
Object V = new MyStruct();
Console.WriteLine(new MyStruct() is Object); // Output: True. 
IEnumerable<Object> Vs = new MyStruct[100]; // Compilation error here
Run Code Online (Sandbox Code Playgroud)

MyStruct实际上是一个Object,但它不起作用,因为Object是引用类型,MyStruct是值类型.好的,我在这看到一些逻辑.

3.

Console.WriteLine(new MyStruct() is ValueType); // Output: "True"
ValueType V2 = new MyStruct();
IEnumerable<ValueType> Vs2 = new MyStruct[100]; // Compilation error here
Run Code Online (Sandbox Code Playgroud)

应该工作,因为IEnumerable<out T>是协变和MyStructIS ValueType,但不起作用......好吧,也许MyStruct实际上并没有继承ValueType....

4.

MyInterface V3 = new MyStruct(); 
Console.WriteLine(V3 is MyInterface); // Output: "True" 
IEnumerable<MyInterface> Vs3 = new MyStruct[100]; // Compilation error here
Run Code Online (Sandbox Code Playgroud)

即使这样:"无法将MyStruct转换为MyInterface".真的吗??你刚才做了一行......


我试图制定共同规则:

public static bool IsCovariantIEnumerable(Type T1, Type T2  ){          
    return (T2.IsAssignableFrom(T1)) && !T2.IsValueType; // Is this correct??
}
Run Code Online (Sandbox Code Playgroud)

那么,问题是如何实际确定是否IEnumerable<T1>协变IEnumerable<T2>?我的IsCovariantIEnumerable(...)功能是否正确?如果是,是否有任何更简单的方法来检查它?如果没有,如何解决?

另请参阅这些文章:1,2.

Ren*_*ogt 5

在您的特定情况下,它不起作用,因为值类型不支持协方差.

但是,对于这个问题如何确定是否一个IEnumerable<T2>共同变种IEnumerable<T1>:

该方法Type.IsAssignableFrom()告诉您某种类型的实例是否已分配给此类型的变量.所以你可以这样实现你的方法:

public static bool IsCovariantIEnumerable(Type T1, Type T2)
{
    Type enumerable1 = typeof(IEnumerable<>).MakeGenericType(T1);
    Type enumerable2 = typeof(IEnumerable<>).MakeGenericType(T2);
    return enumerable1.IsAssignableFrom(enumerable2);
}
Run Code Online (Sandbox Code Playgroud)

用法:

if (IsCovariantIEnumerable(typeof(object), typeof(string))
    Console.WriteLine("IEnumerable<string> can be assigned to IEnumerable<object>");
Run Code Online (Sandbox Code Playgroud)

IsCovariantIEnumerable(typeof(object), typeof(MyStruct))由于上述原因,将返回false.


为了完整性:当然,您不需要额外的方法,因为您可以轻松完成false.