Run*_* FS 39 reflection f# c#-to-f#
我有一段代码,我需要弄清楚一个给定的类型是否实现IEnumerable<T>(我不关心T)
我试过了(t:System.Type万一你想知道)
let interfaces = t.GetInterfaces()
let enumerbale =
interfaces.Any(fun t ->
t.GetGenericTypeDefinition() = typeof<IEnumerable<>>
)
Run Code Online (Sandbox Code Playgroud)
但是这不会编译(编译不喜欢<>).然后我试过了
let interfaces = t.GetInterfaces()
let enumerbale =
interfaces.Any(fun t ->
t.GetGenericTypeDefinition() = typeof<IEnumerable<'a>>
)
Run Code Online (Sandbox Code Playgroud)
但得到一个警告,'a是对obj的约束.我不想弄清楚是否IEnumerable<obj>已实施但是IEnumerabl<>.
任何人都知道解决方案,顺便也可以对上面的代码发表评论.
kvb*_*kvb 54
这应该工作:
typedefof<System.IEnumerable<_>>
Run Code Online (Sandbox Code Playgroud)
编辑
正如托马斯所说,这里的_通配符并没有什么特别之处; 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#的方法形成对比,C#的方法在类似的情况下完全正常.
至于你的代码本身,我想你也想做一些其他的改变,比如在调用之前确保接口是通用的GetGenericTypeDefinition.以下是我编写测试函数的方法:
(fun t -> t.IsGenericType && (t.GetGenericTypeDefinition() = typedefof<_ seq>))
Run Code Online (Sandbox Code Playgroud)
Tom*_*cek 21
据我所知,F#没有任何与C#相同的东西typeof(IEnumerable<>).这是因为,这是C#明确支持的特殊语法.在F#中,typeof是一个普通函数,type参数需要是一个完全指定的类型.您可以像这样以编程方式获取泛型类型定义:
let t = typeof<IEnumerable<obj>>
let genericT = t.GetGenericTypeDefinition()
Run Code Online (Sandbox Code Playgroud)
您的解决方案的问题IEnumerable<'a>是F#编译器仍然需要找到一些要使用的具体类型(因为泛型类型定义不是有效类型).如果类型推断推断出type参数不受任何限制,则使用默认类型,即obj.
编辑我不知道typedefof<IEnumerable<_>>,这是非常有用的!无论如何,请注意下划线在这里没有任何特殊含义 - 实际类型参数仍然是IEnumerable<obj>,但typedefof函数调用GetGenericTypeDefinition后面的场景.