CLR之委托的揭秘(二)

 

杂谈

             在开始真正的代码以前,分析一下上周的一些工做内容,发现本身在代码上仍是有不少小毛病须要纠正和去更改的,首先以前一直疏于文档的整理,几乎不多去写文档,第二对于接口开发过程当中缺乏必定的严谨性,不少问题没有考虑清楚就已经代码敲完了,其实应该先针对接口去写一份接口说明文档,一方面提高本身的文档能力,另一方面也经过文字整理本身的思路,还有就是程序开发中不能懒,由于懒已经出了不少问题,程序毕竟是严谨的,你忽能它,它也必然忽能你!安全

            这是上周工做中的一些总结,接下来继续以CLR的角度分析委托,上一节说了委托的定义,委托链,还有匿名委托。接下来咱们分析ide

 

泛型委托

          其实我对于泛型委托以前也是彻底只知其一;不知其二,有一次在用Linq的时候,先用了Where有用了Find,个人本意是先筛选在查找,但实际上二者基本上是一回事,都是泛型委托,固然关于泛型委托不得不说的就是 Action<T> 泛型委托, Func<T, TResult>,二者是有区别的this

            Action<T> 泛型委托:封装一个方法,该方法只采用一个参数而且不返回值。可使用此委托以参数形式传递方法,而不用显式声明自定义的委托。该方法必须与此委托定义的方法签名相对应。也就是说,封装的方法必须具备一个经过值传递给它的参数,而且不能返回值。固然泛型委托不仅是只能支持一个参数,它最多能够支持四个参数。  spa

          Func<T, TResult> 委托:封装一个具备一个参数并返回 TResult 参数指定的类型值的方法。同理,这里的泛型委托只是接受一个参数的委托,它最多一样支持四个参数。TResult:此委托封装的方法的返回值类型。code

Action T

            还记得上一篇文章中咱们关于委托的定义和声明中,是如何要求的么?委托的安全性很是高,因此在声明委托时,要声明委托返回的类型和参数类型,可是在 Action<T> 上,咱们不须要如此,接下来看一下普通声明和Action<T> 声明的委托有什么不一样对象

        /*
         泛型委托和普通委托的声明对比
         1.不须要使用delegate关键字
         2.Action只能使用返回值为void的方法,若是返回值具备对象类型则报错
         */
        delegate void DisplayMessage(string message);
        static void Main(string[] args)
        {

            DisplayMessage messageTarget;
            messageTarget = ShowWindowsMessage;
            messageTarget("Hello, World!");


            Action<string> messageTarget1;
            messageTarget1 = ShowWindowsMessage;
            messageTarget1("泛型委托");
        }
        public static void ShowWindowsMessage(string s) {
            Console.WriteLine(s);
        }
View Code

         我在注释里加入了一行解释:不须要使用delegate关键字,为何 Action<T> 能够直接声明使用呢?这和其自身封装有关,下面代码就是其在系统中的封装,能够看出来,Action在元数据中就已经存在了public delegate void封装,明确了其使用的范围blog

  //
    // 摘要:
    //     封装一个方法,该方法只有一个参数而且不返回值。
    //
    // 参数:
    //   obj:
    //     此委托封装的方法的参数。
    //
    // 类型参数:
    //   T:
    //     此委托封装的方法的参数类型。此类型参数是逆变。便可以使用指定的类型或派生程度更低的类型。有关协变和逆变的更多信息,请参见泛型中的协变和逆变。
    public delegate void Action<in T>(T obj);
View Code

Func<T, TResult>

        关于Func<T, TResult> 委托,和  Action<T> 委托的区别最大点在于Func<T, TResult>支持返回类型,刚才咱们看了 Action<T> 之后会以为  Action<T>  只能用于void方法,那么若是方法返回int, Action<T> 是否是就不能用了?对的,不能用了。接口

        Func<T,TResult> 的表现形式分为如下几种:开发

      1。Func<T,TResult>文档

      2。Func<T,T1,TResult>

      3。Func<T,T1,T2,TResult>

      4。Func<T,T1,T2,T3,TResult>

      5。Func<T,T1,T2,T3,T4,TResult>

      其实以上的几种表现形式就是Func<T,TResult>的几种重载,最多支持四个参数的重载,分别说一下各个参数的意义,TResult表示 委托所返回值 所表明的类型, T,T1,T2,T3,T4表示委托所调用的方法的参数类型,

如下是使用示例:

  /*
         使用普通委托和泛型委托一样完成一个返回值为string,参数为int方法的委托调用
            */
        delegate string DisplayMessage(int message);
        static void Main(string[] args)
        {
            DisplayMessage messageTarget;
            messageTarget = Kuadi;
            Console.WriteLine(messageTarget(2));
            //Func<T,TResult> 
            Func<int,string>  messageTarget1;
            messageTarget1 = Kuadi;
            Console.WriteLine(messageTarget1(1));
        }
        public static string Kuadi(int zhong) {
            if (zhong == 1)
                return "你的快递";
            else
                return "没有你的货";
        }
View Code

       能够看的出来,泛型委托实际上比起普通委托最大好处就是能够少些不少代码,在之后的代码中能够用泛型委托完成的就不须要使用普通委托去完成,刚才文章中提到了一个委托在linq中得使用,那么linq中如何体现的Action<T> 泛型委托和 Func<T, TResult>泛型委托的呢

Linq中的泛型委托使用

namespace System.Linq
{
    public static class Enumerable
    {
    public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate); 
    }
}

         因为Linq中的方法实在有点多,今天咱们只看一下Where,固然具体实现是看不到,可是咱们在这串代码中却看到了一个身影Func<TSource, bool>这实际上涉及了linq的内部另外一个方法的调用,这串代码所作的事就是把条件做为一个参数传给predicate调用其内部方法,最终返回一个bool值。

       固然了委托用在Liqn中不仅是这么一个地方,还有不少地方都用到了委托,感兴趣的小伙伴能够研究一下,委托在LInq中的使用

相关文章
相关标签/搜索