您的位置:首页 > 编程语言 > C#

C#中的委托,匿名方法、泛型委托和Lambda表达式表达式演变过程

2011-10-14 15:40 246 查看
我为了更好的理解C#中的委托,、泛型委托、匿名方法和Lambda表达式,我把它们的演变过程通过自己的理写了出来,各位高手要是看到有什么不妥的地方,还望指出。

首先,我从一个C语言中很简单的一个问题开始,比较两个数的大小,并将最大的数以string 型输出

首先来看比较常规的写法:

public delegate string DelegateCompare(int Num1,int Num2); //定义委托

class Compare

{

public static string NumCompare(int Num1, int Num2)

{

return Num1 > Num2 ? Num1.ToString() : Num2.ToString();

}

}

class CompareApplication

{

static void Main()

{

DelegateCompare delegate1 = new DelegateCompare(Compare.NumCompare);

string STR = "最大的数位:" + delegate1(10, 20);

Console.WriteLine(STR);

Console.ReadLine();

}

}

为了精简代码(当然这个理由似乎不够充分),我们决定使用匿名方法,也许这里你并不能看到匿名方法的真正好处,但是,当把.NET方法做为委托参数时或处理时间时,就能看到匿名方法的真正用处。下面是贴过来的代码:

public delegate string DelegateCompare(int Num1,int Num2); //定义委托

class CompareApplication

{

static void Main()

{

DelegateCompare delegate1 = new DelegateCompare(delegate(int Num1, int Num2) {

return Num1 > Num2 ? Num1.ToString() : Num2.ToString();

});

string STR = "最大的数位:" + delegate1(10, 20);

Console.WriteLine(STR);

Console.ReadLine();

}

}

正如你所见到的一样,我把Compare类完全删除了,那比较大小的功能是通过什么完成的了,这就是匿名方法,通过delegate关键字,我们声明了一个没有方法名的方法体。

接下来我有个大胆的想法,将委托声明也去掉,这时就应该用到泛型委托

class CompareApplication

{

static void Main()

{

Func<int, int, string> delegate1 = new Func<int, int, string>(delegate(int Num1, int Num2)

{

return Num1 > Num2 ? Num1.ToString() : Num2.ToString();

});

string STR = "最大的数位:" + delegate1(10, 20);

Console.WriteLine(STR);

Console.ReadLine();

}

}

在上面的代码中,我将委托的声明全部用Func<int, int, string>替代掉了,我先分析一下该表达式如何得来,先看我们的委托是如何定义的:

public delegate string DelegateCompare(int Num1,int Num2),从委托的声明中我们得知,绑定到该委托的方法必须具有两个int型参数并且其返回值类型为string,那么泛型委托Func<int, int, string>的得来就一目了然了。

这时,所有的代码都集中在一个函数里了,够精简了,还能不能更加精简了,好,这时候lambda表达式出场了

class CompareApplication

{

static void Main()

{

Func<int, int, string> delegate1 = (x, y) => x > y ? x.ToString() : y.ToString();

string STR = "最大的数位:" + delegate1(10, 20);

Console.WriteLine(STR);

Console.ReadLine();

}

}

我们一定能看出来,这里面最重要的就是这句:Func<int, int, string> delegate1 = (x, y) => x > y ? x.ToString() : y.ToString()。我想我有必要把这句话完整的解释一遍,首先我想知道这句话干了点啥事,它做的事还真不少,定义委托、方法绑定、方法定义,这三件事一气呵成。首先来看委托的定义:Func<int, int, string>
delegate1,这段代码告诉我们,我们定义了一个可以绑定具有两个int型参数并且其返回类型为string型的方法的委托,接下来看等号右边,这里就是一个lambda表达式,lambda表达式可以看作是一个匿名方法,以“=>”运算符为标志,“=>”左边部分为传入,该匿名方法的两个参数,注意,这两个参数我们没有声明类型,但编译器会根据前面泛型委托的定义自动推断出其参数类型(返回值类型是同样的原理)。“=>”右边为返回值。

好了,上面就是我对这些概念的理解。本人是个初学者,还请各位高手多多指教。

补充几点:

只有在 Lambda 有一个输入参数时,括号才是可选的;否则括号是必需的。 两个或更多输入参数由括在括号中的逗号分隔

有时,编译器难于或无法推断输入类型。 如果出现这种情况,您可以按以下示例中所示方式显式指定类型:(int
x, string s) => s.Length > x

使用空括号指定零个输入参数:()
=> SomeMethod()

Lambda 语句与 Lambda 表达式类似,只是语句括在大括号中:

(input parameters) => {statement;}

Lambda 语句的主体可以包含任意数量的语句;但是,实际上通常不会多于两个或三个语句。

delegate void TestDelegate(string s);
…
TestDelegate myDel = n => { string s = n + " " + "World"; Console.WriteLine(s); };
myDel("Hello");

在编写 Lambda 时,通常不必为输入参数指定类型,因为编译器可以根据
Lambda 主体、基础委托类型以及 C# 语言规范中描述的其他因素推断类型。

Lambda 的一般规则如下:

Lambda 包含的参数数量必须与委托类型包含的参数数量相同。

Lambda 中的每个输入参数必须都能够隐式转换为其对应的委托参数。

Lambda 的返回值(如果有)必须能够隐式转换为委托的返回类型。

请注意,Lambda 表达式本身没有类型,因为常规类型系统没有“Lambda 表达式”这一内部概念。但是,有时会不正式地论及 Lambda 表达式的“类型”。 在这些情况下,类型是指委托类型或 Lambda 表达式所转换为的 Expression 类型。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐