我有一段代码,我需要弄清楚给定类型是否实现 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幕后

如果我不指出这个问题是许多问题之一,其答案可以在

这段 C# 代码在 F# 中是什么样子?

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top