如何检查 `IEnumerable<T1>` 是否与 `IEnumerable<T2>` 协变?
How to check if `IEnumerable<T1>` covariant to `IEnumerable<T2>`?
检查 IEnumerable<T1>
是否与 IEnumerable<T2>
协变的通用规则是什么?
我做了一些实验:
1.
Object Obj = "Test string";
IEnumerable<Object> Objs = new String[100];
有效,因为 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
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
应该可以工作,因为 IEnumerable<out T>
是协变的,而 MyStruct
是 ValueType
,但不工作......好吧,也许 MyStruct
不实际上继承了 ValueType
.....
4.
MyInterface V3 = new MyStruct();
Console.WriteLine(V3 is MyInterface); // Output: "True"
IEnumerable<MyInterface> Vs3 = new MyStruct[100]; // Compilation error here
即使这样:"Cannot convert MyStruct to MyInterface"。哦真的吗??你刚刚在一行之前做了...
我尝试制定通用规则:
public static bool IsCovariantIEnumerable(Type T1, Type T2 ){
return (T2.IsAssignableFrom(T1)) && !T2.IsValueType; // Is this correct??
}
那么,问题是如何实际确定 IEnumerable<T1>
是否与 IEnumerable<T2>
协变?我的 IsCovariantIEnumerable(...)
函数正确吗?如果是,有没有更简单的方法来检查它?如果没有,如何解决?
另请参阅这些文章:1, 2。
值类型不支持协变,因为它会改变它们的内部表示 [1]。
如果您想避免奇怪的情况,我建议您改用 IsAssignableFrom
:
public static bool IsCovariantIEnumerable(Type T1, Type T2) => T1.IsAssignableFrom(T2);
在您的特定情况下它不起作用,因为值类型不支持协方差。
但是对于如何确定 if 的问题,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);
}
用法:
if (IsCovariantIEnumerable(typeof(object), typeof(string))
Console.WriteLine("IEnumerable<string> can be assigned to IEnumerable<object>");
但是 IsCovariantIEnumerable(typeof(object), typeof(MyStruct))
会 return false
出于上述原因。
为了完整性:当然你不需要额外的方法,因为你可以很容易地做到typeof(IEnumerable<object>).IsAssignableFrom(typeof(IEnumerable<string>)
。
检查 IEnumerable<T1>
是否与 IEnumerable<T2>
协变的通用规则是什么?
我做了一些实验:
1.
Object Obj = "Test string";
IEnumerable<Object> Objs = new String[100];
有效,因为 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
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
应该可以工作,因为 IEnumerable<out T>
是协变的,而 MyStruct
是 ValueType
,但不工作......好吧,也许 MyStruct
不实际上继承了 ValueType
.....
4.
MyInterface V3 = new MyStruct();
Console.WriteLine(V3 is MyInterface); // Output: "True"
IEnumerable<MyInterface> Vs3 = new MyStruct[100]; // Compilation error here
即使这样:"Cannot convert MyStruct to MyInterface"。哦真的吗??你刚刚在一行之前做了...
我尝试制定通用规则:
public static bool IsCovariantIEnumerable(Type T1, Type T2 ){
return (T2.IsAssignableFrom(T1)) && !T2.IsValueType; // Is this correct??
}
那么,问题是如何实际确定 IEnumerable<T1>
是否与 IEnumerable<T2>
协变?我的 IsCovariantIEnumerable(...)
函数正确吗?如果是,有没有更简单的方法来检查它?如果没有,如何解决?
另请参阅这些文章:1, 2。
值类型不支持协变,因为它会改变它们的内部表示 [1]。
如果您想避免奇怪的情况,我建议您改用 IsAssignableFrom
:
public static bool IsCovariantIEnumerable(Type T1, Type T2) => T1.IsAssignableFrom(T2);
在您的特定情况下它不起作用,因为值类型不支持协方差。
但是对于如何确定 if 的问题,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);
}
用法:
if (IsCovariantIEnumerable(typeof(object), typeof(string))
Console.WriteLine("IEnumerable<string> can be assigned to IEnumerable<object>");
但是 IsCovariantIEnumerable(typeof(object), typeof(MyStruct))
会 return false
出于上述原因。
为了完整性:当然你不需要额外的方法,因为你可以很容易地做到typeof(IEnumerable<object>).IsAssignableFrom(typeof(IEnumerable<string>)
。