5

的比較方法給定兩個實現:條件運算符和比較代表

// compares by Key... 
private static int CompareByKey(KeyValuePair<int, string> x, KeyValuePair<int, string> y) 

{ 
    return x.Key.CompareTo(y.Key); 
} 

// compares by Value... 
private static int CompareByValue(KeyValuePair<int, string> x, KeyValuePair<int, string> y) 
{ 
    return x.Value.CompareTo(y.Value); 
} 

爲什麼不以下條件運算碼塊編譯:

Comparison<KeyValuePair<int, string>> sortMethod; 
sortMethod = isSortByActualValue ? CompareByKey : CompareByValue; 

編譯錯誤:「條件表達式類型不能因爲「方法組」和「方法組」之間沒有隱式轉換「

但是,等效代碼塊使用if-else d OES沒有任何問題:

Comparison<KeyValuePair<int, string>> sortMethod; 
if (isSortByActualValue) 
    sortMethod = CompareByKey; 
else 
    sortMethod = CompareByValue; 

(都好於上述兩個任務)

如此做有條件的經營者,如果我投的比較委託:

Comparison<KeyValuePair<int, string>> sortMethod; 
sortMethod = isSortByActualValue ? (Comparison<KeyValuePair<int, string>>) CompareByKey : CompareByValue; 

(都好於上面的作業,即使只是在真實的部分施放)

+2

如何定義CompareByAcutalValue和CompareByDisplayValue?您只顯示CompareByKey和CompareByValue的定義。 – 2012-02-28 19:30:37

+0

我發佈的代碼片段是爲了清晰起見而編輯的。我沒有意識到我只是部分改變了方法的名稱。感謝Eric,我已經將CompareByActualValue的所有引用更新爲CompareByKey(並將CompareByDisplayValue更新爲CompareByValue)。 – Arun 2012-02-28 19:42:23

回答

7

Th錯誤方法實際上說這一切,但它不是很直觀。如果您在不調用方法的情況下使用方法名稱,則您正在處理方法組。 「組」,因爲一個方法可能被重載,並且該名稱可以指示任何重載的方法。

現在,方法組可隱式轉換爲具有匹配簽名的委託,這就是爲什麼您的作業在if工作。

到目前爲止,這麼好。但是,條件運算符?:需要推導出其第二個和第三個參數可以隱式轉換的通用類型,並且它不考慮所有轉換(這會產生各種問題)。它只是看兩個論點是否具有相同的類型,或者是否可以隱式轉換爲另一個。

這不是這裏的情況:儘管這兩個參數是方法組,它們實際上是與不同類型不同方法組,你不能將一個方法組到另一個。即使兩者都可以很容易地轉換成一個委託,編譯器禁止這種用法。

這同樣適用於其他類型的真實,順便說一句:

object = someBool ? "" : New List<Integer>(); 

也無法編譯,出於同樣的原因。再次,我們可以通過明確鑄造其中一個參數,以一個共同的基本類型此編譯:

object = someBool ? (object) "" : New List<Integer>(); 
+1

+1,但我會改變「需要推斷它的第二和第三個參數的類型」爲「需要推導出一個通用類型,其第二個和第三個參數可以被隱式轉換」 – phoog 2012-02-28 19:50:20

+0

那麼爲什麼不'isSortByActualValue ? CompareByKey:CompareByKey'編譯?他們不是同一個方法組嗎? – svick 2012-02-28 19:56:11

+0

@svick無論方法組如何,都不存在從方法組到方法組的轉換。我應該做得更清楚一點,這是一個相當特殊的情況,因爲沒有普通的類型沒有這種轉換。我不知道C#規範中是如何精確描述的。 – 2012-02-28 20:00:15

3

如果你有一個像你CompareByKey的表達,它不具有任何特定的.NET類型,但一個特殊類型的「方法組」。這是因爲你可能有幾種方法叫做CompareByKey,你不知道你想要哪一種(即使你只有一種方法,它也是一樣的)。另外,您還不清楚代理類型是什麼,例如Comparison<KeyValuePair<int, string>>Func<KeyValuePair<int, string>, int>

你可以用方法組做什麼?您可以使用它們明確創建委託(new Comparison<KeyValuePair<int, string>>(CompareByKey)),並且它們也可以隱式轉換爲委託。這就是您的if版本正常工作的原因。

那麼,這與你的問題有什麼關係?當你有一個條件運算符時,編譯器必須找出整個表達式的類型,並且它不能使用你分配給它的變量的類型(這不是C#中的類型推理的工作方式)。由於這兩個表達式都是方法組,並且方法組被視爲不同類型,彼此之間沒有隱式轉換,所以無法確定整個表達式的類型。這就是你得到錯誤的原因。

您已經找到了一個修復:要麼不使用條件運算符,要麼通過使用轉換(或委託構造函數)明確指定其中一個操作數的類型。