Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/274.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何构建委托调用列表?_C#_Delegates - Fatal编程技术网

C# 如何构建委托调用列表?

C# 如何构建委托调用列表?,c#,delegates,C#,Delegates,我试图了解组合代理是如何工作的。在下面的代码中,我将set的常规实现(通过使用=运算符进行简单赋值)更改为格式错误的实现(通过使用+=运算符) 因此,以下代码: using System; using System.Linq; class Cooler { public void OnTemperatureChanged(float newTemperature) {} } class Heater { public void OnTemperatureChanged(flo

我试图了解组合代理是如何工作的。在下面的代码中,我将
set
的常规实现(通过使用
=
运算符进行简单赋值)更改为格式错误的实现(通过使用
+=
运算符)

因此,以下代码:

using System;
using System.Linq;

class Cooler
{
    public void OnTemperatureChanged(float newTemperature) {}
}

class Heater
{
    public void OnTemperatureChanged(float newTemperature) {}
}

public class Thermostat
{
    private Action<float> _OnTemperatureChange;

    public Action<float> OnTemperatureChange
    {
        get
        { return _OnTemperatureChange; }
        set
        {
            _OnTemperatureChange += value; // note the += 
        }
    }

    public void PrintRegistered()
    {
        if (OnTemperatureChange != null)
        {
            foreach (Delegate existingHandler in _OnTemperatureChange.GetInvocationList())
            {
                Console.WriteLine(existingHandler.Target + "." + existingHandler.Method);
            }
        }
    }
}

class Program
{
    public static void Main()
    {
        Thermostat thermostat = new Thermostat();
        Heater heater = new Heater();
        Cooler cooler = new Cooler();

        thermostat.OnTemperatureChange += cooler.OnTemperatureChanged;
        thermostat.OnTemperatureChange += heater.OnTemperatureChanged;
        thermostat.PrintRegistered();
    }
}
当然,如果我将
设置
更改回其常规实现,我们将看到
冷却器
加热器
的单个
温度更改


我想了解为什么以这种方式设置委托会产生这种形式的调用列表

+=
代表调用
Delegate.Combine
<代码>恒温器.OnTemperatureChange+=冷却器.OnTemperatureChange
调用此函数两次:一次在
Main
中,一次在
set\u OnTemperatureChange
中。所以这是一个老生常谈的错误,会导致两次副作用

恒温器.OnTemperatureChange+=冷却器.OnTemperatureChange
添加
冷却器

恒温器.OnTemperatureChange+=加热器.OnTemperatureChange
接受
冷却器
,将其转换为
冷却器、加热器
,然后调用
设置
,该设置与旧值组合,使其成为
冷却器、冷却器、加热器

我承认我觉得这很不直观,但这是因为一个陈腐的错误

添加第三条加热器管路会导致:

Cooler.Void OnTemperatureChanged(Single)
Cooler.Void OnTemperatureChanged(Single)
Heater.Void OnTemperatureChanged(Single)
Cooler.Void OnTemperatureChanged(Single)
Cooler.Void OnTemperatureChanged(Single)
Heater.Void OnTemperatureChanged(Single)
Heater.Void OnTemperatureChanged(Single)
Cooler.Void OnTemperatureChanged(Single)
Cooler.Void OnTemperatureChanged(Single)
Heater.Void OnTemperatureChanged(Single)
Cooler.Void OnTemperatureChanged(Single)
Cooler.Void OnTemperatureChanged(Single)
Heater.Void OnTemperatureChanged(Single)
Heater.Void OnTemperatureChanged(Single)
Cooler.Void OnTemperatureChanged(Single)
Cooler.Void OnTemperatureChanged(Single)
Heater.Void OnTemperatureChanged(Single)
Cooler.Void OnTemperatureChanged(Single)
Cooler.Void OnTemperatureChanged(Single)
Heater.Void OnTemperatureChanged(Single)
Heater.Void OnTemperatureChanged(Single)
Heater.Void OnTemperatureChanged(Single)
添加另一条加热器管路会导致:

Cooler.Void OnTemperatureChanged(Single)
Cooler.Void OnTemperatureChanged(Single)
Heater.Void OnTemperatureChanged(Single)
Cooler.Void OnTemperatureChanged(Single)
Cooler.Void OnTemperatureChanged(Single)
Heater.Void OnTemperatureChanged(Single)
Heater.Void OnTemperatureChanged(Single)
Cooler.Void OnTemperatureChanged(Single)
Cooler.Void OnTemperatureChanged(Single)
Heater.Void OnTemperatureChanged(Single)
Cooler.Void OnTemperatureChanged(Single)
Cooler.Void OnTemperatureChanged(Single)
Heater.Void OnTemperatureChanged(Single)
Heater.Void OnTemperatureChanged(Single)
Cooler.Void OnTemperatureChanged(Single)
Cooler.Void OnTemperatureChanged(Single)
Heater.Void OnTemperatureChanged(Single)
Cooler.Void OnTemperatureChanged(Single)
Cooler.Void OnTemperatureChanged(Single)
Heater.Void OnTemperatureChanged(Single)
Heater.Void OnTemperatureChanged(Single)
Heater.Void OnTemperatureChanged(Single)
它总是保持相同的前缀,相同的前缀再次出现,然后是加热器


如果需要建议:使用
温度变化事件操作这就消失了。

为什么不在这里使用事件?这正是场景事件的设计目的。Helter Skeleter是一个不错的插曲。谢谢。您能否详细说明为什么使用
事件
可以消除这种情况?
操作符+=
对事件调用
添加
访问器。它本身并不合并代理。我主要建议使用事件,因为它更好地捕捉您的意图。这个bug可以通过多种方式删除,事件只是一个。