这里有一个小小的例子描述了一些单独使用委托链的局限。
知道了使事件的优势,用委托链的不足,也就更清楚了使用这样便于在设计时灵活的选择。
1) 委托链中的异常
这是能想到的最直接的问题。委托链中的委托是被顺序访问的,当其中一个出现了异常,就会打破这个链。例如上面的委托链中 heater 先被访问,然后是cooler。可能cooler是我们需要处理温度变化的对象,但在委托链在访问 heater时出了异常,cooler就无法再执行了,虽然cooler可能一点问题都没有,但它没办法执行。
2) 委托链中的返回值
假设程序需要扩展一下,在第11步和第13步需要返回值给控制端,当控制端收到第11步的返回值后,委托链并没有终止,而是继续了13步,这样最终的返回值将总是第13步的返回值。using System; using System.Collections.Generic; using System.Text; namespace delegate_bad_point { class Cooler { private float m_fTemperature; public Cooler(float fTemperature) { m_fTemperature = fTemperature; } public float Temperature { get { return m_fTemperature; } set { m_fTemperature = value;} } public void OnTemperatureChaged(float fNewTemperature) { if (fNewTemperature > m_fTemperature) { Console.WriteLine("Cooler : ON"); } else { Console.WriteLine("Cooler : OFF"); } } } class Heater { private float m_fTemperature; public Heater(float fTemperature) { m_fTemperature = fTemperature; } public float Temperature { get { return m_fTemperature; } set { m_fTemperature = value; } } public void OnTemperatureChaged(float fNewTemperature) { if (fNewTemperature < m_fTemperature) { Console.WriteLine("Heater : ON"); } else { Console.WriteLine("Heater : OFF"); } } } public class Thermostat { public delegate void TemperatureChangedHandler(float newTemperature); private TemperatureChangedHandler m_OnTemperatureChange; private float m_fCurrentTemperature; public TemperatureChangedHandler OnTemperatureChanged { get { return m_OnTemperatureChange; } set { m_OnTemperatureChange = value; } } public float CurrentTemperature { get { return m_fCurrentTemperature; } set { if (m_fCurrentTemperature != value) { m_fCurrentTemperature = value; TemperatureChangedHandler localOnChange = m_OnTemperatureChange; // check the null value, it's important if (localOnChange != null) localOnChange(value); } } } } class Program { static void Main(string[] args) { Cooler cool = new Cooler(80); Heater heat = new Heater(60); Thermostat thermostat = new Thermostat(); string strTemp = ""; thermostat.OnTemperatureChanged += heat.OnTemperatureChaged; thermostat.OnTemperatureChanged += cool.OnTemperatureChaged; Console.WriteLine("Enter temperature: "); strTemp = Console.ReadLine(); thermostat.CurrentTemperature = float.Parse(strTemp); Console.ReadKey(); } } }
下面将会使用事件方式来解决委托链中的问题。