使用 < 和 > 运算符时支持哪些隐式转换?

What implicit conversions are supported when using < and > operators?

我有一个结构:

public struct Decibel
{
    public readonly double Value;

    public Decibel (double value)
    {
        Value = value;
    }

    public static implicit operator Decibel (double decibels)
    {
        return new Decibel (decibels);
    }

    public static implicit operator double (Decibel decibels)
    {
        return decibels.Value;
    }
}

现在我可以做到:

bool x = new Decibel (0) < new Decibel (1);

编译器似乎很聪明,可以将Decibel转换为double,然后使用<运算符进行双精度运算?

我有不同的 struct 命名为 Duration,它正在包装 TimeSpan。它对 TimeSpan to/from Duration 进行了隐式转换,但 <> 运算符对其不起作用。

c#是否只识别原始类型之间的转换?

首先请注意,C# 最多允许在类型之间进行一次隐式用户定义转换。

因此,当您比较 Decibel 的两个实例时,编译器发现它可以使用用户定义的隐式转换将 Decibel 转换为 double 以进行比较.

然而,当您比较 Duration 的两个实例时,编译器无法找到任何可以用来进行比较的 单一 隐式转换。对于可以隐式转换为的任何类型,编译器不会考虑任何用户定义的比较运算符。它只会为类型可以隐式转换为的任何类型寻找内置比较运算符。

因此,即使 TimeSpan 提供了理论上可以使用的用户定义比较运算符,编译器也不会使用隐式转换为 TimeSpan

另请注意,即使 TimeSpan class 提供了到 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) ...