2012-11-25 28 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中找到它,并想知道他们是如何做到的 –

相关问题