我在Delegate
或MulticastDelegate
下的Reflector中找不到+运算符。
我正在试图弄清楚这不需要演员:
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);
在第一个样本中是刚刚在封面下完成的演员吗?
答案 0 :(得分:5)
+=
和-=
在语言级别(即使用编译器帮助)实现,具有已知的委托类型,因此它不需要强制转换,而Delegate.Combine
只是普通的具有Delegate
返回类型的(非泛型)方法,因此需要强制转换。
答案 1 :(得分:1)
在第一个样本中是刚刚在封面下完成的演员吗?
是的,你可以这么说!
{1}}方法是用.NET 1编写的,其中不存在通用的C#。因此,Combine
的正式返回类型必须是Combine
:
Delegate
但当public static Delegate Combine(Delegate a, Delegate b)
{
...
}
和Action
都为a
时,该方法仍会返回b
。是的,Action
和a
需要具有相同的运行时类型。
请不要写b
,因为MulticastDelegate.Combine
是Combine
类定义的static
方法。因此请说System.Delegate
,这不那么令人困惑。
<强>迂回:强>
当前版本的C#和Delegate.Combine
存在逆变委托类型的问题。请考虑以下事项:
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
并假设C#已更改,以致public static TDel Combine<TDel>(TDel a, TDel b) where TDel : Delegate
{
// use typeof(TDel) to figure out type of new "sum" delegate
}
被转换为对新通用+
方法的调用,然后逆向和委托组合将被修复!我猜他们告诉我们他们有更高的优先级,但仍然。
答案 2 :(得分:1)
采用以下示例:
class Program
{
static void Main(string[] args)
{
Test1();
Test2();
}
public static void Test1()
{
Action a = () => Console.WriteLine("A");
Action b = () => Console.WriteLine("B");
Action c = a + b;
c();
}
public static void Test2()
{
Action a = () => Console.WriteLine("A");
Action b = () => Console.WriteLine("B");
Action c = (Action)MulticastDelegate.Combine(a, b);
c();
}
}
然后用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#在第一次测试中提供了一些语法糖。
答案 3 :(得分: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!”
所以我假设框架在后台执行这样的事情
public static Action operator +(Action a1, Action a2)
{
return (Action)MulticastDelegate.Combine(a1,a2);
}