C#==>匿名方法 【转】

http://blog.csdn.net/gishero/article/details/5161826

1,匿名方法

C#为委托提供一种机制,可以为委托定义匿名方法,匿名方法没有名称,编译器会定指定一个名称

匿名方法中不能使用跳转语句跳转到该匿名方法的外部,也不能跳转到该方法的内部。

也不能在匿名方法外部使用的ref和out参数

  1. //用匿名方法定义委托
  2. class Program
  3. {
  4. delegate string MyDelagate(string val);
  5. static void Main(string[] args)
  6. {
  7. string str1 = " 匿名方法外部 ";
  8. //中括号部分定义来了一个方法,没有名称,编译器会定指定一个名称
  9. MyDelagate my = delegate(string param)
  10. {
  11. string str2 = " 匿名方法内部 ";
  12. return param + str1 + str2;
  13. };
  14. //调用委托的匿名方法
  15. Console.WriteLine(my(" 参数 "));
  16. //从结果可以看到,匿名方法同样达到了为委托定义方法的效果
  17. Console.Read();
  18. }
  19. }

2,匿名方法的【λ(拉姆达)表达式】方式定义

C#3.0之后匿名方法可以使用λ表达式来进行定义

无论是拉姆达(lambda)表达式(事实上应该叫匿名函数)或是匿名类,都能归属到一种叫闭包的东西上面。

λ运算符 =>

左边是参数,使用括号表达 (string param),可以是 (param)这样不定义类型,编译器会推断出来,只有一个参数的时候可以不使用括号

右边是实现代码,使用花括号,如果代码只有一行,则不使用花括号和return关键字也可以,编译器会为我们添加

这是λ表达式的简单实现

string str1 = " 匿名方法外部 ";
string str2 = " 匿名方法内部 ";

MyDelagate my = param => param + str1 + str2;

Console.WriteLine(my(" 参数 "));

3,委托调用过程的协变和抗变

关于委托的返回类型和委托方法的参数传递,如果我们不能正确使用的时候,经常会发生“协变和抗变”的错误。

需要额外注意

返回类型:返回类型需要注意的是协变

方法的返回类型可以派生于委托定义的类型。

参数类型:参数类型需要注意的是抗变

向委托传递的参数类型可以派生于委托方法的参数类型

返回类型的协变

  1. public class A { }
  2. //B继承自A
  3. public class B : A { }
  4. class Program
  5. {
  6. //委托的返回类型是A
  7. public delegate A MyDelegate();
  8. static void Main(string[] args)
  9. {
  10. //向委托添加方法Method
  11. MyDelegate my = Method;
  12. //方法Method的返回类型可以派生于委托定义的返回类型,这就是协变
  13. my();
  14. //※,如果将委托的返回类型,和Method方法的返回类型互换,就会产生编译错误
  15. }
  16. //方法返回一个子类B的类型,B继承自A
  17. static B Method()
  18. {
  19. return new B();
  20. }
  21. }

参数类型的抗变

  1. public class A { }
  2. //B继承自A
  3. public class B : A { }
  4. class Program
  5. {
  6. //委托的返回类型是A
  7. public delegate void MyDelegate(B b);
  8. static void Main(string[] args)
  9. {
  10. //向委托添加方法Method
  11. MyDelegate my = Method;
  12. //向委托传递的参数的类型可以派生于委托方法的参数类型,这就是抗变
  13. my(new B());
  14. //※,如果将委托的参数的类型,和Method方法的参数的类型互换,就会产生编译错误
  15. }
  16. //方法返回一个子类B的类型,B继承自A
  17. static void Method(A a) { }
  18. }

//实际上继承自A的类型B的实例可以转化为A,而子类向父类转化的过程,在默认情况下会有编译错误
//如下代码
A aa = new A();
B bb = new B();
//这句没问题
aa = bb;
//子类向父类转化的过程中存在问题
bb = aa;

以上协变和抗变都是由这个原因产生的

上一篇:c#之反射总结


下一篇:JQuery:通过noConflict()方法同时使用jQuery 和其他框架