c#中多播委托的执行顺序

时间:2014-06-30 07:14:59

标签: c# delegates

我读了那个

  

如果您正在使用多播代理,您应该知道   将调用链接到同一委托的方法的顺序是   正式未定义。因此,您应该避免编写代码   依赖于以任何特定顺序调用的此类方法。

但是当我尝试使用这段代码时

using System;
namespace Wrox.ProCSharp.Delegates
{
    class Program
    {
        static void One()
        {
            Console.WriteLine("watch when i occur");
            throw new Exception("Error in watching");
        }
        static void Two()
        {
            Console.WriteLine("count");
        }
        static void Three()
        {
            Console.WriteLine("great");
        }
        static void Main()
        {
            Action d1 = Two;
            d1+=Two;
            d1+=Two;
            d1+=Two;
            d1+=One;
            d1+=Three;
            d1+=Three;
            d1+=Three;

            Delegate[] delegates = d1.GetInvocationList();
            foreach (Action d in delegates)
                try
                {
                    d1();
                }
                catch(Exception)
                {
                    Console.WriteLine("Exception Caught");

                }
        }
    }
}

这是我得到的输出

count
count
count
count
watch when i occur
Exception Caught
count
count
count
count
watch when i occur
Exception Caught
count
count
count
count
watch when i occur
Exception Caught
count
count
count
count
watch when i occur
Exception Caught
count
count
count
count
watch when i occur
Exception Caught
count
count
count
count
watch when i occur
Exception Caught
count
count
count
count
watch when i occur
Exception Caught
count
count
count
count
watch when i occur
Exception Caught

显然,委托是按照我编写的指定顺序执行的,并且Three()方法都没有在引发异常的One()方法之前执行。

所以我缺少一些东西,或者委托中的实际方法按指定的顺序执行,而我从书中读到的东西意味着别的东西。

3 个答案:

答案 0 :(得分:6)

未定义 - 行为被指定为任意(就像你忘记了妻子的生日后发生的事情......)所以取决于任意行为是可能的危险。

可能是5年后,Microsoft发布了.NET 7并且您的程序结果发生了变化。那是"未定义"这意味着,今天没有多少测量值可以让您对下一个版本,甚至是您的计算机和Fred的计算机之间感到舒适。所以观察它只是有趣的,但对可靠性没有用。依靠你观察到的东西在技术上是错误的。

有时,供应商会专门记录未定义的内容,以便在实施过程中保持灵活性。

答案 1 :(得分:2)

"正式未定义"简单地说:无论发生什么,都是实施细节;它可能会像你自然期望的那样工作;它可能完全不同,要么完全有效。实现者没有需求mande它以任何特定顺序运行。此外,这可能会在框架版本,目标和实现之间发生变化。

基本上:即使它符合您的期望和愿望:不要依赖它继续这样做。

答案 2 :(得分:-1)

我不是高级程序员,但是在查看了您的代码之后,我可能会发现一些错误。

您需要使用此

Delegate[] delegates = d1.GetInvocationList();
            foreach (Action d in delegates)
            {
                try
                {
                    d();
                }
                catch(Exception e)
                {
                    Console.WriteLine("Exception Caught : "+e.Message);

                }
             }

代替这个

Delegate[] delegates = d1.GetInvocationList();
            foreach (Action d in delegates)
                try
                {
                    d1();
                }
                catch(Exception)
                {
                    Console.WriteLine("Exception Caught");

                }

这就是我得到的

count
count
count
count
watch when i occur
Exception Caught : Error in watching
great
great
great

很明显,调用列表中的委托是按顺序执行的

最诚挚的问候