2012-11-25 31 views
5

我在DelegateMulticastDelegate下的Reflector中找不到+運算符。爲什麼使用Delegate.Combine需要強制轉換,但使用+運算符不需要?

我試圖弄清楚如何,這並不需要一個轉換:

Action a =() => Console.WriteLine("A"); 
Action b =() => Console.WriteLine("B"); 

Action c = a + b; 

但這:

Action a =() => Console.WriteLine("A"); 
Action b =() => Console.WriteLine("B"); 

Action c = (Action)MulticastDelegate.Combine(a, b); 

在第一個樣品只是在幕後所做的投?

回答

1

以下面的例子:

​​

然後用ILSpy看着它:

internal class Program 
{ 
    private static void Main(string[] args) 
    { 
     Program.Test1(); 
     Program.Test2(); 
    } 
    public static void Test1() 
    { 
     Action a = delegate 
     { 
      Console.WriteLine("A"); 
     }; 
     Action b = delegate 
     { 
      Console.WriteLine("B"); 
     }; 
     Action c = (Action)Delegate.Combine(a, b); 
     c(); 
    } 
    public static void Test2() 
    { 
     Action a = delegate 
     { 
      Console.WriteLine("A"); 
     }; 
     Action b = delegate 
     { 
      Console.WriteLine("B"); 
     }; 
     Action c = (Action)Delegate.Combine(a, b); 
     c(); 
    } 
} 

似乎他們做同樣的事情,只是C#是提供在第一次測試的一些語法糖。

4

+=-=在語言級別上實現(即編譯器幫助)與已知的委託類型,因此它不需要打石膏,而Delegate.Combine只是一個普通的(非通用)方法Delegate返回類型,所以它需要演員。

1

在第一個示例中是剛剛在封面下完成的演員嗎?

是的,你可以這麼說!

Combine方法是在沒有泛型C#的.NET 1中編寫的。因此的Combine正式返回類型必須是Delegate

public static Delegate Combine(Delegate a, Delegate b) 
{ 
    ... 
} 

但該方法又返回Action當兩個abAction。是的,要求ab具有相同的運行時類型。

請不要寫MulticastDelegate.Combine作爲Combine是由System.Delegate類定義的static方法。因此請說Delegate.Combine,這不太令人困惑。

迂迴:

C#的當前版本和Combine與逆變委託類型的問題。考慮以下幾點:

Action<string> doSomethingToString; // will be assigned below 

Action<ICloneable> a = cloneable => { Console.WriteLine("I'm cloning"); cloneable.Clone(); } 
Action<IConvertible> b = convertible => { Console.WriteLine("I'm converting"); convertible.ToInt32(CultureInfo.InvariantCulture); } 

Action<string> aStr = a; // OK by contravariance of Action<in T>, aStr and a reference same object 
Action<string> bStr = b; // OK by contravariance of Action<in T>, bStr and b reference same object 

doSomethingToString = aStr + bStr; // throws exception 
doSomethingToString("42");   // should first clone "42" then convert "42" to Int32 

現在,假設未來的某個框架的版本中引入的通用Combine方法:

public static TDel Combine<TDel>(TDel a, TDel b) where TDel : Delegate 
{ 
    // use typeof(TDel) to figure out type of new "sum" delegate 
} 

,並假設C#改爲使得+被翻譯成調用新的通用Combine<>方法,然後逆變和代表組合將被修復!我想他們告訴我們他們有更高的優先級,但仍然。

+1

執行財產以後會不會有每個委託類型定義了自己的靜態'Combine'方法的任何根本問題?然後,如果兩個代表'X'和'Y'都是可替代'FooDelegate'的類型,則可以使用'FooDelegate.Combine(X,Y)'。即使沒有協變問題,它看起來比'(FooDelegate)Delegate.Combine(X,Y)'更清潔,並且可以添加一個編譯時檢查'X'和'Y'是合適的。 – supercat

+0

@supercat對我來說,這聽起來像一個很好的解決方案。 –

0

它使用「操作符重載」完成,你可以在你自己的對象中做到這一點。

public class MyObject 
{ 
    public string Property { get; set; } 

    public MyObject(string property) 
    { 
     this.Property = property; 
    } 

    public static MyObject operator +(MyObject a1, MyObject a2) 
    { 
     return new MyObject(a1.Property + a2.Property); 
    } 
} 

    MyObject o1 = new MyObject("Hello"); 
    MyObject o2 = new MyObject(" World!"); 

    MyObject o3 = o1 + o2; 

結果:o3.Property =「Hello World!」

所以我假定framwork這樣的背景

public static Action operator +(Action a1, Action a2) 
    { 
     return (Action)MulticastDelegate.Combine(a1,a2); 
    } 
+0

噢,我知道運營商超載我只是無法在Reflactor中找到它,並想知道他們是如何做到的 –

相關問題