首页 > 代码库 > C# Func<>委托
C# Func<>委托
以前我们为了能够调用一个方法,必须比照这个方法定义一个相应的delegate.
原先我们定义delegate
// 委托声明 -- 定义一个签名: delegate doubleMathAction(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
此委托封装的方法的参数类型。
TR
此委托封装的方法的返回值类型。
在使用 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雷同,这里就不在说了。希望自己的总结可以对大家有所帮助。