我有一个FSharpOption类型的对象,但我不知道它的深度。它可能是......
FSharpOption<Int32>
FSharpOption<FSharpOption<Int32>>
FSharpOption<FSharpOption<FSharpOption<Int32>>>
FSharpOption<FSharpOption<FSharpOption<FSharpOption<Int32>>>>
etc.
编辑:另请注意,它不一定是Int32。它可以是任何基础类型。
如何使用VB或C#获得底值?
答案 0 :(得分:2)
我不禁想知道你是如何进入这种状态的。
那就是说,假设静态类型是'对象',那么我想你必须看看它的.GetType()是否是FSharpOption`1的泛型类型定义,并使用反射(或'动态')来打开一个级别再试一次......
我不清楚这是一个F#问题,因为你想在C#或VB中得到答案,并且可以询问任何Foo&lt; T&gt;的问题。类型。
所有人都说,这里有一些C#4.0代码:
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);
和一些F#代码:
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"
编辑注意我更改了它以显示策略是否有效,即使它包含除了整数之外的其他内容。
答案 1 :(得分:1)
好的,这就是我到目前为止所做的。有关改进的建议吗?
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
答案 2 :(得分:1)
这可能与版本无关......这个微小变化如何不依赖于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;
}