C#内容学习——委托与事件

前言:

一直对C#中的委托与事件不太了解,今天来正式学习一下,我跟着的课程,是这个网站的讲解

 

 

 

 


Action委托

我们新建一个C#项目

代码:

namespace Project_Action
{
    class Program
    {
        static void Main(string[] args)
        {
            //第一种应用 将方法当成参数来进行传递
            Test(Test2);
            Console.ReadLine();
        }

        //执行完之后,我还有一些事情要继续执行,但是我暂时不知道
        //是要调用哪个接口
        public static void Test(Action action) {
            Console.WriteLine("执行完Test方法了");
            if (action != null) {
                action();
            }
        }
        public static void Test2() {
            Console.WriteLine("执行完Test2方法了");
        } 
    }
}

如示例,第一种使用方法就是这样将另一个方法作为参数调用。

另外

我们还可以这样利用Action委托

namespace Project_Action
{
    class Program
    {
        static Action mAction;
        static void Main(string[] args)
        {
            //与委托绑定了的方法,在委托调度的时候,就会被执行
            mAction += Test1;
            mAction += Test2;
            mAction();
            //不需要条用的时候,从绑定的列表汇总移除
            mAction -= Test2;
            mAction();
            Console.ReadLine();
        }

        //执行完之后,我还有一些事情要继续执行,但是我暂时不知道
        //是要调用哪个接口
        public static void Test1() {
            Console.WriteLine("执行完Test1方法了");
        }
        public static void Test2() {
            Console.WriteLine("执行完Test2方法了");
        }
    }
}

+=:用于多个方法绑定给委托

=   :用于单个方法绑定给委托

如果我们想要给Action委托添加参数呢?

namespace Project_Action
{
    class Program
    {
        static Action<int,string> mAction;
        static void Main(string[] args)
        {
            //与委托绑定了的方法,在委托调度的时候,就会被执行
            mAction += Test1;
            int a = 3;
            string b = "Hello";
            mAction(a,b);
            Console.ReadLine();
        }

        //执行完之后,我还有一些事情要继续执行,但是我暂时不知道
        //是要调用哪个接口
        public static void Test1(int a,string b) {
            Console.WriteLine("第"+a+"个:"+b);
        }
    }
}

 

以上就是Action委托的基本用法。

Action委托有一个大缺点:不支持返回值,所以后面才有了Func委托

 


Func委托

使用Func来实现带有返回值的委托调用

可以绑定带有返回值的方法,并且接受其返回值

namespace Project_Action
{
    class Program
    {
        static Func<int, int, int> func1;
        static void Main(string[] args)
        {
            //将方法与委托进行绑定
            func1 = Test;
            int result=func1(50,16);
            Console.WriteLine(result);

            //不管是+=还是=,都要取消委托的注册,移除委托绑定的方法
            func1 -= Test;

            Console.ReadLine();
        }
        public static int Test(int a,int b) {
            return (a + b);
        }
    }
}

打印:66

另外func也可以像Action一样作为参数传递

namespace Project_Action
{
    class Program
    {
        
        static Func<int, int, int> func1;
        static void Main(string[] args)
        {
            int result=Test(Test2, 100,500);
            Console.WriteLine(result);

            Console.ReadLine();
        }
        public static int  Test(Func<int,int,int> callback,int a,int b) {
            if (callback!=null) {
                return callback(a,b);
            }
            return 0;
        }
        public static int  Test2(int a,int b) {
            return a * b;
        }
    }
}

输出:50000

 


Delegate委托

这种委托比上面那两古老一些,而且语法也相对复杂一点,这个委托可以带返回值,也可以不带。

简单使用方法

namespace Project_Action
{
    class Program
    {
        //定义委托原型(此例无返回值无参数)
        delegate void MyDelegate();
        //通过定义的delegate创建一个事件
        static MyDelegate delegate1;
        static void Main(string[] args)
        {
            Console.WriteLine("第一次调用");
            delegate1 += Test1;
            delegate1 += Test2;
            delegate1(); 
            Console.WriteLine("第二次调用");
            delegate1 -= Test1;
            delegate1();
            Console.ReadLine();
        }
        static void Test1() {
            Console.WriteLine("test1被执行");
        }
        static void Test2()
        {
            Console.WriteLine("test2被执行");
        }
    }
}

另外它也有作为参数的方法:

namespace Project_Action
{
    class Program
    {
        //定义委托原型(此例无返回值无参数)
        delegate void MyDelegate();
        //通过定义的delegate创建一个事件
        static MyDelegate delegate1;
        static void Main(string[] args)
        {
            Test(Test1);
            Console.ReadLine();
        }
        static void Test(MyDelegate d) {
            Console.WriteLine("test被执行");
            if (d != null) {
                d();
            }
        }
        static void Test1()
        {
            Console.WriteLine("test1被执行");
        }
    }
}

如果需要参数

namespace Project_Action
{
    class Program
    {
        //定义委托原型(此例无返回值无参数)
        delegate void MyDelegate();
        //通过定义的delegate创建一个事件
        static MyDelegate delegate1;

        delegate void MyDelegate2(int a,int b);
        static MyDelegate2 delegate2;

        static void Main(string[] args)
        {
            Test(Test1,100,200);
            Console.ReadLine();
        }
        static void Test(MyDelegate2 d,int a,int b) {
            Console.WriteLine("test被执行");
            if (d != null) {
                d(a,b);
            }
        }
        static void Test1(int a,int b)
        {
            Console.WriteLine("test1被执行"+a+b);
        }
    }
}

返回值也是一样的道理,就不做示范了。

 

 


Event事件

event实际上是对Delegate的一个封装

我们来举个例子:

一个命令空间下有两个类——Player和Program

    class Player
    {
        public delegate void myDelegate();
        public event myDelegate d1;   //事件
    }
    class Program
    {
        static void Main(string[] args)
        {
            Player player = new Player();
            player.d1 += Test1;
            player.d1();
            Console.ReadLine();
        }
        static void Test1() {
            Console.WriteLine("我是Test1");
        }
    }

然后我们会发现报错

这就是Event的作用,它限制了Delegate委托绑定的方法必须在Player中调用。

    class Player
    {
        public delegate void myDelegate();
        public event myDelegate d1;   //事件
        public void Call() {
            if (d1 != null) {
                d1();
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Player player = new Player();
            player.d1 += Test1;
            player.Call();
            Console.ReadLine();
        } 
        static void Test1() {
            Console.WriteLine("我是Test1");
        }
    }

输出:我是Test1

 

从上面的实验,我们得出:

事件,实际就是对委托的一个限制,让委托的调度只能限制在这个类的内部(在别的类中可以进行注册/移除的操作,但是不能调用)

 

 

 

 


总结:

C#中的委托大致就是这些内容了,它主要的作用其实就是去解耦各个模块;避免直接调度其他模块的方法、而是通过注册/移除来控制其他模块方法的调度。

委托是一个非常好的策略,比如在游戏制作中,战斗开始之后,无需调用英雄的初始化、音乐的初始化、场景的初始化,可以直接在一个委托中直接调用。

 

 

商业转载 请联系作者获得授权,非商业转载 请标明出处,谢谢

 

发表评论