F# equivalent of the C# typeof(IEnumerable<>)

18,530

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#?

Share:
18,530

Related videos on Youtube

Rune FS
Author by

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, 2020

Comments

  • Rune FS
    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 but IEnumerabl<>.

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

Related