开放类型List<>和IEnumerable<>?之间有什么关系吗?
例:
var type1 = typeof(List<>);
var type2 = typeof(IEnumerable<>);
//return false
type2.IsAssignableFrom(type1);
Run Code Online (Sandbox Code Playgroud)
有没有任何方法可以检查两种开放类型之间的关系,或者关系只存在于封闭类型上?
Joh*_* Wu 19
List<>而IEnumerable<>不是类型; 它们是类型定义.因此,询问一个人是否可以转让给另一个人是没有意义的.两者都不能分配给.例如,您无法声明变量List<> a = null- 您将收到编译错误"意外使用未绑定的通用名称".
指定type参数时,类型定义将成为泛型类型.此时,它是一种类型,可以分配给.所以例如List<string>可以分配给IEnumerable<string>.
如果您有一个类型定义并且想要进行类型兼容性检查,只需使用<object>(或者如果存在类型约束,则使用合适的类型),而不是<>:
var type1 = typeof(List<object>);
var type2 = typeof(IEnumerable<object>);
//returns true
type2.IsAssignableFrom(type1);
Run Code Online (Sandbox Code Playgroud)
Jev*_*sen 16
尽管John Wu对类型定义与实际类型之间的差异写了一个很好的答案,但我认为它并没有完全回答OP中提出的问题/问题.
有没有任何方法可以检查两种开放类型之间的关系,或者关系只存在于封闭类型上?
首先,这种关系始终存在; 每个List<>都是一个IEnumerable<>,你可以在List<T>类型的定义中看到:
public class List<T> : IList<T>, ICollection<T>, IEnumerable<T>, ...
但是如果有办法检查两种类型之间是否存在这种关系,那么这不能回答你的第二个问题.您可能会认为该IsAssignableFrom方法可用于检查类型打开类型之间是否存在关系,但您不能.为什么?让我们在IsAssignableFrom 函数的文档中找到:
Type.IsAssignableFrom(Type c)如果满足以下任一条件,则返回true:
- c和当前实例表示相同的类型.
c直接或间接地从当前实例派生.如果它从当前实例继承,则直接从当前实例派生; 如果c继承自从当前实例继承的一个或多个类的连续,则c从当前实例间接派生.
当前实例是c实现的接口.
c是泛型类型参数,当前实例表示c的约束之一.
如果这些条件均不为真,或者c为null,则为false.
在您的情况下,上述条件都不会导致如下:(1)它们不是同一类型.(2)它们不能相互派生,因为它们是开放类型:它们的泛型类型参数是未知的(unknown != unknown).所述List<>器具的闭合IEnumerable<T>型,而不是打开IEnumerable<>的类型(3).它们不是通用类型参数(4).
要确定两个泛型类型是否存在关系,您需要检查它们type definitions(及其嵌套的接口/基类型)并验证它们是否存在关系:
public static bool IsAssignableToOpenGenericType(Type givenType, Type genericType)
{
var interfaceTypes = givenType.GetInterfaces();
foreach (var it in interfaceTypes)
{
if (it.IsGenericType && it.GetGenericTypeDefinition() == genericType)
return true;
}
if (givenType.IsGenericType && givenType.GetGenericTypeDefinition() == genericType)
return true;
Type baseType = givenType.BaseType;
if (baseType == null) return false;
return IsAssignableToGenericType(baseType, genericType);
}
Run Code Online (Sandbox Code Playgroud)
将导致:
var typ1 = typeof(List<>);
var typ2 = typeof(IEnumerable<>);
// true, List<>'s type definition contains an IEnumerable<>
Console.WriteLine(IsAssignableToOpenGenericType(typ1, typ2));
// false, IEnumerable<>'s type definition does not contain List<>
Console.WriteLine(IsAssignableToOpenGenericType(typ2, typ1));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
897 次 |
| 最近记录: |