zoukankan      html  css  js  c++  java
  • 委托

    委托

    委托:委托是一种安全地封装方法的引用类型,他是面向对象的、类型安全的和保险的,它可以代理一个或是多个方法,或是代码块执行,由于是引用类型,它保存的不是实际值,而是保存对存储在托管堆中的对象的引用,即对函数的引用。

    构造委托对象的方法:

    命名方法:使用命名方法构造的委托可以封装静态方法或实例方法(当然定义定义委托的时候不能用static修饰,静态方法不能调用实例化方法),命名方法代理的是方法。

    public delegate void SampleDelegate(string message);
    public static void SampleDelegateMethod(string message)
    {
    Console.WriteLine("SampleDelegateMethod:" + message);
    }
    SampleDelegate d1 =new SampleDelegate(SampleDelegateMethod);
    //可以简写成
    SampleDelegate d1 = SampleDelegateMethod;
    d1("chentaihan");

    匿名方法:匿名方法代理的是一段代码块,使用匿名方法,则不必创建单独的方法,因此减少了实例化委托所需的编码系统开销。

    SampleDelegate d2 = delegate(string message)
    {
    Console.WriteLine(message);
    };
    d2("chentaihan");

    委托中的协变与逆变

    协变实例如下

      public class Animal
    {
    public Animal(string name)
    {
    this.Name = name;
    }

    protected string Name;
    public virtual void ShowName()
    {
    Console.WriteLine("Animal:" + Name);
    }

    };

    public class Cat : Animal
    {
    public Cat(string name) : base(name) { }
    public override void ShowName()
    {
    Console.WriteLine("Cat:" + Name);
    }
    }

    public delegate Animal DelegateAnimalXB(string name);

    public class DelegateXB
    {

    public static Animal CreateAnimal(string name)
    {
    return new Animal(name);
    }

    public static Cat CreateCat(string name)
    {
    return new Cat(name);
    }

    public static void Test()
    {
    DelegateAnimalXB d1 = CreateAnimal;
    d1("Animal").ShowName();//Animal:Animal

    DelegateAnimalXB d2 = CreateCat;
    d2("Cat").ShowName();//Cat:Cat
    }

    }

    委托协变讲的是定义委托是返回类型的多态,我觉得重点根本不在委托,这其实还是一个类型转换的问题,定义委托时返回类型未Animal,你返回他的之类Cat,没有问题啊,编译器帮你隐式类型转换啊,就这样。

    委托逆变实例如下:

        public class MyEventArgs : EventArgs
    {
    public MyEventArgs(){}
    }

    public class DelegateNB
    {
    public delegate void Handler(EventArgs e);
    public event Handler eventHandler;
    public void Test(EventArgs e)
    {
    eventHandler(e);
    }
    }

    static void Main(string[] args)
    {
    DelegateNB nb = new DelegateNB();
    nb.eventHandler += new DelegateNB.Handler(Test);
    nb.Test(new MyEventArgs());
    Console.Read();
    }

    public static void Test(EventArgs e)
    {
    Console.WriteLine(e.ToString());
    }
    }

    委托的逆变看上去实现了参数的多态,定义委托的时候,参数为EventArgs,而传进去的却是一个MyEventArgs,但是定义其他类型的参数,使用多态的方式传参却编译通过不了,只能是EventArgs及其之类,为什么是这样呢,俺也不知道,只知道事件代理的时候,定义委托的时候参数绝对是(object sender,EventArgs e),微软只用定义这一个事件,他就能委托很多类型的事件,如mouseup,mousedown,keyup等一堆类似的事件,正 因为定义委托的时候参数类型未EventArgs,所以你在写事件方法的时候参数为EventArgs或是相关的事件类(肯定也是EventArgs的之类)都是可以的。如文本框的KeyDown事件参数为KeyEventArgs,你用EventArgs是没有问题的,因为委托定义的时候参数就是EventArgs吗,当然用EventArgs没有会失去KeyEventArgs自带的属性和方法,反过来说如果我们不需要这些特有的属性和方法,用EventArgs会更好,杀鸡焉用宰牛刀。

    泛型委托

    泛型委托就会泛型跟委托的结合,根本不是什么新东西,只要你会泛型,会用委托,你就知道怎么使用泛型委托。泛型委托其实就是编译器动态的帮你定义一组委托,在你要用得时候才定义,不用就不定义,而且每种类型的委托只定义一次。泛型说白了就是编译器帮你写代码,当然使用他的确是减少了类型转换。

    简单实例如下:

        public class DelegateGeneric
    {
    public delegate void Del<T>(T item);

    public static void f1(double i)
    {
    Console.WriteLine(i);
    }

    public static void Test()
    {
    Del<double> d1 = f1;
    d1(1);//代理方法f1(double i),输出:1
    }
    }

    委托不能重载,即委托名称相同,参数类型,个数不同。构造委托的时候,根本不管参数,当然也就不知道你要构造的是哪个委托。

    委托不支持多态,正因为重载的存在导致委托不能支持多态。

        public class A { }
    public class B : A { }

    public class DelegateDT
    {
    public delegate void DelegateFun(A a);
    public static void DelegateA(A a)
    {
    Console.WriteLine("DelegateA");
    }

    public static void DelegateA(B a)
    {
    Console.WriteLine("DelegateB");
    }

    public static void Test()
    {
    DelegateFun d1 = DelegateA;
    d1(new B());
    }
    }

    这里其实调用的是方法DelegateA(A a),并不是DelegateA(B a),要是支持多态的话,他根本就不知道调用哪个方法,还是因为多态,你传进来一个对象B,正好有一个方法所需的参数是B的父类A,所以编译器自动将B隐式转换成A,然后调用方法DelegateA(A a),如果没有这个方法,编译是通不过的。多态不就是编译器帮我们寻找最合适的方法吗,如果没找到,就隐式转换,看有没有合适的方法,如果没有,编译出错。

      作者:陈太汉

      博客:http://www.cnblogs.com/hlxs/

  • 相关阅读:
    python入门
    Django 知识点回顾
    Django----ORM 对表单的操作
    Django----ORM 对表单的操作2
    html
    线程ThreadPoolExecutor与进程ProcessPoolExecutor
    CMDB基于配置文件加载插件的范例
    瀑布流方式三(方式二的升级版)
    学校系统快速js代码
    小知识:Python函数传递变长
  • 原文地址:https://www.cnblogs.com/hlxs/p/2264496.html
Copyright © 2011-2022 走看看