Luka Horvat
Luka Horvat

Reputation: 4412

Casting an object to a generic type without supplying the parameters

Say I have a code like this

let a = new List<int>()
let b = a :> obj :?> List<obj>

It throws an exception saying that it can't do it since one is List<int> while I'm trying to make it an List<obj>. I understand why that's a problem. It can't just magically create an interface for me that replaces all int types with obj, but what CAN I do here?

I have an object and I know that's it's a List of something. How can I access the elements and just not care about their type?

My concrete example doesn't use Lists so I require a general, not a List specific, solution.

Upvotes: 4

Views: 654

Answers (1)

desco
desco

Reputation: 16782

In case of lists you can use System.Collections.IList to access elements

open System.Collections
open System.Collections.Generic

let x = List<int>()
let y: IList = downcast (x :> obj)

This approach can also be generalized: make your generic classes implement non-generic interface:

type IT = 
    abstract Value: obj

type T<'a>(a: 'a) = 
    member val Value = a;
    interface IT with
        member this.Value = upcast this.Value

If this is not an option (i.e. because you cannot make changes in classes) you can always resort to reflection

type T<'a>(a: 'a) = 
    member val Value = a;

type Action = 
    static member Do(a: T<_>) = printfn "%A" a.Value

let v = T(10)
let mi = typeof<Action>.GetMethod("Do").MakeGenericMethod(v.GetType().GetGenericArguments().[0])
mi.Invoke(null, [|v|])

Upvotes: 4

Related Questions