F# 相当于 C# typeof(IEnumerable<>)
-
21-09-2019 - |
题
我有一段代码,我需要弄清楚给定类型是否实现 IEnumerable<T>
(我不关心T)
我试过了 (t:System.Type
如果你想知道)
let interfaces = t.GetInterfaces()
let enumerbale =
interfaces.Any(fun t ->
t.GetGenericTypeDefinition() = typeof<IEnumerable<>>
)
但是这不会编译(编译不喜欢 <>)。然后我尝试了
let interfaces = t.GetInterfaces()
let enumerbale =
interfaces.Any(fun t ->
t.GetGenericTypeDefinition() = typeof<IEnumerable<'a>>
)
但收到警告,指出 'a 是 obj 的约束。我不想弄清楚是否 IEnumerable<obj>
已实施但 IEnumerabl<>
.
任何人都知道解决方案,顺便说一句,也可以随意对上面的代码发表评论。
解决方案
此应该工作:
typedefof<System.IEnumerable<_>>
修改强>
由于托马斯指出,没有什么特别之处这里_
通配符; F#推断该类型obj
是在这种情况下最普遍适用的类型,所以这是与使用typedefof<System.IEnumerable<obj>>
。在某些情况下,这种工作方式可以是有点障碍的,虽然。举例来说,如果你定义一个接口type I<'a when 'a :> I<'a>> = interface end
,那么你就不能使用typedefof<I<_>>
,因为I<obj>
不满足通用约束和F#不能推断出另一个更合适的类型。这可能发生,即使没有递归约束(例如type I<'a when 'a : struct and 'a :> System.ICloneable> = interface end
,这是相对于C#的方法,它在类似的情况下工作完全正常。
至于你的代码本身,我想你会想要做一些其他的变化也一样,如确保接口调用GetGenericTypeDefinition
前通用。以下是我会写的测试功能:
(fun t -> t.IsGenericType && (t.GetGenericTypeDefinition() = typedefof<_ seq>))
其他提示
据我所知,F#没有任何等同于C#的typeof(IEnumerable<>)
。这是因为,这是C#明确支持的一种特殊的语法。在F#,typeof
是一个正常的功能和类型参数需要是完全指明的类型。你可以得到一个泛型类型定义编程是这样的:
let t = typeof<IEnumerable<obj>>
let genericT = t.GetGenericTypeDefinition()
与IEnumerable<'a>
您的解决方案的问题是,F#编译器仍然需要找到一些具体类型的使用(如泛型类型定义是不是有效的类型)。如果类型推断推断类型参数是不以任何方式受到限制,它使用缺省类型,这是obj
。
修改我不知道typedefof<IEnumerable<_>>
,这是非常有用的!无论如何,请注意下划线没有这里的任何特殊含义 - 实际类型参数仍然IEnumerable<obj>
,但typedefof
函数调用GetGenericTypeDefinition
幕后
如果我不指出这个问题是许多问题之一,其答案可以在