tags:

views:

114

answers:

2

I'm trying to figure out if an obj returned from a call is of a certain type. Here is my code:

type MyType<'T>= 
    val mutable myArr : array
    val mutable id : int
    val mutable value : 'T

and in some method that has MyType in scope...

let a  = someFunThatReturnsObj()   // a could be of type MyType 

How do I figure out if a is of type MyType?

+3  A: 
match a with
| :? MyType<int> as mt -> // it's a MyType<int>, use 'mt'
| _ -> // it's not

If you care about just a MyType<X> for some unknown X, then

let t = a.GetType()
if t.IsGenericType && t.GetGenericTypeDefinition() = typedefof<MyType<int>> then
    // it is
Brian
It looks like I have another issue. It appears someFunThatReturnsObj() returns 'U. Using your first suggested method, I get: "This runtime coercion or type test from type 'U to MyType<int> involves an indeterminate type based on information prior to this program point. Runtime type tests are not allowed on some types. Further type annotations are needed."
PhilBrown
Just call 'box' first, then. "match box a with..."
Brian
I'm not sure what you mean by 'box' Brian?
PhilBrown
Call the `box` function, which upcasts its argument to type `obj`.
Brian
+1  A: 

I don't think this is that simple (remember I am f# naive) consider the follwoing scenario where

1) we are using generics on multiple types 2) we don't have the type information for an object so it comes in to a function as type obj, like in some of the .NET datacontract / serialization libraries

I reworked my proposal to use reflection:

type SomeType<'A> = { 
        item : 'A 
    } 


type AnotherType<'A> = { 
    someList : 'A list 
} 

let test() = 

    let getIt() : obj =  
        let results : SomeType<AnotherType<int>> = { item = { someList = [1;2;3] }} 
        upcast results 

    let doSomething (results : obj) =  
        let resultsType = results.GetType()
        if resultsType.GetGenericTypeDefinition() = typedefof<SomeType<_>> then 
            let method = resultsType.GetMethod("get_item")
            if method <> null then
                let arr = method.Invoke(results, [||]) 
                if arr.GetType().GetGenericTypeDefinition() = typedefof<AnotherType<_>> then 
                    printfn "match" 

    getIt() |> doSomething  

Seems like there should be more natural way of doing this...

akaphenom
This is great for figuring out if results falls into my desired SomeType<AnotherType<'T>> category. The problem I still face is casting and using results as SomeType<AnotherType<System.Object>>. I have control over everything 'T could be. Can anyone suggest a way of doing this perhaps by using a common interface for all objects 'T could be? Perhaps a common superclass?
PhilBrown