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#另一个扑朔迷离的东西:事件

    转自https://www.cnblogs.com/ruanraun/p/6044477.html 

  • 相关阅读:
    JS函数
    函数与指针
    函数返回指针类型(strchr函数)
    二维数组求平均值(指针的使用)
    二维数组做函数参数传递
    指针与函数
    Ubuntu安装mysql步骤
    带参程序
    函数返回值是指针
    mystrcat
  • 原文地址:https://www.cnblogs.com/asdyzh/p/9858288.html
Copyright © 2011-2022 走看看