2010-06-09 65 views
1

Possible Duplicate:
Nullable types and the ternary operator. Why won’t this work?如何在C#/ .NET 3.5中使用帶'?'的類型

這是我的代碼工作

public decimal? Get() 
{ 
    var res = ... 
    return res.Count() > 0 ? res.First() : (decimal?) null; 
} 

,這一次不起作用

public decimal? Get() 
{ 
    var res = ... 
    return res.Count() > 0 ? res.First() : null; 
} 

給編譯器錯誤:

Error 1 Type of conditional expression cannot be determined because there is no implicit conversion between 'decimal' and ' <null> '

我不知道爲什麼?有任何想法嗎?

+1

重複http://stackoverflow.com/questions/858080的Count會,因爲它擊中的第一個元素遍歷而Any所有元素,就立即停止/ nullable-types-and-the-ternary-operator-why-wont-this-work – LukeH 2010-06-09 16:09:40

+1

...和http://stackoverflow.com/questions/2450866/why-doesnt-the-conditional-operator-correctly-allow使用空分配 – LukeH 2010-06-09 16:11:07

+1

...和http://stackoverflow.com/questions/75746/conditional-operator-assignment-with-nullablevalue-types – LukeH 2010-06-09 16:11:43

回答

2

錯誤很明顯。這倆 」?」 en「:」該條件運算符的部分需要具有相同的類型或至少必須隱式轉換爲相同的類型。而一個孤獨的null沒有一個好的類型。

也許你可以使用.FirstOrDefault()。取決於你的res的類型,這將給null0m

1

我在猜res是一個小數數組,即decimal []。這是因爲您已聲明水庫這樣的:

var res = { 1.0, 2.0, 3.0 }; 

,而不是像這樣:

var res = { 1.0, 2.0, null }; 

所以沒有理由讓編譯器認爲資源是可空的小數的數組。

現在您正在使用一個三元運算符,它必須始終從兩側返回相同的(或等價的castable)類型。但是由於res.First()是一個'decimal',你的null默認是無類型的,它只是讓你的null等價於你的第一個參數(res.First(),即十進制)的類型。通過強制將null作爲可爲空的十進制類型('decimal?'),你實際上迫使編譯器將res.First()作爲一個可爲空的小數。

但是,對於您的整體更好的解決方案是這樣的:

public decimal? Get() 
{ 
    decimal?[] res = ... 
    return res.FirstOrDefault(); 
} 
+0

「更好的解決方案overalll」假設'res'包含可爲空的小數,你已經假設*不是在開始時的情況你的答案。鑑於「res」可能不包含可爲空的小數的世界,那麼「更好的整體解決方案」是不正確的。 – 2010-06-09 16:05:05

+0

偉大的一點 - 我認爲FirstOrDefault將返回一個NULL,但默認(十進制)實際上是0.0M。 – 2010-06-09 16:34:48

7

這種行爲是覆蓋在C#語言規範的第7.13節。

簡而言之,三元運算符中兩個表達式的類型必須是* compatible *,以便編譯器確定三元表達式的類型。在這種情況下所考慮的兩種類型是

  1. decimal
  2. null

decimal類型爲值類型,因此null是不可轉換到它。值null沒有關聯的類型。這可以防止編譯器確定表達式的類型並導致編譯錯誤。

在第一個例子中,第二種類型是decimal?。在decimaldecimal?之間有一個轉換,因此編譯器選擇decimal?作爲類型。

0

在第二種情況下,您可以使用res.FirstOrDefault()

IEnumerable<T>.FirstOrDefault()回報一套第一Tdefault<T>如果設置爲空:null類和對結構的一些默認值,在常見的情況 - 0

public decimal? Get() 
{ 
    var res = ... 
    return res.FirstOrDefault(); 
} 

等於

public decimal? Get() 
{ 
    var res = ... 
    return res.Count() > 0 ? res.First() : default(decimal?); 
} 
+1

無論您是否將值轉換爲「decimal?」,''decimal'列表的FirstOrDefault()'將爲0M。這提出了一個問題。 0M是不存在的值的情況還是0M是列表中的第一個值? – 2010-06-09 16:07:59

2

題外話,但...

使用Count有點毫無意義時,所有你需要知道的是序列是否有任何元素。

public decimal? Get() 
{ 
    var res = ... 
    return res.Any() ? res.First() : (decimal?)null; 
} 

或者,也許這樣的::

public decimal? Get() 
{ 
    var res = ... 
    using (var e = res.GetEnumerator()) 
    { 
     return e.MoveNext() ? e.Current : (decimal?)null; 
    } 
}