• C# Func<>委托


       委托是一种类型,由关键字delegate声明。确切的说,委托是一种可用于封装命名或者匿名方法的引用类型。  它类似于 C++ 中的函数指针,而且是类型安全和可靠的。

      委托类型的声明与方法签名相似,有一个返回值和任意数目任意类型的参数。必须使用具有兼容返回类型和输入参数的方法或 lambda 表达式实例化委托。下面给出了委托声明及实例化的示例代码:

    原先我们定义delegate

    [csharp] view plain copy
     
     print?
    1. // 委托声明 -- 定义一个签名:  
    2. delegate double MathAction(double num);  
    3. class DelegateTest  
    4. {  
    5.     // 符合委托声明的常规方法  
    6.     static double Double(double input)  
    7.     {  
    8.         return input * 2;  
    9.     }  
    10.    
    11.     static void Main()  
    12.     {  
    13.       // 使用一个命名方法实例化委托类型  
    14.         MathAction ma = Double;  
    15.    
    16.         // 调用委托实例  
    17.         double multByTwo = ma(4.5);  
    18.         Console.WriteLine(multByTwo);  
    19.    
    20.      // 再用匿名方法来实例化委托类型  
    21.         MathAction ma2 = delegate(double input)  
    22.         {  
    23.             return input * input;  
    24.         };  
    25.    
    26.         double square = ma2(5);  
    27.         Console.WriteLine(square);  
    28.    
    29.       // 最后用Lambda表达式来实例化委托类型  
    30.         MathAction ma3 = s => s * s * s;  
    31.         double cube = ma3(4.375);  
    32.    
    33.         Console.WriteLine(cube);  
    34.     }  
    35. }  

     

    .NETFramework 3.5中,提供了两类通用的delegate

    如果方法有返回值,则使用Func,或者Func<>

    如果方法没有返回值,则使用Action,或者Action<>

    Func<T,TR>(T arg)

    参数类型

    T

    此委托封装的方法的参数类型。

    TR

    此委托封装的方法的返回值类型。

     

    参数

    arg
    类型 T
     
    此委托封装的方法的参数。

     

     

    在使用 Func<T,TResult>委托时,不必显式定义一个封装只有一个参数的方法的委托。以下示例简化了此代码,它所用的方法是实例化 Func<T, TResult>委托,而不是显式定义一个新委托并将命名方法分配给该委托。

     

    使Func<>委托,我们这样写

     1 using System;
     2 
     3 public class GenericFunc
     4 {
     5    public static void Main()
     6    {
     7       // 依旧是用命名方法实例化委托类型
     8       Func<string, string> convertMethod = UppercaseString;
     9       string name = "Dakota";
    10       // 依旧是通过委托实例调用该方法
    11       Console.WriteLine(convertMethod(name));
    12    }
    13 
    14    private static string UppercaseString(string inputString)
    15    {
    16       return inputString.ToUpper();
    17    }
    18 }
    复制代码
     

    您也可以按照以下示例所演示的那样在 C# 中将 Func<T, TResult> 委托与匿名方法一起使用。

    复制代码
     1 using System;
     2 
     3 public class Anonymous
     4 {
     5    public static void Main()
     6    {
     7       Func<string, string> convert = delegate(string s)
     8          { return s.ToUpper();}; 
     9 
    10       string name = "Dakota";
    11       Console.WriteLine(convert(name));   
    12    }
    13 }
    复制代码
     
     

     

    您还可以按照以下示例所演示的那样将 lambda 表达式分配给 Func<T, TResult> 委托。

    复制代码
     1 using System;
     2 
     3 public class LambdaExpression
     4 {
     5    public static void Main()
     6    {
     7       Func<string, string> convert = s => s.ToUpper();
     8 
     9       string name = "Dakota";
    10       Console.WriteLine(convert(name));   
    11    }
    12 }
    复制代码

    Lambda 表达式的基础类型是泛型 Func 委托之一。  这样能以参数形式传递 lambda 表达式,而不用显式将其分配给委托。  尤其是,因为 System.Linq 命名空间中许多类型方法具有 Func<T, TResult> 参数,因此可以给这些方法传递 lambda 表达式,而不用显式实例化 Func<T, TResult> 委托。

     

    Func委托是system下的全局函数,不用我们自定,系统自定义的,供我们使用,带有多个重载.

    这里我们除了使用Func委托外,还是用了Labdab表达式.这里我再谈谈这个表达式.

    Lambda表达式的基础类型是泛型 Func委托之一。 这样能以参数形式传递 lambda表达式,而不用显式将其分配给委托。 尤其是,因为 System.Linq命名空间中许多类型方法具有Func<T, TResult>参数,因此可以给这些方法传递 lambda表达式,而不用显式实例化 Func<T, TResult>委托。

     

    如果前面的解析看的不是很清楚,相信最后这个实例能够让你更加明白Func委托是多么有意思。

    下面的示例演示如何声明和使用 Func<T, TResult> 委托。  此示例声明一个 Func<T, TResult> 变量,并为其分配了一个将字符串中的字符转换为大写的 lambda 表达式。  随后将封装此方法的委托传递给 Enumerable.Select方法,以将字符串数组中的字符串更改为大写。

    复制代码
     1 using System;
     2 using System.Collections;
     3 using System.Collections.Generic;
     4 using System.Linq;
     5 
     6 static class Func
     7 {
     8    static void Main(string[] args)
     9    {
    10       // 声明了一个Func委托类型的变量selector并用Lambda表达式进行实例化 
    11       // 这个Lambda表达式将用来获取一个字符串并将这个字符串转化为大写并返回
    12       Func<string, string> selector = str => str.ToUpper();
    13 
    14       // 创建一个字符串数组
    15       string[] words = { "orange", "apple", "Article", "elephant" };
    16       // 依次遍历这个字符串数组并调用委托实例selector进行处理
    17       IEnumerable<String> aWords = words.Select(selector);
    18 
    19       // 输出结果到控制台
    20       foreach (String word in aWords)
    21          Console.WriteLine(word);
    22    }
    23 }      
    24 /*
    25 This code example produces the following output:
    26 
    27    ORANGE
    28    APPLE
    29    ARTICLE
    30    ELEPHANT
    31 */
    复制代码

    通过委托和Lambda表达式及Func<>特性的结合,可以看出他们带给代码多么大的改变,不仅让我们的代码更加简洁,更让我们的代码执行起来更加高效灵活。

     

    三种委托写法对比

     

    [csharp] view plain copy
     
     print?
    1. using System;  
    2. using System.Collections.Generic;  
    3. using System.Linq;  
    4. using System.Text;  
    5.    
    6. namespace func  
    7. {  
    8. //委托声明 -- 定义一个签名:  
    9. delegate double MathAction(double num);  
    10. public class Program  
    11. {  
    12. // 符合委托声明的常规方法  
    13. static double Double(double input)  
    14. {  
    15. return input * 2;  
    16. }  
    17.    
    18. static void Main(string[] args)  
    19. {  
    20. // 使用一个命名方法实例化委托类型  
    21. /* 
    22.  * 写法一,需要写出专门委托的函数,还需要自定义委托 
    23.  **/  
    24. MathAction ma = Double;//注意这里千万不可有Double(),否则就成了一个返回类型,是报错的,这里是制定函数的地址,给定的是函数的地址  
    25.    
    26. //调用委托  
    27. double result1 = ma(4.5);  
    28.    
    29. //使用系统自定义委托实例化委托类型  
    30. /* 
    31.  * 写法二,需要写出专门委托的函数,不需要自定义委托,使用系统委托 
    32.  **/  
    33. Func<double,double> func = Double;  
    34.    
    35. //调用委托  
    36. double result2 = func(4.5);  
    37.    
    38. //系统委托使用lamdba进行传递参数  
    39. /* 
    40.  * 写法三,不需要写出专门委托的函数,还需要自定义委托 
    41.  **/  
    42. Func<doubledouble> result = s=> s * 2;//写法还可以换成lamdba语句块,适应多个参数的写法  
    43.    
    44. double result3=result(4.5);  
    45.    
    46. Func<double,double> result4 = s =>  
    47. {  
    48. return s * 2;  
    49. };  
    50.    
    51. Console.WriteLine(result1);  
    52. Console.WriteLine(result3);  
    53. Console.WriteLine(result2);  
    54. Console.WriteLine(result4(4.5));  
    55. }   
    56. }  
    57.    
    58. }  

    效果图

     

    同样的输出效果,但是编写代码的质量确有不同。Func的委托中,它简化了我们自己定义委托带来的繁琐,同时它更好的结合了Lamdba的使用,减少了自定义函数的作用,同时也是有缺点的,就是错误的出现不容易发现是那里。如果不是对这个很熟悉,很容易造成出现问题,如从着手错误的源泉。匿名函数的写法解决的这个问题。但是匿名函数却没有Lamdba简便。Action委托的使用与Func雷同。

  • 相关阅读:
    NYOJ 91 阶乘之和
    NYOJ 47 过河问题
    NYOJ 12 喷水装置(二)
    NYOJ 78 圈水池(凸包问题)
    NYOJ 523 亡命逃窜( bfs )
    NYOJ 564 最优对称路径(湖南省第七届大学生计算机程序设计竞赛)
    NYOJ 491 幸运三角形(bitset)
    排列组合 C(n,k)= C(n1)+C(n1,k1) 对应于杨辉三角
    Android (服务Service)
    Android (界面编程#5ProgressDialog)
  • 原文地址:https://www.cnblogs.com/wyongqi/p/7483748.html
Copyright © 2020-2023  润新知