【问题标题】:F# equivalent of the C# typeof(IEnumerable<>)F# 等效于 C# typeof(IEnumerable<>)
【发布时间】:2011-01-29 15:08:03
【问题描述】:

我有一段代码需要确定给定类型是否实现 IEnumerable&lt;T&gt;(我不关心 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&lt;obj&gt; 是否已实现但IEnumerabl&lt;&gt;

任何人都知道解决方案,顺便说一句,也可以对上面的代码发表评论。

【问题讨论】:

标签: reflection f# c#-to-f#


【解决方案1】:

这应该可行:

typedefof<System.IEnumerable<_>>

编辑

正如 Tomas 所说,_ 通配符在这里没有什么特别之处; F# 推断obj 类型是此上下文中最普遍适用的类型,因此这与使用typedefof&lt;System.IEnumerable&lt;obj&gt;&gt; 相同。但是,在某些情况下,这种工作方式可能会有点障碍。例如,如果你定义了一个接口type I&lt;'a when 'a :&gt; I&lt;'a&gt;&gt; = interface end,那么你就不能使用typedefof&lt;I&lt;_&gt;&gt;,因为I&lt;obj&gt; 不满足泛型约束并且F# 不能推断出另一个更合适的类型。即使没有递归约束(例如type I&lt;'a when 'a : struct and 'a :&gt; System.ICloneable&gt; = interface end)也可能发生这种情况。这与 C# 的方法形成对比,后者在类似情况下工作得非常好。

至于您的代码本身,我认为您还需要进行一些其他更改,例如在调用GetGenericTypeDefinition 之前确保接口是通用的。下面是我如何编写测试函数:

(fun t -> t.IsGenericType && (t.GetGenericTypeDefinition() = typedefof<_ seq>))

【讨论】:

  • 您的解决方案使我摆脱了另一个问题 :) 没有那么有用的错误消息“由于对象的当前状态而不受支持”,这是一种说法,不能在非泛型类型上调用 getgenerictypedefinition
  • 如果泛型类型受到限制,这将变得非常丑陋。在我的例子中,约束是when 'T: struct and 'T :&gt; Enum,所以编译器抱怨_Error FS0071 Type constraint mismatch when applying the default type 'int' for a type inference variable. The type 'int' is not compatible with the type 'Enum' Consider adding further type constraints.
【解决方案2】:

据我所知,F# 没有任何等同于 C# 的typeof(IEnumerable&lt;&gt;)。这是因为,这是 C# 明确支持的特殊语法。在 F# 中,typeof 是一个普通函数,类型参数需要是完全指定的类型。您可以像这样以编程方式获得泛型类型定义:

let t = typeof<IEnumerable<obj>>
let genericT = t.GetGenericTypeDefinition()

IEnumerable&lt;'a&gt; 解决方案的问题在于 F# 编译器仍然需要找到一些具体的类型来使用(因为泛型类型定义不是有效类型)。如果类型推断推断类型参数不受任何限制,则使用默认类型,即obj

编辑我不知道typedefof&lt;IEnumerable&lt;_&gt;&gt;,这非常有用!无论如何,请注意下划线在这里没有任何特殊含义——实际的类型参数仍然是IEnumerable&lt;obj&gt;,但typedefof函数在后台调用GetGenericTypeDefinition

【讨论】:

  • 感谢您对_的澄清
【解决方案3】:

如果我没有指出这个问题是众多答案之一,那我就失职了

What does this C# code look like in F#?

【讨论】:

    猜你喜欢
    • 2020-05-02
    • 1970-01-01
    • 2017-05-01
    • 1970-01-01
    • 2019-07-06
    • 1970-01-01
    • 1970-01-01
    • 2013-02-18
    • 2014-02-28
    相关资源
    最近更新 更多