委托 和 事件

委托

定义

委托是存有对某个方法的引用的一种引用类型变量,本质是一个类,用来 存储、传递函数(方法)。可以将其 实例与 "格式"的方法 相关联。
观察者模式就是通过委托进行实现的

using System;

namespace Lesson12_委托
{
    #region 知识点一 委托是什么
    //委托是 函数(方法)的容器 
    //可以理解为 表示函数(方法)的变量类型
    //用来 存储、传递函数(方法)
    //委托的本质是一个类,用来定义函数(方法)的类型(返回值和参数的类型)
    //不同的 函数(方法)必须对应和各自"格式"一致的委托
    #endregion

    #region 知识点二 基本语法
    //关键字 : delegate
    //语法:访问修饰符 delegate 返回值 委托名(参数列表);

    //写在哪里?
    //可以申明在namespace和class语句块中
    //更多的写在namespace中

    //简单记忆委托语法 就是 函数申明语法前面加一个delegate关键字
    #endregion

    #region 知识点三 定义自定义委托
    //访问修饰默认不写 为public 在别的命名空间中也能使用
    //private 其它命名空间就不能用了
    //一般使用public

    //申明了一个可以用来存储无参无返回值函数的容器
    //这里只是定义了规则 并没有使用
    delegate void MyFun();
    //委托规则的申明 是不能重名(同一语句块中)
    //表示用来装载或传递 返回值为int 有一个int参数的函数的 委托 容器规则
    public delegate int MyFun2(int a);

    //委托是支持 泛型的 可以让返回值和参数 可变 更方便我们的使用
    delegate T MyFun3<T, K>(T v, K k);
    #endregion

    #region 知识点四 使用定义好的委托
    //委托变量是函数的容器

    //委托常用在:
    //1.作为类的成员
    //2.作为函数的参数
    class Test
    {
        public MyFun fun;
        public MyFun2 fun2;

        public Action action;

        public void TestFun( MyFun fun, MyFun2 fun2 )
        {
            //先处理一些别的逻辑 当这些逻辑处理完了 再执行传入的函数
            int i = 1;
            i *= 2;
            i += 2;

            //fun();
            //fun2(i);
            //this.fun = fun;
            //this.fun2 = fun2;
        }


        #region 增
        public void AddFun(MyFun fun, MyFun2 fun2)
        {
            this.fun += fun;
            this.fun2 += fun2;
        }
        #endregion

        #region 删
        public void RemoveFun(MyFun fun, MyFun2 fun2)
        {
            //this.fun = this.fun - fun;
            this.fun -= fun;
            this.fun2 -= fun2;
        }
        #endregion
    }
    #endregion

    #region 知识点五 委托变量可以存储多个函数(多播委托)


    #endregion

    

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("委托");
            //专门用来装载 函数的 容器
            MyFun f = new MyFun(Fun);
            Console.WriteLine("1");
            Console.WriteLine("2");
            Console.WriteLine("3");
            Console.WriteLine("4");
            Console.WriteLine("5");
            f.Invoke();

            MyFun f2 = Fun;
            Console.WriteLine("1");
            Console.WriteLine("2");
            Console.WriteLine("3");
            Console.WriteLine("4");
            Console.WriteLine("5");
            f2();

            MyFun2 f3 = Fun2;
            Console.WriteLine(f3(1));

            MyFun2 f4 = new MyFun2(Fun2);
            Console.WriteLine(f4.Invoke(3));

            Test t = new Test();

            t.TestFun(Fun, Fun2);
            Console.WriteLine("***************");
            //如何用委托存储多个函数
            MyFun ff = null;
            //ff = ff + Fun;
            ff += Fun;
            ff += Fun3;
            ff();
            //从容器中移除指定的函数
            ff -= Fun;
            //多减 不会报错 无非就是不处理而已
            ff -= Fun;
            ff();
            //清空容器
            ff = null;
            if( ff != null )
            {
                ff();
            }

            #region 知识点六 系统定义好的委托
            //使用系统自带委托 需要引用using System;
            //无参无返回值
            Action action = Fun;
            action += Fun3;
            action();

            //可以指定返回值类型的 泛型委托
            Func<string> funcString = Fun4;
            Func<int> funcInt = Fun5;

            //可以传n个参数的  系统提供了 1到16个参数的委托 直接用就行了
            Action<int, string> action2 = Fun6;

            //可以穿n个参数的 并且有返回值的 系统也提供了 16个委托
            Func<int, int> func2 = Fun2;
            #endregion
        }

        static void Fun()
        {
            Console.WriteLine("张三做什么");
        }
        static void Fun3()
        {
            Console.WriteLine("李四做什么");
        }

        static string Fun4()
        {
            return "";
        }

        static int Fun5()
        {
            return 1;
        }

        static void Fun6(int i, string s)
        {

        }

        static int Fun2(int value)
        {
            return value;
        }
    }

    //总结
    //简单理解 委托 就是装载、传递函数的容器而已
    //可以用委托变量 来存储函数或者传递函数的
    //系统其实已经提供了很多委托给我们用 
    //Action:没有返回值,参数提供了 0~16个委托给我们用
    //Func:有返回值,参数提供了 0~16个委托给我们用
    //也可以自己定义委托
}

事件

using System;

namespace Lesson13_事件
{
    #region 知识点一 事件是什么
    //事件是基于委托的存在
    //事件是委托的安全包裹
    //让委托的使用更具有安全性
    //事件 是一种特殊的变量类型
    #endregion

    #region 知识点二 事件的使用
    //申明语法:
    //访问修饰符 event 委托类型 事件名;
    //事件的使用:
    //1.事件是作为 成员变量存在于类中
    //2.委托怎么用 事件就怎么用
    //事件相对于委托的区别:
    //1.不能在类外部 赋值
    //2.不能再类外部 调用
    //注意:
    //它只能作为成员存在于类和接口以及结构体中
    class Test
    {
        //委托成员变量 用于存储 函数的
        public Action myFun;
        //事件成员变量 用于存储 函数的
        public event Action myEvent;

        public Test()
        {
            //事件的使用和委托 一模一样 只是有些 细微的区别
            myFun = TestFun;
            myFun += TestFun;
            myFun -= TestFun;
            myFun();
            myFun.Invoke();
            myFun = null;

            myEvent = TestFun;
            myEvent += TestFun;
            myEvent -= TestFun;
            myEvent();
            myEvent.Invoke();
            myEvent = null;
        }

        public void DoEvent()
        {
            if(myEvent != null)
            {
                myEvent();
            }
        }

        public void TestFun()
        {
            Console.WriteLine("123");
        }
    }
    #endregion

    #region 知识点三 为什么有事件
    //1.防止外部随意置空委托
    //2.防止外部随意调用委托
    //3.事件相当于对委托进行了一次封装 让其更加安全
    #endregion

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("事件");

            Test t = new Test();
            //委托可以在外部赋值
            t.myFun = null;
            t.myFun = TestFun;
            t.myFun = t.myFun + TestFun;
            t.myFun += TestFun;
            //事件是不能再外部赋值的
            //t.myEvent = null;
            //t.myEvent = TestFun;
            //虽然不能直接赋值 但是可以 加减 去添加移除记录的函数
            t.myEvent += TestFun;
            t.myEvent -= TestFun;

            //委托是可以在外部调用的
            t.myFun();
            t.myFun.Invoke();
            //事件不能再外部调用
            //t.myEvent(); 这里调不出来
            //只能在类的内部去封装 调用
            t.DoEvent();

            Action a = TestFun;
            //事件 是不能作为临时变量在函数中使用的
            //event Action ae = TestFun;
        }

        static void TestFun()
        {

        }
    }
    //总结
    //事件和委托的区别
    //事件和委托的使用基本是一模一样的
    //事件就是特殊的委托
 
}

区别

//主要区别:
//1.事件不能再外部使用赋值=符号,只能使用+ - 委托 哪里都能用
//2.事件 不能再外部执行 委托哪里都能执行
//3.事件 不能作为 函数中的临时变量的 委托可以

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值