委托充当值类型

Mik*_*per 2 c# delegates

我刚刚发现一件奇怪的事情:

Action a1 = () => Console.Write("1 ");
Action a2 = () => Console.Write("2 ");
Action tmp = a1;
a1 += a2;
a2 = tmp;
Console.Write("a1:\t");
a1();   //a1:  1 2
Console.Write("\na2:\t");
a2();   //a2:  1
Console.ReadLine();
Run Code Online (Sandbox Code Playgroud)

我预计这两个语句都会返回“1 2”;为什么不是这样呢?

Mik*_*ray 9

是的,委托是引用类型。它们也是不可变的,就像 System.String 一样。这让很多人感到惊讶。想象一下您有相同的字符串代码。我认为这更清楚:

String s1 = "1 ";
String s2 = "2 ";
String stmp = s1;
s1 += s2;
s2 = stmp;
Console.WriteLine(s1);  //  1 2
Console.WriteLine(s2);  //  1
Run Code Online (Sandbox Code Playgroud)

调用+=不会改变委托的底层实例,它会生成一个新委托,并将右侧附加到新委托的调用列表中。+=实际上只是 的糖Delegate.Combine,编译器生成类似于以下的代码:

a1 = (Action)Delegate.Combine(a1, a2);
Run Code Online (Sandbox Code Playgroud)

我认为这使得我们正在创建委托的新实例变得更加明显。