内置的“&lt;&gt;比较”不适用于“IComparable <t>”?</t>

时间:2012-10-05 11:00:27

标签: f# comparison

我有一个被歧视的联盟,我希望使用像> < 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那样强制转换,我认为这会耗费时间

3 个答案:

答案 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#编写了这个例子。