C# 2.0 Specification(匿名方法)(二)

原创 2004年03月05日 13:41:00

21.7委托实例相等性

如下规则适用由匿名方法委托实例的相等运算符(§7.9.8)object.Equals方法产生的结果。

l         当委托实例是由具有相同被捕获外部变量集合的语义相同的匿名方法表达式计算而产生时,可以说(但不是必须)它们相等。

l         当委托实例由具有语义不同的匿名方法表达式,或具有不同的被捕获外部变量集合时,它们决不相等。

<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 

21.8明确赋值

匿名方法参数的明确赋值状态与命名方法是相同的。也就是,引用参数和值参数被明确的赋初值,而输出参数不用赋初值。并且,输出参数在匿名方法正常返回之前必须被明确赋值(§5.1.6)

当控制转换到匿名方法表达式的程序块时,对外部变量v的明确赋值状态,与在匿名方法表达式之前的v的明确赋值状态是相同的。也就是,外部变量的明确赋值将从匿名方法表达式上下文被继承。在匿名方法程序块内,明确赋值将和在普通程序块内一样而得到演绎(§5.3.3)

在匿名方法表达式之后的变量v的明确赋值状态与在匿名方法表达式之前它的明确赋值状态相同。


例如

delegate bool Filter(int i);

void F() {
  int max;

  // 错误,max没有明确赋值
  Filter f = delegate(int n) { return n < max; }

  max = 5;
  DoWork(f);
}

将产生一个编译时错误,因为max没有在匿名方法声明的地方明确赋值。示例

delegate void D();

void F() {
  int n;
  D d = delegate { n = 1; };

  d();

  //错误,n没有明确赋值
  Console.WriteLine(n);
}

也将产生一个编译时错误,因为匿名方法内n的赋值,对于该匿名方法外部n的明确赋值状态没有效果。

21.9方法组转换

与在§21.3中描述的隐式匿名方法转换相似,也存在从方法组(§7.1)到兼容的委托类型的隐式转换。

对于给定的方法组E和委托类型D,如果允许new D(E)形式的委托创建表达式(§7.5.10.3 §20.9.6),那么就存在从ED的隐式转换,并且转换的结果恰好等价于new D(E)

在以下示例中

using System;
using System.Windows.Forms;

class AlertDialog
{
  Label message = new Label();
  Button okButton = new Button();
  Button cancelButton = new Button();`


 

  public AlertDialog() {
      okButton.Click += new EventHandler(OkClick);
      cancelButton.Click += new EventHandler(CancelClick);
      ...
  }

  void OkClick(object sender, EventArgs e) {
      ...
  }

  void CancelClick(object sender, EventArgs e) {
      ...
  }
}

构造函数用new创建了两个委托实例。隐式方法组转换允许将之简化为

public AlertDialog() {
    okButton.Click += OkClick;
    cancelButton.Click += CancelClick;
    ...
}

对于所有其他隐式和显式的转换,转换运算符可以用于显式地执行一个特定的转换。为此,示例

object obj = new EventHandler(myDialog.OkClick);

可被代替写成如下的样子。

object obj = (EventHandler)myDialog.OkClick;

方法组合匿名方法表达式可以影响重载决策(overload resolution,但它们并不参与类型推断。请参见§20.6.4获取更详细的信息。

 

21.10实现例子

本节以标准C#的构件形式描述匿名方法的可能实现。在这里描述的实现基于Microsoft C#编译器所采用的相同原则,但它决不是强制性的或唯一可能的实现。

本节的后面部分给出了几个示例代码,它包含了具有不同特性的匿名方法。对于每个例子,我们将提供使用唯一标准C#构件的代码的对应转换。在这些例子中,标识符D假定表示如下委托类型。

public <?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />delegate void D();


匿名方法的最简形式就是没有捕获外部变量的那个。

class Test
{
    static void F() {
        D d =
del
egate { Console.WriteLine("test"); };
    }
}

这段代码可被转换到一个引用编译器生成的静态方法的委托实例,而匿名方法的代码将会放入到该静态方法中。、

class Test
{
  static void F() {
      D d = new D(__Method1);
  }

  static void __Method1() {
      Console.WriteLine("test");
  }
}

 

在下面的示例中,匿名方法引用this的实例成员。

class Test
{
  int x;

  void F() {
      D d = delegate { Console.WriteLine(x); };
  }
}

this可以被转换到由编译器生成的包含匿名方法代码的实例方法。

class Test
{
  int x;

  void F() {
      D d = new D(__Method1);
  }

  void __Method1() {
      Console.WriteLine(x);
  }
}

在这个例子中,匿名方法捕获了一个局部变量。


 

class Test
{
    void F() {
        int y = 123;
        D d = delegate { Console.WriteLine(y); };
    }
}

该局部变量的生存期现在至少必须延长到匿名方法委托的生存期为止。这可以通过将局部变量“提升(lifting)”为编译器生成的(compiler-generated)类的字段来完成。局部变量的实例化对应于创建一个编译器生成的类的实例,而访问局部变量将对应于访问编译器生成的类实例的一个字段。并且,匿名方法将成为编译器生成类的实例方法。

class Test
{
  void F() {
      __locals1 = new __Locals1();
      __locals1.y = 123;
      D d = new D(__locals1.__Method1);
  }

  class __Locals1
  {
      public int y;

      public void __Method1() {
          Console.WriteLine(y);
      }
  }
}

最后,如下匿名方法将捕获this,以及具有不同生存期的两个局部变量。

class Test
{
  int x;

  void F() {
      int y = 123;
      for (int i = 0; i < 10; i++) {
          int z = i * 2;
          D d = delegate { Console.WriteLine(x + y + z); };
      }
  }
}

 

在这里,编译器将为每个语句块生成类,在这些语句块中局部变量将被捕获,而在不同块中的局部变量将会有独立的生存期。


__Locals2的实例,编译器为内部语句块生成的类,包含局部变量z和引用__Locals1实例的字段。__Locals1的实例,编译器为外部语句块生成的类,包含局部变量y和引用封闭函数成员的this的字段。通过这些数据结构,你可以通过__Locals2的一个实例到达所有被捕获的局部变量,并且匿名方法的代码可以作为那个类的实例方法而实现。

class Test
{
  void F() {
      __locals1 = new __Locals1();
      __locals1.__this = this;
      __locals1.y = 123;
      for (int i = 0; i < 10; i++) {
          __locals2 = new __Locals2();
          __locals2.__locals1 = __locals1;
          __locals2.z = i * 2;
          D d = new D(__locals2.__Method1);
      }
  }

  class __Locals1
  {
      public Test __this;
      public int y;
  }

  class __Locals2
  {
      public __Locals1 __locals1;
      public int z;

      public void __Method1() {
          Console.WriteLine(__locals1.__this.x + __locals1.y + z);
      }
  }
}

 (匿名方法完)

C# 2.0 Specification(匿名方法)(一)

21匿名方法21.1.匿名方法表达式匿名方法表达式(anonymous-method-expression)定义了匿名方法(anonymous method),它将计算为引用该方法的一个具体值。l  ...
  • tlping
  • tlping
  • 2004年03月05日 13:36
  • 801

C# 2.0 Specification(二)

(接上)这篇文章是翻译的微软的技术文章.供学习c#的朋友参考,请勿用于商业目的。http://msdn.microsoft.com/vcsharp/team/language/default.aspx...
  • tlping
  • tlping
  • 2004年02月27日 10:15
  • 651

.Net 2.0 新功能:匿名方法(Anonymous Methods)

匿名方法(Anonymous Methods)1.       在2.0之前的c#版本中,声明委托的唯一方法是使用命名方法。this.Load+= new System.EventHandler(th...
  • edisundong
  • edisundong
  • 2007年09月03日 15:55
  • 2526

C# 2.0 Specification(迭代器)(二)

22.4 yield 语句yield语句用于迭代器块以产生一个枚举器对象值,或表明迭代的结束。embedded-statement:(嵌入语句)...yield-statement(yield语句)y...
  • tlping
  • tlping
  • 2004年03月08日 11:32
  • 1005

USB 2.0 Specification

USB 2.0 SpecificationUniversal Serial Bus Revision 2.0 specification (.zip file format, size 9.73 MB...
  • yangchun301
  • yangchun301
  • 2007年12月22日 11:39
  • 2308

关于C#匿名方法

作者  陈嘉栋(慕容小匹夫) 阅读目录 0x00 前言0x01 不必构造委托对象0x02 匿名方法初探0x03 使用匿名方法省略参数0x04 匿名方法和闭包0x05 匿名方法如何捕获外部变...
  • cxihu
  • cxihu
  • 2016年09月02日 15:54
  • 863

c# 匿名方法传参数 和有返回值

delegate void CountIt(int end); CountIt count = delegate(int end) { for...
  • ssihc0
  • ssihc0
  • 2010年02月21日 15:46
  • 2661

C#匿名方法之循环注册问题

C#匿名方法之循环注册问题 Demo: void Demo() { List list = new List(); for (int i = 0; i ...
  • leo_wc
  • leo_wc
  • 2017年05月15日 12:50
  • 159

C# Version 2.0 Specification

 Copyright  Microsoft Corporation 1999-2003. All Rights Reserved.C# Version 2.0 Specification July ...
  • WhenTrue
  • WhenTrue
  • 2007年01月11日 09:28
  • 967

C# 2.0 Specification (四)

这段比较短就先干掉了:)23不完整类型23.1不完整类型声明新类型修饰符partial 用于在多个部分中定义一个类型。为了确保和现存程序的兼容性,这个修饰符和其他修饰符(比如get和set)是不同的,...
  • tlping
  • tlping
  • 2004年02月29日 18:54
  • 607
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C# 2.0 Specification(匿名方法)(二)
举报原因:
原因补充:

(最多只允许输入30个字)