从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#调用者来说可能不那么明显。
+1这比已接受的答案 – MattDavey
优雅得多,这个解决方案有一些限制。就像,你不能做类似'a.Match(ifLeft:x => x + 1,ifRight:_ => return null);' –