欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

委托的发展(二)

程序员文章站 2022-04-11 20:44:39
嗯~~,其实在C#1看来委托语法看起来似乎并不太坏——语言以围绕Delegate.Combine,Delegate.Remove以及委托实例的调用提供了语法糖。 表面上一切都在正常的轨道上,但是感觉不太对。 很难确切的描述C#1的委托创建表达式为什么会令人不快,但他们确实如此。 在C#1中我们先写好 ......

嗯~~,其实在C#1看来委托语法看起来似乎并不太坏——语言以围绕Delegate.Combine,Delegate.Remove以及委托实例的调用提供了语法糖。

表面上一切都在正常的轨道上,但是感觉不太对。

很难确切的描述C#1的委托创建表达式为什么会令人不快,但他们确实如此。

在C#1中我们先写好一连串事件处理程序,然后到处写new。这显得很多余,很凌乱,因为事件本身已经指定了它要使用那个委托类型。

可能你会有不同意见,但是由于代码中的文字量过多,会妨碍我们阅读,并会使我们分心而忽略了真正该注意的代码。

委托的协变性与逆变型,暂时先不所!

*C#2委托的进步阶梯

        delegate void TestDelegate(string x);
        public class Snippet
        {
            public void TestAction(string x)
            {
                Console.WriteLine("Hellow");
            }
        }

        public class Derived : Snippet
        {
            public void TestAction(object x)
            {
                Console.WriteLine("Hi");
            }
        }

如果这样调用这个委托的话:

          Derived x = new Derived();
                TestDelegate test = new TestDelegate(x.TestAction);
                test("test");

上面有两个类,Snippet与Derived,并且Derived继承自Snippet

在C#1中会输出"Hellow"。因为object参数那个方法与委托TestDelegate不兼容。

但在C#2中,它是兼容的,他会输出“Hi”。由于是在另一个派生的类型中声明的,所以选中的是这个方法,。

*C#2匿名方法

在C#1,你只需要一个委托,做一件非常非常小的事情,但也必须创建一个完整的新方法。该方法表示的行为只和原始方法有关,但现在却对整个类公开。

这一切都让人呕吐,所以C#2引入了  匿名方法

漂亮的解决了此问题。

按照不太正式的说法,匿名方法允许你指定一个内联委托实例的操作,作为创建委托实例表达式的一部分。

匿名方法还以 闭包 的形式提供了一些更加强大的行为。

与下面的Action一起来做一个例子吧

*C#2引入了一个泛型委托类型Action<T>

他的签名非常简单: 就是一个无返回值的只有一个参数的名叫Action的泛型委托

 public delegate void Action<T>(T obj);

使用匿名方法加Action泛型委托来:输出List<int>的总和

 Action<List<int>> list = delegate (List<int> x)
 {
      int sum = 0;
      foreach (int i in x)
      {
         sum += i;
      }
       Console.WriteLine("总和:" + sum );
 };
  list(List<int>); //执行

 首先是匿名方法的语句:首先是delegate关键字,再是参数(如果有的话),随后是一个代码块,定义的对委托实例的操作。

 看的出来这个匿名方法声明了一个int变量,然后循环List集合,累加到int变量上,然后输出这个List总和。

提醒一点,逆变型不适用于匿名方法:必须指定和委托类型完全匹配的参数类型。

*匿名方法的返回值

Action<T>委托的返回类型是void,所以不必从匿名方法中返回任何东西。在某种情况下需要返回值怎么办呢?

使用.NET2.0中的Predicate<T>委托类型。下面给出它的签名:

public delegate bool Predicate<T>(T obj);

它是一个Predicate<T>的泛型委托实例,返回值时bool类型,而且有一个参数。

谓词(Predicate)通常用于过滤和匹配,例如,可以利用代码清单来过滤一个列表,使之只包含偶数元素。

来用一下,创建一个Predicate<T>实例,其返回值指出传入的实参是奇数还是偶数。

        Predicate<int> isEven = delegate (int x)
            {
                return x % 2 == 0;
            };

            Console.WriteLine(isEven(1));
            Console.WriteLine(isEven(6));

新的语法(匿名方法),我想把它当做一个普通方法来对待,并返回一个恰当的值。你可能以为还要在靠近delegate关键字的地方声明一个返回类型,但那是没有必要的。

因为编译器只需检查是否所有可能的返回值都兼容于委托类型(编译器会尝试将匿名方法转换成这个委托类型)声明的返回类型。

*小结

C#2根本性的改变了委托的创建方式,这样我们就能在。NET Framework的基础上采取一种更函数化的编程风格。

与.Net1.0/1.1相比,2.0有更多以委托作为参数的方法

2.0委托改动非常多甚至可以说是变革一样。我讲述了不到十分之一。

只是大体讲了讲委托的进化,而没有说出他的内在变化,逆变型与协变性,包括闭包,捕获变量等等。。。

太多了。。。以后再补充吧