簡體   English   中英

為什么C#編譯器不調用隱式轉換運算符?

[英]Why C# compiler doesn't call implicit cast operator?

假設我們有以下類型:

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 <Money>'和'MyNullable <Money>'類型的操作數 ?”

這是一個有趣的問題......例如,它適用於Decimal ,但不適用於TimeSpan ,它們都是正確的.NET類型(與原始類型的float等不同)並且都有+運算符。 好奇!

當然,你可以扭動手臂:

Money m3 = (Money)m1 + (Money)m2;

而你只需使用Nullable<T>它就可以免費工作 - 當然 - 加上你獲得編譯器+運行時(拳擊)支持。 有沒有理由不在這里使用Nullable<T>

我會看看規格; 在此期間,您可能會考慮將運營商推廣到MyNullable<T> ; 使用常規Nullable<T> ,C#編譯器為類型支持的那些提供“提升”運算符,但是你不能自己做。 您可以做的最好的是提供所有明顯的,並希望類型支持它;-p要訪問具有泛型的運算符,請參閱此處 ,可在此處免費下載。

請注意,您可能希望應用適當的“提升”檢查 - 即

x + y => (x.HasValue && y.HasValue)
          ? new MyNullable<T>(x.Value + y.Value)
          : new MyNullable<T>();

更新

不同的處理看起來與14.7.4(ECMA 334 v4)“加法運算符”有關,其中它是為包括十進制在內的一系列類型預先定義的(因此這對我來說是一次糟糕的測試),因為14.2.4(相同)“二元運算符重載分辨率”,預定義運算符確實得到特別提及。 不過,我並沒有聲稱完全理解它。

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不在候選運營商的集合中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM