假设我们有以下类型:

struct MyNullable<T> where T : struct
{
    T Value;

    public bool HasValue;

    public MyNullable(T value)
    {
        this.Value = value;
        this.HasValue = true;
    }

    public static implicit operator T(MyNullable<T> value)
    {
        return value.HasValue ? value.Value : default(T);
    }
}

并尝试编译以下代码片段:
MyNullable<int> i1 = new MyNullable<int>(1);
MyNullable<int> i2 = new MyNullable<int>(2);

int i = i1 + i2;

这样可以很好地编译并且没有错误。 i1和i2强制转换为整数并评估加法。

但是,如果我们具有以下类型:
struct Money
{
    double Amount;
    CurrencyCodes Currency; /*enum CurrencyCode { ... } */

    public Money(double amount, CurrencyCodes currency)
    {
        Amount = amount;
        Currency = currency;
    }

    public static Money operator + (Money x, Money y)
    {
        if (x.Currency != y.Currency)
            // Suppose we implemented method ConvertTo
            y = y.ConvertTo(x.Currency);

        return new Money(x.Amount + y.Amount, x.Currency);
    }
}

尝试编译另一个代码片段:
MyNullable<Money> m1 =
   new MyNullable<Money>(new Money(10, CurrenciesCode.USD));
MyNullable<Money> m2 =
   new MyNullable<Money>(new Money(20, CurrenciesCode.USD));

Money m3 = m1 + m2;

现在的问题是,为什么编译器会生成“错误CS0019:运算符'+'无法应用于类型为'MyNullable '和'MyNullable '的操作数”?

最佳答案

Marc在右边,这是C#3.0规范中的7.2.4节-二进制运算符重载分辨率。

基本上,这些步骤是:

  • 我们需要解决“X + Y”的实现,其中X和Y都是MyNullable<Money>
  • 参见7.2.5节(用户定义的候选运算符),我们最终得到一个空集,因为MyNullable<T>不会重载+。
  • 在7.2.4中,候选运算符集是+的内置二进制运算符集,即int + int,十进制+小数等。
  • 然后应用7.4.3中的重载解析规则。当我们执行MyNullable<int> + MyNullable<int>时,这是有效的,因为每个参数都隐式转换为int-但是当我们执行MyNullable<Money> + MyNullable<Money>时,它不起作用,因为Money + Money不在候选运算符集中。
  • 09-05 21:57