F# equivalent of the C# typeof(IEnumerable<>)
Solution 1
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.
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:
(fun t -> t.IsGenericType && (t.GetGenericTypeDefinition() = typedefof<_ seq>))
Solution 2
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:
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
.
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.
Solution 3
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#?
Related videos on Youtube
Rune FS
SOreadytohelp I'm a Solutions Architect with experience from a lot of different fields ranging from server monitoring, web sites, medical devices and is currently working in the financial industry. I like my work and therefor usually have quite a few sparetime projects as well. Including a couple compilers, research projects and contributions to the DCI community. More information on both can be found at my blog or on the DCI community site
Updated on February 07, 2020Comments
-
Rune FS about 4 years
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)I've tried (
t:System.Type
in case you wonder)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 butIEnumerabl<>
.Any one know's the solution and btw feel free to comment on the code above as well.