【转载】Unity C# の 委托、事件、匿名委托、Lambda 表达式(二)

135 阅读2分钟

原文链接

Unity C# 多态 委托 事件 匿名委托 Lambda表达式 观察者模式 .NET 框架中的委托和事件 | Jason_c

原文写得很好,但是主题格式我不太喜欢,所以我对文章的格式进行了修整,方便自己日后阅读

正文

二、委托

委托:将方法作为参数传递

using System;

namespace Delegate
{
    public delegate void GreetingDelegate(string name);

    class People
    {
        public static void Speak(string name,GreetingDelegate _delegate)
        {
            _delegate (name);
        }
    }
    class Language
    {
        public static void EnglishGreeting(string name)
        {
            Console.WriteLine ("Good Morning,"+name);
        }
        public static void ChineseGreeting(string name)
        {
            Console.WriteLine ("早上好,"+name);
        }
    }

    class MainClass
    {
        public static void Main (string[] args)
        {
            GreetingDelegate greetingDelegate;
            greetingDelegate = Language.EnglishGreeting ;//委托第一次绑定时,须用“=”
            People.Speak("Jason", greetingDelegate);
            greetingDelegate -= Language.EnglishGreeting;
            greetingDelegate += Language.ChineseGreeting ;
            People.Speak("杰森", greetingDelegate);
        }
    }
}
  • 运行结果 image.png

三、事件

事件:对委托类型的变量的封装

在类的内部,不管你声明的事件是 public 还是 protected ,它总是 private 的;

在类的外部,注册 += 和注销 -= 的访问限定符与你在 声明事件 时使用的访问符相同。

using System;

namespace Delegate
{
    public delegate void GreetingDelegate(string name);

    class People
    {
        public static event GreetingDelegate greetingEvent;
        public static void Speak(string name)
        {
            greetingEvent(name);
        }
    }
    class Language
    {
        public static void EnglishGreeting(string name)
        {
            Console.WriteLine ("Good Morning,"+name);
        }
        public static void ChineseGreeting(string name)
        {
            Console.WriteLine ("早上好,"+name);
        }
    }

    class MainClass
    {
        public static void Main (string[] args)
        {
            People.greetingEvent += Language.EnglishGreeting;
            People.Speak ("Jason");
            People.greetingEvent -= Language.EnglishGreeting;
            People.greetingEvent += Language.ChineseGreeting;
            People.Speak ("杰森");
        }
    }
}
  • 运行结果 image.png

四、匿名委托

匿名委托:也叫匿名方法,将代码块当做参数传递,因为不需要创建单独的方法,因此 减少了实例化委托所需要的开销

using System;

namespace Delegate
{
    public delegate void GreetingDelegate(string name);
    class People
    {
        public static void Speak(string name,GreetingDelegate _delegate)
        {
            _delegate (name);
        }
    }

    class MainClass
    {
        public static void Main (string[] args)
        {
            GreetingDelegate greetingDelegate = delegate(string name) {
                Console.WriteLine ("Good Morning,"+name);
            };
            People.Speak ("Jason",greetingDelegate);

            GreetingDelegate greetingDelegate_1 = delegate(string name) {
                Console.WriteLine ("早上好,"+name);
            };
            People.Speak ("杰森",greetingDelegate_1);
        }
    }
}

在使用匿名方法时候,要 注意

  • 不能使用跳转语句跳转到该匿名方法的外部,
  • 同样不能用跳转语句从外部跳转到匿名方法内部,
  • 匿名方法中不能访问不安全代码(unsafe),
  • 也不能访问在匿名方法外部使用的 refout 参数。

在实际问题中可能遇到的问题要比上面的代码复杂得多,在匿名方法中捕获变量就是难点之一。

  • 运行结果: image.png

五、Lambda 表达式

Lambda 表达式:比匿名委托代码更加简洁,运算符 ()=>,

using System;

namespace Delegate
{
    public delegate void GreetingDelegate(string name);
    class People
    {
        public static void Speak(string name,GreetingDelegate _delegate)
        {
            _delegate (name);
        }
    }

    class MainClass
    {
        public static void Main (string[] args)
        {
            GreetingDelegate greetingDelegate = (string name) =>
                Console.WriteLine ("Good Morning,"+name);
            People.Speak ("Jason",greetingDelegate);

            GreetingDelegate greetingDelegate_1 = (string name) => {
                Console.WriteLine ("早上好," + name);
            };
            People.Speak ("杰森",greetingDelegate_1);
        }
    }
}
  • 运行结果: image.png