2019.11.13委托笔记

1、委托(千呼万唤始出来啊,终于比较详细地了解了这个概念了)
委托就是一种特殊的类型,代表一类方法,该类方法拥有一样的传入参数和返回结果。
委托的好处是实现方法之间的解耦,比如以下代码的Main方法和Sum方法解耦。
delegate int FirstDelegate(int x,int y);
class X{
static void Main(){
FirstDelegate first = Sum;
Console.WriteLine(first(1,2));//3
}
private int Sum(int x,int y){return x+y;}
private int Sum(int x,int y)=>x+y;//简写
}
2、用委托实现插件式的方法
delegate int Transformer(int x);
class Util{
public static void Transform(List numbers,Transformer t){
foreach(var number in numbers){
int result = t(number);
Console.WriteLine(result);
}
}
}
class Programme{
static void Main(){
List numbers = new List{1,2,3,4,5};
Util.Transform(numbers ,Square);//输出 1 4 9 16 25
}
private int Square(int x) => xx;
}
那么我们可以通过以上方法来对同一个list对象进行不同的逻辑处理,只要符合Transformer委托定义的方法类型,都可以用这种方式来实现。
3、多播委托
多播委托通过+=、-=操作符来实现,比如上面我们可以加一个算立方的方法
private int Cube(int x) => x
xx;
然后把平方、立方方法都注册到委托对象中去
Transformer t = null;
t+=Square;
t+=Cube;
这样如果我们调用t(3),那么就会算出3的平方和立方,但是由于多播委托的特性,只会返回最后一个方法的结果,所以只会返回27。
委托对象是不变的,因此每次调用+=或者-=,相当于创建一个新的委托对象,再赋值给原来的。
4、泛型委托
第2点中的插件式方法还可以升级成泛型委托
delegate T Transformer(T x);
class Util{
public static void Transform(List numbers,Transformer t){
foreach(var number in numbers){
T result = t(number);
Console.WriteLine(result);
}
}
}
class Programme{
static void Main(){
List numbers = new List{1,2,3,4,5};
Util.Transform(numbers ,Square);//输出 1 4 9 16 25
//这里也可以写成Util.Transform(numbers ,Square);不过由于传入的list已经声明int类型的了,方法类型参数就可以不写了
}
private int Square(T x) => x
x;
}
5、Func和Action都是特殊的委托,也可以说是一些委托的简写
Func :
Func 相当于 delegate T Func();//也就是没有传入参数,返回结果只有一个泛型类
Func<TFirst,TSecond,TResult>相当于有2个泛型传入参数,一个泛型结果
Action:
Action相当于没有输入也没有输出的泛型类
Action 相当于delegate void Action(T t);
Action<TFirst,TSecond> 相当于delegate void Action(TFirst first,TSecond second);
Func、Action的传入参数都最多能有16位,Func有返回参数,Action无返回参数
所以第五点的Util类又可以改成
class Util{
public static void Transform(List numbers,Func<T,T> t){
foreach(var number in numbers){
T result = t(number);
Console.WriteLine(result);
}
}
}
delegate T Transformer(T x);//这个委托类型就可以去掉了
6、委托的兼容性
委托类型之间互不相容,即使他们方法签名一样
delegate void D1(int x);
delegate void D2(int x);
D1 d = Method1;
D2 d2 =d;//转换失败

如果委托实例有相同的方法目标,那么委托实例就认为是相等的。
delegate void D1(int x);
delegate void D2(int x);
D1 d1 = Method1;
D2 d2 = Method1;
Console.WriteLine(d1==d2);//true
7、事件,B站https://www.bilibili.com/video/av59733329/?p=3
委托涉及到广播者和订阅者,广播者通过调用委托来决定何时进行广播,订阅者通过+=、-=来决定何时开始或者结束监听,一个订阅者不知道也不干扰其他的订阅者。
事件就是为了实现以上的广播者/订阅者模式的一种比较正式化的语言特性。他只暴露了所需的委托特性的部分子集。事件的主要目的是防止订阅者之间互相干扰。
事件实例:
//定义传递信息的类
//比如商品价格改变的时候,传入旧价格和新价格
public class PriceChangedEventArgs : EventArgs
{
private readonly decimal OldPrice;
private readonly decimal NewPrice;

    //构造函数
    public PriceChangedEventArgs(decimal oldPrice, decimal newPrice)
    {
        OldPrice = oldPrice;
        NewPrice = newPrice;
    }

}
//广播者,可以理解为,商品的价格改变了,它就需要告诉要买它的人
public class Commodity
{
    string name;
    decimal price;
    public Commodity(string name)
    {
        this.name = name;
    }

    //定义事件
    //EventHandler这个委托是通用的泛型委托
    public event EventHandler<PriceChangedEventArgs> PriceChanged;
    //价格变化时触发的方法,官方指定使用protected virtual void作修饰符
    protected virtual void OnPriceChanged(PriceChangedEventArgs e)
    {
        //调用事件,传入广播者以及需要传入委托调用的方法的参数类
        PriceChanged?.Invoke(this, e);
    }

    public decimal Price
    {
        get { return price; }
        set
        {
            if (price == value) return;
            decimal oldPrice = price;
            price = value;
            OnPriceChanged(new PriceChangedEventArgs(oldPrice, price));
        }
    }
}
class Program
{
    static void Main(string[] args)
    {
        Commodity com = new Commodity("苹果");
        com.Price = 10;
        //订阅事件
        com.PriceChanged += Commodity_PriceChanged;
        com.Price = 12;
    }
    //商品价格改变就会触发
    static void Commodity_PriceChanged(Object sender, PriceChangedEventArgs e)
    {
        Console.WriteLine("涨价辣");
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值