使用C#中的F#Discriminated Unions的最佳方法是什么?
我一直在深入研究这个问题,我可能找到了最简单的方法,但由于它相当复杂,可能还有其他一些我看不到的东西......
有一个有区别的联盟,例如:
type Shape =
| Rectangle of float * float
| Circle of float
Run Code Online (Sandbox Code Playgroud)
我发现C#的用法是(避免使用变量,使类型明显):
Shape circle = Shape.NewCircle(5.0);
if (circle.IsCircle)
{
Shape.Circle c = (Shape.Circle)circle;
double radius = c.Item;
}
Run Code Online (Sandbox Code Playgroud)
在C#中,NewXXXX
静态方法总是创建Shape
类的对象,还有一种方法IsXXXX
来检查对象是否属于该类型; 当且仅当它是,它可以转换为Shape.XXXX
类,并且只有它的项目可访问; Shape.XXXX
类的构造函数是内部的,即无法访问.
有人知道从一个受歧视的联盟获取数据的更简单的选择吗?
Tom*_*cek 13
如果您正在使用F#编写一个向C#开发人员公开的库,那么C#开发人员应该能够在不了解F#的情况下使用它(并且不知道它是用F#编写的).这也是F#设计指南的推荐.
对于受歧视的工会,这很棘手,因为它们遵循与C#不同的设计原则.因此,我可能会隐藏F#代码中的所有处理功能(如计算区域)并将其作为普通成员公开.
如果你真的需要将这两个案例暴露给C#开发人员,那么我觉得这样的东西对于一个简单的歧视联盟来说是一个不错的选择:
type Shape =
| Rectangle of float * float
| Circle of float
member x.TryRectangle(width:float byref, height:float byref) =
match x with
| Rectangle(w, h) -> width <- w; height <- h; true
| _ -> false
member x.TryCircle(radius:float byref) =
match x with
| Circle(r) -> radius <- r; true
| _ -> false
Run Code Online (Sandbox Code Playgroud)
在C#中,您可以像熟悉的TryParse
方法一样使用它:
int w, h, r;
if (shape.TryRectangle(out w, out h)) {
// Code for rectangle
} else if (shape.TryCircle(out r)) {
// Code for circle
}
Run Code Online (Sandbox Code Playgroud)
根据F#规范,唯一可用的互操作是通过以下实例方法
.IsC...
.Tag
(给每个案例一个整数标签)
.Item
(在子类型上获取数据 - 仅当存在多个联合案例时才会出现此情况)但是,您可以自由地在F#中编写方法以使interop更容易.