C# delegate event框架及观察者模式

event(事件)就是delegate(代理),event能做到的事情delegate都能做到。

而delegate可以认为是一种函数指针

1.先用函数指针来做例子,C++代码

//函数指针,指向的类型为参数为空,返回值也为空的函数
void (*pFun)();

void Fun3(){
    cout << "Fun3" << endl;
}
//在代用Fun1()前先将函数指针pFun指向Fun2()函数
int main(){
    pFun = Fun3();
    pFun();
    return 0;
}

2.delegate的例子

    public delegate void Del();

    class Program
    {
        static void Main(string[] args)
        {
            Del del = Fun;
            del += Fun; 
            del.Invoke();

            Console.ReadLine();
        }

        public static void Fun()
        {
            Console.WriteLine();
        }
    }

delegate的声明形式是:public delegate void Del();; 这和函数指针的声明形式基本一样:void (*pFun)();

上面的函数指针和delegate代码说明,函数指针和delegate是非常像的,作用也是非常像的。

delegate具有多播的能力,即可以同时绑定多个方法,正如例子中所展示的。


个人理解delegate:

delegate是一种类型,和string,int,class一样,是一种类型。每一种类型都是一种约束,约束了该类型的各种能力(比如string就是字符串的各种操作,int就是整数的各种操作)。而delegate作为一种类型,他也有自己的约束,就是他指向的是一类方法(函数)。当定义了一个delegate的类型时:

 public delegate void Del();//此句中的delegate是一个标识符,而Del才是真正的delegate类型

Del del;//del表示Del这个delegate类型的实例

del这个实例就和函数指针void (*pFun)()一样,可以指向一个参数为空,返回值也为空的方法。可以在原本需要调用这个方法时用del就代替这个方法的位置,但前提是,将方法绑定到del上。

在有了delegate程序就可以灵活很多了。原本在程序中固定的方法可以用delagate代替,然后动态的传递符合要求的方法。

这样可以使一些底层的方法不需要改了,只要改上层的逻辑就可以了。


个人理解event:

event就是一个delegate,event能做到的,delegate都能做到。

但是不希望event拥有太多delegate的属性,就采用event。

event即事件。事件表示某一个动作发生或某一个时机到来的时候,紧接着会产生某一个动作

public void Fun1(){
    Fun2();
}
public void Fun2(){
}

上面的例子中,每当Fun1()方法被调用的时候,Fun2()必定被调用。那么Fun2就是一个事件,该事件的触发条件就是当Fun1被调用。

private int price;
public int Price
{
    get { return price; }
    set
    {
        price = value;
        if (price > 10)
        {
            Fun2();
        }
    }
}

上面的例子中,每当price>10时,Fun2都会被触发。那么这个例子中的Fun2()也是一个事件,该事件的触发条件就是price>10。

可以说,事件本身其实就是一个函数。只不过它的调用时机不是任意的,而是固定在某一个节点上。


像上面的例子中,事件直接用方法来替代的做法不是很聪明,因为太死板了。我们何不用delegate来代替这个方法,可以做到灵活多变。这样底层的代码就可以不用修改了,我们的需求改变时,只要增加新的方法就行了(对修改关闭,对添加开放)。

使用delegate的例子:

    delegate void OnClick(string key);
    class Program
    {
        static void Main(string[] args)
        {
            //可以动态绑定我们需要的方法
            OnClick onclick = ShowLower;
            //onclick += ShowUpper;
            while (true)
            {
                Console.Write("input:");
                onclick(Console.ReadLine());
            }
            Console.ReadLine();
        }
        //将输入的字符串变小写
        public static void ShowLower(string key)
        {
            Console.WriteLine("output:" + key.ToLower());
        }
        //将输入的字符串变大写
        public static void ShowUpper(string key)
        {
            Console.WriteLine("output:" + key.ToUpper());
        }

    }

在前文中说过,event能够做的事,delegate都能做,而且event就是delagate中的特殊情况。那为什么我们还要创建event呢。因为当我们定义delegate时,delegate会包含很多对delagate的操作,可以从外部来直接操作这个delegate。所以用event来限制外部对delagate其余方法的调用,让外部只能添加和删除delegate绑定的方法。

使用event的例子:

也可以将上述例子使用event代替

    delegate void OnClick(string key);
    class Program
    {
        private static event OnClick onclick;

        static void Main(string[] args)
        {
            onclick = ShowLower;
            //onclick += ShowUpper;
            while (true)
            {
                Console.Write("input:");
                onclick(Console.ReadLine());
            }
            Console.ReadLine();
        }

        public static void ShowLower(string key)
        {
            Console.WriteLine("output:" + key.ToLower());
        }

        public static void ShowUpper(string key)
        {
            Console.WriteLine("output:" + key.ToUpper());
        }
    }

上面的event是语法级别的,可以这么使用,但并不符合逻辑。

使用event更好的例子。

气象台和广播。1个气象台,多个地方广播,每个地方广播有自己的特色。每当气象台的温度改变时,各个广播会自动的播报。

    public delegate void TempChangeEventHandler(int temp);
    class Program
    {
        static void Main(string[] args)
        {
            Center center = new Center(25);
            center.tempChangeEvent += 东部电视台;
            center.tempChangeEvent += 西部电视台;
            center.tempChangeEvent += 中部电视台;
            while (true)
            {
                Console.WriteLine("当前温度:{0}",center.Temperature);
                Console.Write("新温度为:");
                center.Temperature = int.Parse(Console.ReadLine());
            }

            Console.ReadLine();
        }

        public static void 东部电视台(int temp)
        {
            Console.WriteLine($"东部电视台:当前温度为{temp}℃, 生活愉快");
        }

        public static void 西部电视台(int temp)
        {
            Console.WriteLine($"西部电视台:当前温度为{temp}℃, 欢迎大家来游玩");
        }

        public static void 中部电视台(int temp)
        {
            Console.WriteLine($"中部电视台:当前温度为{temp}℃, 请适当增减衣物");
        }

    }

    public class Center
    {
        public TempChangeEventHandler tempChangeEvent;

        private int _temperature;

        public int Temperature
        {
            get => _temperature;
            set
            {
                if (value != _temperature)
                {
                    _temperature = value;
                    tempChangeEvent(_temperature);
                }
            }
        }

        public Center(int temperature)
        {
            _temperature = temperature;
        }
    }

但是C#定义了一套专门的事件框架,最好使用这个框架。

class Program
    {
        static void Main(string[] args)
        {
            Center center = new Center(25);
            center.tempChangeEvent += 东部电视台;
            center.tempChangeEvent += 西部电视台;
            center.tempChangeEvent += 中部电视台;
            while (true)
            {
                Console.WriteLine("当前温度:{0}",center.Temperature);
                Console.Write("新温度为:");
                center.Temperature = int.Parse(Console.ReadLine());
            }

            Console.ReadLine();
        }

        public static void 东部电视台(object sender, TempEventArgs e)
        {
            Console.WriteLine($"东部电视台:当前温度为{e.Temp}℃, 生活愉快");
        }

        public static void 西部电视台(object sender, TempEventArgs e)
        {
            Console.WriteLine($"西部电视台:当前温度为{e.Temp}℃, 欢迎大家来游玩");
        }

        public static void 中部电视台(object sender, TempEventArgs e)
        {
            Console.WriteLine($"中部电视台:当前温度为{e.Temp}℃, 请适当增减衣物");
        }

    }

    public class Center
    {
        public EventHandler<TempEventArgs> tempChangeEvent;

        private int _temperature;

        public int Temperature
        {
            get => _temperature;
            set
            {
                if (value != _temperature)
                {
                    _temperature = value;
                    tempChangeEvent?.Invoke(this, new TempEventArgs(_temperature));
                }
            }
        }

        public Center(int temperature)
        {
            _temperature = temperature;
        }
    }

    //事件中需要的参数
    public class TempEventArgs : EventArgs
    {
        public int Temp;
        public TempEventArgs(int temp)
        {
            Temp = temp;
        }
    }

可以对比两者的区别。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值