首先请注意,C#最多允许一种类型之间的隐式用户定义转换。
因此,当您比较两个
Decibel
实例时,编译器会看到它可以使用用户定义的隐式转换将
Decibel
转换为
double
来进行比较。
然而,当您比较两个
Duration
实例时,编译器找不到任何单个隐式转换可用于允许比较。编译器不会考虑任何类型的用户定义比较运算符,这些类型可以隐式转换为该类型。它只会查找可以将类型隐式转换为其任何类型的内置比较运算符。
因此,即使
TimeSpan
提供了一个理论上可以使用的用户定义比较运算符,编译器也不会使用隐式转换为
TimeSpan
,并且即使
TimeSpan
类提供了隐式转换为
double
,编译器也不会使用它,因为它最多只会考虑一种链式隐式转换中的一种用户定义转换。
换句话说,给定以下结构:
public struct Number
{
public readonly double Value;
public Number(double value)
{
Value = value;
}
public static implicit operator Number(double duration)
{
return new Number(duration);
}
public static implicit operator double(Number number)
{
return number.Value;
}
}
public struct NumberWrapper
{
public readonly Number Value;
public NumberWrapper(Number value)
{
Value = value;
}
public static implicit operator NumberWrapper(Number duration)
{
return new NumberWrapper(duration);
}
public static implicit operator Number(NumberWrapper number)
{
return number.Value;
}
}
这段代码将会被编译:
bool x = new Number(1) < new Number(2);
当然,这也会发生变化:
Number n1 = new NumberWrapper(1);
Number n2 = new NumberWrapper(2);
bool z = n1 < n2;
但这个不会:
bool y = new NumberWrapper(1) < new NumberWrapper(2);
因为NumberWrapper
没有对任何支持<
的类型进行隐式转换,所以需要进行进一步的隐式转换。
请注意,所有原始数值和枚举类型(例如char、short、int、long、float、double、decimal、enum)都提供内置比较运算符。所有其他类型都只能提供用户定义的比较运算符。
用户定义的比较运算符应该像这样:
public static bool operator < (MyType lhs, MyType rhs) ...