C# Func<>委托

来源:互联网 发布:网络运维服务承诺书 编辑:程序博客网 时间:2024/05/29 08:40

以前我们为了能够调用一个方法,必须比照这个方法定义一个相应的delegate.

原先我们定义delegate

// 委托声明 -- 定义一个签名:delegate double MathAction(double num);class DelegateTest{    // 符合委托声明的常规方法    static double Double(double input)    {        return input * 2;    }     static void Main()    {     原版:   // 使用一个命名方法实例化委托类型        MathAction ma = Double;         // 调用委托实例        double multByTwo = ma(4.5);        Console.WriteLine(multByTwo);     简化版1:   // 再用匿名方法来实例化委托类型        MathAction ma2 = delegate(double input)        {            return input * input;        };         double square = ma2(5);        Console.WriteLine(square);      简化版2:  // 最后用Lambda表达式来实例化委托类型        MathAction ma3 = s => s * s * s;        double cube = ma3(4.375);         Console.WriteLine(cube);    }}

这个是否能有更好的实现办法呢?

答案是:肯定有了.也就是有通用的delegate了。在.NETFramework 3.5中,提供了两类通用的delegate

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

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

Func<T,TR>(T arg)

参数类型

T

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

TR

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

参数

arg
类型 T

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

 

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


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

using System;public classLambdaExpression{   public static void Main()   {       Func<string, string> convert = s=> s.ToUpper();//该方法将小写字母转为大写      string name = "Dakota";      Console.WriteLine(convert(name));     }}

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

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

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

下面一行代码将生成一个序列,其中包含 numbers 数组中在 9左侧的所有元素,因为它是序列中第一个不满足条件的数字:

int[] n= { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };var firstNumbersLessThan6 = numbers.TakeWhile(n => n < 6);

实例2

var firstSmallNumbers =numbers.TakeWhile((n, index) => n >= index);

此示例展示了如何通过将输入参数括在括号中来指定多个输入参数。该方法将返回数字数组中的所有元素,直至遇到一个值小于其位置的数字为止。不要将 lambda运算符 (=>)与大于等于运算符 (>=)混淆。

 

三种委托写法对比

using System;using System.Collections.Generic;using System.Linq;using System.Text; namespace func{//委托声明 -- 定义一个签名:delegate double MathAction(double num);public class Program{// 符合委托声明的常规方法static double Double(double input){return input * 2;} static void Main(string[] args){// 使用一个命名方法实例化委托类型/* * 写法一,需要写出专门委托的函数,还需要自定义委托 **/MathAction ma = Double;//注意这里千万不可有Double(),否则就成了一个返回类型,是报错的,这里是制定函数的地址,给定的是函数的地址 //调用委托double result1 = ma(4.5); //使用系统自定义委托实例化委托类型/* * 写法二,需要写出专门委托的函数,不需要自定义委托,使用系统委托 **/Func<double,double> func = Double; //调用委托double result2 = func(4.5); //系统委托使用lamdba进行传递参数/* * 写法三,不需要写出专门委托的函数,还需要自定义委托 **/Func<double, double> result = s=> s * 2;//写法还可以换成lamdba语句块,适应多个参数的写法 double result3=result(4.5); Func<double,double> result4 = s =>{return s * 2;}; Console.WriteLine(result1);Console.WriteLine(result3);Console.WriteLine(result2);Console.WriteLine(result4(4.5));} } }


效果图


 

同样的输出效果,但是编写代码的质量确有不同。当然了也是要对自己的问题进行负责的。lamdba的使用简化的代码,但是如果自己不是对这个很熟悉,很容易造成出现问题,如从着手错误的源泉。匿名函数的写法解决的这个问题。但是匿名函数却没有Lamdba简便。这就是折中方法吧。看自己更喜欢哪种了。

 

小结:

Func的委托中,我们可以看出,它简化了我们自己定义委托带来的繁琐,同时它更好的结合了Lamdba的使用。减少了自定义函数的作用。同时也是有缺点的,就是错误的出现不容易发现是那里。Action委托的使用与Func雷同,这里就不在说了。希望自己的总结可以对大家有所帮助。

 

12 0
原创粉丝点击