How do I unwrap an FSharpOption of unknown depth?
I have an object of type FSharpOption, but I don't know it's depth. It could be any of...
FSharpOption<Int32>
FSharpOption<FSharpOption<Int32>>
FSharpOption<FSharpOption<FSharpOption<Int32>>>
FSharpOption<FSharpOption<FSharpOption<FSharpOption<Int32>>>>
etc.
Edit: Also no开发者_StackOverflow中文版te that it isn't necessarily an Int32. It could be any underlying type.
How do I get at the underling value using VB or C#?
I can't help but wonder how you got into this state in the first place.
That said, assuming the static type is 'object', then I guess you'll have to see if its .GetType() is the generic type definition of FSharpOption`1, and use reflection (or 'dynamic') to unwrap one level and try again...
I am unclear how this is an F# question, since you want the answer in C# or VB, and the same question could be asked of any Foo<T> type.
That all said, here's some C# 4.0 code:
object o = FS.Foo.F(3);
while (o.GetType().IsGenericType &&
o.GetType().GetGenericTypeDefinition() ==
typeof(Microsoft.FSharp.Core.FSharpOption<>))
{
dynamic d = o;
o = d.Value;
}
Console.WriteLine(o);
and some F# code:
namespace FS
type Foo() =
static member F x =
match x with
| 1 -> Some 42 |> box
| 2 -> Some(Some "forty-two") |> box
| 3 -> Some(Some(Some 42)) |> box
| _ -> failwith "no"
EDIT note that I changed it to show the strategy works even if it contains things other than just ints.
That may not be version independent... how about this minor variation with no dependency on FSharp.Core?
static object OptionGetUnderlyingValue(object obj)
{
while (obj != null && obj.GetType().Name == "FSharpOption`1")
{
PropertyInfo pi = obj.GetType().GetProperty("Value");
Contract.Assert(pi != null);
obj = pi.GetValue(obj, null);
}
return obj;
}
Ok, so this is what I have so far. Any suggestions on improving it?
Option Strict Off
Imports Microsoft.FSharp.Core
Public Module FSharpInterop
Public Function OptionGetUnderlyingValue(ByVal value As Object) As Object
If value Is Nothing Then Return Nothing
Dim temp = value
Do While temp.GetType.Name = "FSharpOption`1"
temp = OptionModule.GetValue(temp)
If temp Is Nothing Then Return Nothing
Loop
Return temp
End Function
End Module
精彩评论