微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么委托不能在容器中添加带有引用的侦听器

如何解决为什么委托不能在容器中添加带有引用的侦听器

我创建了一个 字典并将委托对象添加到容器中。 并尝试将另一个侦听器方法添加到该委托中,该方法通过 Dicionary 的 TryGetValue 方法获取引用。 结果显示我们不能输出事件处理器2,为什么?

class Program
{

    public delegate void TestDelegate();
    static void Main(string[] args)
    {
        Dictionary<int,TestDelegate> delegates = new Dictionary<int,TestDelegate>();
        delegates.Add(1,() =>
        {
            Console.WriteLine("event handler 1");
        });
        if (delegates.TryGetValue(1,out TestDelegate td))
        {
            Console.WriteLine($"delegates same Reference {ReferenceEquals(td,delegates[1])}");
            td += () => Console.WriteLine("event handler 2");
        }
        delegates[1] += () => Console.WriteLine("event handler 3");
        if (delegates.TryGetValue(1,out TestDelegate td2))
        {
            td2.Invoke();
        }
    }
}

解决方法

委托是不可变的对象。 + 运算符返回一个新的委托实例,其调用列表包含两个相加的委托。

你这样做:

delegates.TryGetValue(1,out TestDelegate td);
td += () => Console.WriteLine("event handler 2");

这会将字典中对委托的引用复制到 td 中。 td += ... 然后将 td 的调用列表与您指定的新委托组合到一个新委托实例中,并将对该新委托实例的引用存储在 td 中。

因此,我们已更新 td 以指向一个新的委托实例,但尚未更新 delegates[1] 中保存的引用。当我们稍后访问 delegates[1] 以调用它时,该实例的调用列表将不包含 () => Console.WriteLine("event handler 2")


strings 类似:它们是对不可变对象的引用。考虑:

string s1 = "Hello";
string s2 = s1;
s2 += ",World";
Console.WriteLine(s1);

打印“Hello”:+ 创建了一个新的字符串实例并将其分配给 s2,但我们没有更新 s1 以引用该新的字符串实例,并且我们没有改变 s1 所指的字符串。

,

td += () => Console.WriteLine("event handler 2"); 可以扩展为:

td = td + () => Console.WriteLine("event handler 2");

所以你可以看到你只是重新分配给一个局部变量,而不是更新原始委托实例,顺便说一下是不可变的。


另一方面,当你这样做时:

delegates[1] += () => Console.WriteLine("event handler 3");

扩展为:

delegates[1] = delegates[1] + () => Console.WriteLine("event handler 3");

所以你用一个委托替换字典中的值,即原始和新处理程序的组合。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?