我有一个被歧视的联盟,我希望使用像> < compare max
这样的内置运算符。
[<CustomComparison>]
type SymbolType =
| A
| B
| C
| D
interface IComparable<SymbolType> with
member x.CompareTo y =
match x, y with
| A, A-> 0
| A, _ -> 1
| _, A-> -1
| _, _ -> 0
我知道我可以使用IComparable
,但后来我必须进行null
检查,更糟糕的是我必须像(SymbolType) y
那样强制转换,我认为这会耗费时间
答案 0 :(得分:3)
您已经在该类型上使用标准比较运算符。内置实现使用各个案例的声明顺序,因此:
type SymbolType = A | B | C | D
// Behavior of built-in comparison
A < B = true
D <= C = false
max B D = D
这看起来非常脆弱,所以也许这不是最好的依赖。如果您的案例不包含其他值,则可以使用 enum 而不是区分联合并定义您希望的顺序:
type SymbolType =
| A = 1
| B = 2
| C = 4
| D = 3
// The order is now defined by your code
SymbolType.C < SymbolType.D = false
答案 1 :(得分:1)
您可以使用精简包装器实现所需的方法:
[<CustomComparison>]
[<CustomEquality>]
type SymbolType =
| A
| B
| C
| D
override x.Equals y =
match y with
| :? SymbolType as t -> (((x :> IComparable<_>).CompareTo) t)=0
| _ -> false
interface IComparable with
member x.CompareTo y =
match y with
| :? SymbolType as t -> ((x :> IComparable<_>).CompareTo) t
| _ -> failwith "bad comparison"
interface IComparable<SymbolType> with
member x.CompareTo y =
match x, y with
| A, A-> 0
| A, _ -> 1
| _, A-> -1
| _, _ -> 0
这样可以避免任何重复输入。
答案 2 :(得分:0)
在CLR上,运算符是静态函数,因此您无法在接口中定义它们。但是,如果将接口用作泛型函数的类型参数的约束,也可以避免装箱。
int Compare<T>(T lhs, T rhs) where T : IComparable<T>
{
return lhs.CompareTo(rhs) // no boxing
}
抱歉,我不熟悉F#,所以我用C#编写了这个例子。