f#对应的c#类型(IEnumerable)

时间:2022-09-02 00:26:39

I have a piece of code where I need to figure out if a given type implements IEnumerable<T> (I don't care about the T)

我有一段代码,我需要弄清楚一个给定的类型是否实现了IEnumerable (我不关心T)

I've tried (t:System.Type in case you wonder)

我试着(t:系统。类型,以防你怀疑)

let interfaces = t.GetInterfaces()
let enumerbale = 
    interfaces.Any(fun t -> 
        t.GetGenericTypeDefinition() = typeof<IEnumerable<>>
    ) 

however that won't compile (the compile doesn't like the <>). I then tried

但是,这不会编译(编译不喜欢<>)。然后我试着

let interfaces = t.GetInterfaces()
let enumerbale = 
    interfaces.Any(fun t -> 
        t.GetGenericTypeDefinition() = typeof<IEnumerable<'a>>
    )

but get's a warning that 'a is constraint to obj. I Don't want to figure out if IEnumerable<obj> is implemented but IEnumerabl<>.

但是得到一个警告,a是对obj的约束。我不想算出IEnumerable 是否被执行,而是IEnumerabl<>。

Any one know's the solution and btw feel free to comment on the code above as well.

任何一个人都知道解决方案,顺便也可以对上面的代码进行评论。

3 个解决方案

#1


49  

This should work:

这应该工作:

typedefof<System.IEnumerable<_>>

EDIT

编辑

As Tomas notes, there's nothing special about the _ wildcard here; F# infers that the type obj is the most general applicable type in this context, so this is the same as using typedefof<System.IEnumerable<obj>>. In some cases the way this works can be a bit of a hindrance, though. For instance, if you define an interface type I<'a when 'a :> I<'a>> = interface end, then you can't use typedefof<I<_>>, because I<obj> doesn't satisfy the generic constraint and F# can't infer another more appropriate type. This can happen even without recursive constraints (e.g. type I<'a when 'a : struct and 'a :> System.ICloneable> = interface end. This is in contrast to C#'s approach, which works perfectly fine in the analogous cases.

正如Tomas所指出的,这里的_wildcard没什么特别的;在这个上下文中,类型obj是最通用的类型,所以这和使用typedef >是一样的。不过,在某些情况下,这种方法可能会带来一些阻碍。例如,如果你定义了一个接口类型I< a when 'a:> I< a>> = interface end,那么你就不能用typedefof >,因为我 不满足通用约束,f#不能推断出另一个更合适的类型。即使没有递归约束(例如I<'a: when 'a: struct和'a:>系统),也会发生这种情况。ICloneable > =接口。这与c#的方法形成了鲜明的对比,在类似的情况下,这种方法非常适用。 <_>

As to your code itself, I think you'll want to make some other changes, too, such as ensuring that the interface is generic before calling GetGenericTypeDefinition. Here's how I'd write the test function:

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

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

#2


17  

As far as I know, F# doesn't have any equivalent to C#'s typeof(IEnumerable<>). This is because, this is a special syntax supported explicitly by C#. In F#, typeof is a normal function and the type argument needs to be a fully specified type. You can get a generic type definition programatically like this:

据我所知,f#没有与c#的typeof(IEnumerable<>)相对应。这是因为,这是c#显式支持的特殊语法。在f#中,typeof是一个正常的函数,类型参数需要是一个完全指定的类型。你可以像这样得到一个泛型类型定义:

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

The problem with your solution with IEnumerable<'a> is that the F# compiler still needs to find some concrete type to use (as generic type definition isn't a valid type). If the type inference deduces that the type parameter isn't restricted in any way, it uses default type, which is obj.

使用IEnumerable<'a> '的解决方案的问题是,f#编译器仍然需要找到一些具体类型(作为泛型类型定义不是有效类型)。如果类型推断推断类型参数不受任何限制,则使用默认类型obj。

EDIT I didn't know about typedefof<IEnumerable<_>>, that is very useful! Anyway, note that the underscore doesn't have any special meaning here - the actual type argument is still IEnumerable<obj>, but the typedefof function calls GetGenericTypeDefinition behind the scene.

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

#3


5  

I would be remiss not to point out that this question is one of many whose answers are found in

我不应该指出,这个问题是许多人的答案之一。

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

这个c#代码在f#中是什么样子?

#1


49  

This should work:

这应该工作:

typedefof<System.IEnumerable<_>>

EDIT

编辑

As Tomas notes, there's nothing special about the _ wildcard here; F# infers that the type obj is the most general applicable type in this context, so this is the same as using typedefof<System.IEnumerable<obj>>. In some cases the way this works can be a bit of a hindrance, though. For instance, if you define an interface type I<'a when 'a :> I<'a>> = interface end, then you can't use typedefof<I<_>>, because I<obj> doesn't satisfy the generic constraint and F# can't infer another more appropriate type. This can happen even without recursive constraints (e.g. type I<'a when 'a : struct and 'a :> System.ICloneable> = interface end. This is in contrast to C#'s approach, which works perfectly fine in the analogous cases.

正如Tomas所指出的,这里的_wildcard没什么特别的;在这个上下文中,类型obj是最通用的类型,所以这和使用typedef >是一样的。不过,在某些情况下,这种方法可能会带来一些阻碍。例如,如果你定义了一个接口类型I< a when 'a:> I< a>> = interface end,那么你就不能用typedefof >,因为我 不满足通用约束,f#不能推断出另一个更合适的类型。即使没有递归约束(例如I<'a: when 'a: struct和'a:>系统),也会发生这种情况。ICloneable > =接口。这与c#的方法形成了鲜明的对比,在类似的情况下,这种方法非常适用。 <_>

As to your code itself, I think you'll want to make some other changes, too, such as ensuring that the interface is generic before calling GetGenericTypeDefinition. Here's how I'd write the test function:

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

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

#2


17  

As far as I know, F# doesn't have any equivalent to C#'s typeof(IEnumerable<>). This is because, this is a special syntax supported explicitly by C#. In F#, typeof is a normal function and the type argument needs to be a fully specified type. You can get a generic type definition programatically like this:

据我所知,f#没有与c#的typeof(IEnumerable<>)相对应。这是因为,这是c#显式支持的特殊语法。在f#中,typeof是一个正常的函数,类型参数需要是一个完全指定的类型。你可以像这样得到一个泛型类型定义:

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

The problem with your solution with IEnumerable<'a> is that the F# compiler still needs to find some concrete type to use (as generic type definition isn't a valid type). If the type inference deduces that the type parameter isn't restricted in any way, it uses default type, which is obj.

使用IEnumerable<'a> '的解决方案的问题是,f#编译器仍然需要找到一些具体类型(作为泛型类型定义不是有效类型)。如果类型推断推断类型参数不受任何限制,则使用默认类型obj。

EDIT I didn't know about typedefof<IEnumerable<_>>, that is very useful! Anyway, note that the underscore doesn't have any special meaning here - the actual type argument is still IEnumerable<obj>, but the typedefof function calls GetGenericTypeDefinition behind the scene.

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

#3


5  

I would be remiss not to point out that this question is one of many whose answers are found in

我不应该指出,这个问题是许多人的答案之一。

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

这个c#代码在f#中是什么样子?