从 C# 中使用 F# 可区分联合有点不雅,因为它们是如何编译的。
我认为最好的方法是定义一些成员(在 F# 端),这将简化使用 C# 中的类型。有多种选择,但我更喜欢定义TryLeft
和TryRight
行为类似的方法Int32.TryParse
(因此使用 F# API 的 C# 开发人员应该熟悉它们):
open System.Runtime.InteropServices
type Either<'a,'b> =
| Left of 'a
| Right of 'b
member x.TryLeft([<Out>] a:byref<'a>) =
match x with Left v -> a <- v; true | _ -> false
member x.TryRight([<Out>] b:byref<'b>) =
match x with Right v -> b <- v; true | _ -> false
然后您可以使用 C# 中的类型,如下所示:
int a;
string s;
if (v.TryLeft(out a)) Console.WriteLine("Number: {0}", a);
else if (v.TryRight(out s)) Console.WriteLine("String: {0}", s);
这样做会失去一些 F# 安全性,但这是在没有模式匹配的语言中所期望的。但好消息是任何熟悉 .NET 的人都应该能够使用在 F# 中实现的 API。
另一种选择是定义成员,该成员使用左/右大小写携带的值Match
接受Func<'a>
和委托并调用右委托。Func<'b>
从函数的角度来看,这更好一些,但对于 C# 调用者来说可能不太明显。