首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >复制委托行为

复制委托行为
EN

Stack Overflow用户
提问于 2022-11-15 18:17:16
回答 3查看 44关注 0票数 0

C# 11:

代码语言:javascript
复制
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 (值类型)和字符串(也是引用类型,但不可变)的示例。但是委托也是引用类型,为什么它的行为类似于结构和字符串?

EN

回答 3

Stack Overflow用户

发布于 2022-11-15 18:24:56

a1分配给a2意味着要复制a1中包含的引用,这是对v1的引用。a2从来不包含对a1的引用。因此,改变a1没有任何影响。

代码语言:javascript
复制
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
票数 1
EN

Stack Overflow用户

发布于 2022-11-15 18:26:02

因为代表们有自己的逻辑。他们是多播代表。您可以将它们看作是委托的数组(实际上,它们是这样一个数组的包装器)。也就是说,你可以增加几个代表。每次添加或删除委托时,都会得到该数组的新实例。这确保了多线程场景中的正确行为。

例如:

代码语言:javascript
复制
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)创建,这是对委托类型的转换、委托组合或委托删除。

这相当于说它们是不可变的。

票数 1
EN

Stack Overflow用户

发布于 2022-11-15 18:55:34

有时候,看看实际的代码是什么样子很有帮助。

在本例中,+=-=Delegates上基本上是语法糖果。

这是实际的代码谢谢SharpLab

代码语言:javascript
复制
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();
}

所以

代码语言:javascript
复制
a+=v;
a-=v;

代码语言:javascript
复制
a = (Action) Delegate.Combine(a, new Action(v));
a = (Action) Delegate.Remove(a, new Action(v));

Delegate.CombineDelegate.Remove都创建了新的代理程序,而不是修改原始的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74450453

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档