2011-08-16 53 views
8

當設置Action<T>值時,我遇到了這個帶有條件語句的奇怪問題。這並不是說我不知道​​如何解決這個問題,因爲使用正常的if可以很容易地解決這個問題。條件聲明,通用代理不必要的轉換

這裏是我的問題:

public class Test 
{ 
    public bool Foo { get; set; } 
    public Action<bool> Action { get; set; } 

    public void A() 
    { 
     Action = Foo ? B : C;//Gives compiler error 
    } 

    public void B(bool value) 
    { 

    } 

    public void C(bool value) 
    { 

    } 
} 

這給了我一個編譯器錯誤與消息

有「方法組」和「方法組」之間不存在隱式轉換。

這是奇怪的,因爲我不明白爲什麼這將是非法的。

順便說一句,下面的語法將使這一有效(從視編譯點):

public void A() 
    { 
     Action = Foo ? (Action<bool>) B : C; 
    } 

因此,也許你可以讀出了一個問題,爲什麼是必要的投?

回答

2

您正在合併兩個相似的概念:

A)方法組。方法組是一個或多個具有相同名稱的C#方法。這是一個主要由編譯器使用的抽象;你不能傳遞一個方法組。你可以用方法組完成所有的工作,就是調用它或者創建一個委託。如果類型簽名匹配,您可以隱式地從方法組創建委託。

B)代表。你知道一個代表是什麼;它有一個特定的類型簽名,並直接指向一種方法。除了調用它之外,您還可以將它作爲第一類對象來處理。

因此,在第一個示例中,表達式返回一側的方法組B,另一側返回另一個方法組C。三元運算符需要在兩邊都返回相同的類型,但它不知道向哪一方投擲什麼;您將結果分配給(Action<bool>)的變量類型不會確定表達式的類型。所以這是不明確的。

在第二個示例中,您合法地將方法組B轉換爲三元運算符一側的Action<bool>委託。在試圖消除表達歧義的過程中,編譯器試圖將每一邊都轉換爲另一邊的類型。它可以成功將方法組C轉換爲Action<bool>,因此它可以這樣做,並且表達式是合法的。

-1

一個Action是一個特定的委託類,並且不存在從具有類似簽名的常規委託可用的/可轉換的impicit轉換。

+0

我認爲c#編譯器足夠聰明來檢查... –

1

因爲BC實際上並不是代表。他們是方法組,他們可以被隱式轉換爲代表(特別是Action<bool>),但這不是一回事。

的類型,條件表達式必須是兩個分支一致,並且由於BC目前方法組(未類型化,)編譯器不能斷定類型應該是什麼。正如它告訴你的,它們之間沒有隱含的轉換。

同時,它不能(或至少)查看賦值操作符的另一邊,說:「哦,應該是Action<bool>」。

當添加鑄造,左分支表達式的類型變得Action<bool>,且有在另一側的方法組和該委託,所以編譯器之間的隱式轉換爲再次開心:類型整個表達式是Action<bool>

0

我認爲,Eric will again tell me, that my reasoning is slightly incorrect,但我會試試看無論如何,希望他改正:-)

方法組,例如B,沒有一個類型,它是不是一個對象(B.GetType()不會編譯)。
它可以很容易地轉換成一個類型,這就是爲什麼存在隱式轉換。 樣品:

Action<bool> a = B; // implicit cast taking place. 

然而,正如你可以在鏈接的問題看,三元表達式會找到一個返回類型的表達式匹配的兩個部分。它不知道以後應該發生轉換爲Action<bool>。因爲方法組本身沒有類型,所以它們之間不存在任何轉換,並且B不能轉換爲C,因此編譯器會抱怨這一點。

通過將三元表達式的任何部分轉換爲Action<bool>,您告訴編譯器,返回類型應該是該類型,並檢查三元表達式的其他部分是否支持對該類型的隱式轉換。因爲這種情況,代碼將被編譯。