C# 11:
file class C
{
public int IntField1;
}
file struct S
{
public int IntField1;
}
file class StructureVsClassWhenCopying
{
private static void v1()
{
System.Console.WriteLine("v1");
}
private static void v2()
{
System.Console.WriteLine("v2");
}
public static void Main()
{
C c1 = new();
c1.IntField1 = 1;
C c2 = c1;
c1.IntField1 = 2;
System.Console.WriteLine(c2.IntField1); // 2, because class is a reference-type
S s1 = new();
s1.IntField1 = 1;
S s2 = s1;
s1.IntField1 = 2;
System.Console.WriteLine(s2.IntField1); // 1, because struct is a value type
string str1 = "old string";
string str2 = str1;
str1 = "new string";
System.Console.WriteLine(str2); // old string, because string is immutable
System.Action a1 = v1;
System.Action a2 = a1;
a1 -= v1;
a1 += v2;
a2.Invoke(); //v1. Why?
}
}我想知道引用类型和价值类型的复制。我已经理解了类(引用类型)、struct (值类型)和字符串(也是引用类型,但不可变)的示例。但是委托也是引用类型,为什么它的行为类似于结构和字符串?
发布于 2022-11-15 18:24:56
将a1分配给a2意味着要复制a1中包含的引用,这是对v1的引用。a2从来不包含对a1的引用。因此,改变a1没有任何影响。
System.Action a1 = v1; //a1 points to the v1 method
System.Action a2 = a1; //a2 now points to the v1 method too
a1 -= v1; //a1 points nowhere
a1 += v2; //a1 now points at the v2 method
a2.Invoke(); //a2 still points at the v1 method发布于 2022-11-15 18:26:02
因为代表们有自己的逻辑。他们是多播代表。您可以将它们看作是委托的数组(实际上,它们是这样一个数组的包装器)。也就是说,你可以增加几个代表。每次添加或删除委托时,都会得到该数组的新实例。这确保了多线程场景中的正确行为。
例如:
System.Action a1 = v1; // Equivalent to: System.Action a1 = new Action(v1);
a1 += v2;
a1(); ==> Prints "v1" and "v2";C#语言参考在19.5代表实例化一章中说
委托的实例由delegate_creation_expression (§11.7.15.6)创建,这是对委托类型的转换、委托组合或委托删除。
这相当于说它们是不可变的。
发布于 2022-11-15 18:55:34
有时候,看看实际的代码是什么样子很有帮助。
在本例中,+=和-=在Delegates上基本上是语法糖果。
这是实际的代码谢谢SharpLab
public static void Main()
{
C c = new C();
c.IntField1 = 1;
C c2 = c;
c.IntField1 = 2;
Console.WriteLine(c2.IntField1);
S s = default(S);
s.IntField1 = 1;
S s2 = s;
s.IntField1 = 2;
Console.WriteLine(s2.IntField1);
string text = "old string";
string value = text;
text = "new string";
Console.WriteLine(value);
Action action = <>O.<0>__v1 ?? (<>O.<0>__v1 = new Action(v1));
Action action2 = action;
action = (Action)Delegate.Remove(action, <>O.<0>__v1 ?? (<>O.<0>__v1 = new Action(v1)));
action = (Action)Delegate.Combine(action, <>O.<1>__v2 ?? (<>O.<1>__v2 = new Action(v2)));
action2();
}所以
a+=v;
a-=v;是
a = (Action) Delegate.Combine(a, new Action(v));
a = (Action) Delegate.Remove(a, new Action(v));Delegate.Combine和Delegate.Remove都创建了新的代理程序,而不是修改原始的。
https://stackoverflow.com/questions/74450453
复制相似问题