zoukankan      html  css  js  c++  java
  • 委托学习总结(三)泛型委托

    之前,我们学习总结了委托这个概念,也阐述了委托,匿名方法,lambda表达式三者之间的关系,那么今天再来继续学习委托更深层次的东西:泛型委托,什么是泛型,这个概念我也会在之后做出总结,这里不做很深层次的讨论,重点是讨论泛型和委托如何配合使用,其实泛型这个概念在这里也不会对我们对委托的理解有太大的影响,我们只要大概知道泛型就是一种动态的类型,它在使用时可以代表任意类型,下面我们再来回顾一下我们是如何定义普通委托的:

    public delegate int 委托名(int a, int b);

    这是委托的定义,它的定义有这几个特点,(1)可以用访问修饰符修饰。(2)delegate关键字。(3)有返回值和参数。

    我们之前也说了,委托是一种类型,与之对应的方法必须和它具有相同的签名,即相同的参数个数,相同的参数类型和相同的返回值类型。我们回顾了普通委托之后再来看一下泛型委托的定义:

    public delegate T 委托名<T>(T a, T b);

    与之前不同的是,我们把int类型变成了万能的T类型,这样写的好处是什么呢?
    可以想象,我们之前写了这样一个方法来处理加减乘除不同的计算方法:

        static void Calculate(Expression ex, int a, int b)
            {
                Console.WriteLine(ex(a, b) + "
    ");
            }    

    仔细的你会发现我们封装的这个方法有很大的局限性,假如我们某天要计算Double,float小数类型或者其他类型的加减乘除时,我们是不是又不得不重载多个不同参数类型的Calculate方法,即:

    复制代码
        static void Calculate(Expression ex, double a, double b)
            {
                Console.WriteLine(ex(a, b) + "
    ");
            }
    
        static void Calculate(Expression ex, float a, float b)
            {
                Console.WriteLine(ex(a, b) + "
    ");
            }
    复制代码

    这样的话是不是代码又有重复了,那假设又几千种不同的类型要去计算呢?我们能不能只写一个方法就处理不同类型的加减乘除呢?这时,C#里有一个重要的工具:泛型的作用就体现出来了,我们可以把委托和方法定义成泛型的。代码如下:

    复制代码
        public delegate T Expression<T>(T a, T b);
        class Program
        {
            static void Main(string[] args)
            {
                Expression<int> add = (a, b) => a + b;
                Calculate(add, 10, 25);
                Console.ReadKey();
            }
            static void Calculate<T>(Expression<T> ex, T a, T b)
            {
                Console.WriteLine(ex(a, b) + "
    ");
            }     
        }
    复制代码

    我们只需在声明委托Expression<>时,为委托定义int类型就可以了,假如有一天,我要定义double类型,同理只需把Expression<int>换成Expression<double>即可,这样写是不是既节省了代码,又让Calculate方法的灵活性变高了。不管是lambda表达式还是泛型,微软可谓把DRY(Don't-repeat-yourself)原则发挥的淋漓尽致,其实微软早已为我们定义好了一套泛型委托供我们使用,以免我们在自己使用时还繁琐重复的去定义它,他们分别是Action,Func和Predicate

    这是我在资料上摘取的这几个委托的区别:

    (1). Action

           Action是无返回值的泛型委托。

       Action 表示无参,无返回值的委托

       Action<int,string> 表示有传入参数int,string无返回值的委托

       Action<int,string,bool> 表示有传入参数int,string,bool无返回值的委托

           Action<int,int,int,int> 表示有传入4个int型参数,无返回值的委托

       Action至少0个参数,至多16个参数,无返回值。

     (2). Func

       Func是有返回值的泛型委托

       Func<int> 表示无参,返回值为int的委托

       Func<object,string,int> 表示传入参数为object, string 返回值为int的委托

       Func<object,string,int> 表示传入参数为object, string 返回值为int的委托

       Func<T1,T2,,T3,int> 表示传入参数为T1,T2,,T3(泛型)返回值为int的委托

       Func至少0个参数,至多16个参数,根据返回值泛型返回。必须有返回值,不可void

    (3). Predicate

       predicate 是返回bool型的泛型委托

       predicate<int> 表示传入参数为int 返回bool的委托

       Predicate有且只有一个参数,返回值固定为bool

    一般的需求下,我们就使用微软定义的委托就足够了,这样减少了我们对委托的重复定义,可能有部分初学者见到Func<>,Action<>这样的代码肯定会很懵比,这只是你对新东西陌生罢了,多结合实例敲几遍,自然就会用了,它们其实就是微软封装定义好了的委托,没有什么特别的。我们上面的代码也可以这样写:

    复制代码
        class Program
        {
            static void Main(string[] args)
            {
                Func<int,int,int> add = (a, b) => a + b;
                Calculate(add, 10, 25);
                Console.ReadKey();
            }
            static void Calculate<T, Y, U>(Func<T, Y, U> ex, T a, Y b)
            {
                Console.WriteLine(ex(a, b) + "
    ");
            }
        }
    复制代码

    这样写用Func就省去了定义委托这一步。

    同样,其实在我们的webform,winform框架中,微软也给我们规范了一个委托的定义:

    delegate void EvenHandler(object sender, EventArgs e);

    都知道上面的object类是所有类型的基类,那EventArgs类呢?它其实就是所有包含事件数据类的基类,那什么是事件呢?,之后的学习总结中,我们来解谜C#另一个扑朔迷离的东西:事件

    引用地址:http://www.cnblogs.com/ruanraun/p/6044477.html

  • 相关阅读:
    pipelinewise 学习二 创建一个简单的pipeline
    pipelinewise 学习一 docker方式安装
    Supercharging your ETL with Airflow and Singer
    ubuntu中使用 alien安装rpm包
    PipelineWise illustrates the power of Singer
    pipelinewise 基于singer 指南的的数据pipeline 工具
    关于singer elt 的几篇很不错的文章
    npkill 一个方便的npm 包清理工具
    kuma docker-compose 环境试用
    kuma 学习四 策略
  • 原文地址:https://www.cnblogs.com/Arlar/p/6092723.html
Copyright © 2011-2022 走看看