C# 2.0-Spezifikation (anonyme Methode) (2)

黄舟
Freigeben: 2017-01-03 11:58:17
Original
1355 Leute haben es durchsucht

21.7 Delegateninstanzgleichheit

Die folgenden Regeln gelten für Ergebnisse, die vom Gleichheitsoperator (§7.9.8) und der Methode „object.Equals“ anonymer Methodendelegateninstanzen erzeugt werden.
l Wenn Delegateninstanzen aus der Auswertung semantisch identischer anonymer Methodenausdrücke mit demselben Satz erfasster externer Variablen resultieren, gelten sie als gleich (müssen aber nicht sein).
l Wenn Delegateninstanzen durch anonyme Methodenausdrücke mit unterschiedlicher Semantik oder mit unterschiedlichen Sätzen erfasster externer Variablen dargestellt werden, sind sie niemals gleich.

21.8 Explizite Zuweisung

Der explizite Zuweisungsstatus anonymer Methodenparameter ist der gleiche wie der benannter Methoden. Das heißt, Referenzparametern und Wertparametern werden explizit Anfangswerte zugewiesen, während Ausgabeparametern keine Anfangswerte zugewiesen werden müssen. Außerdem müssen Ausgabeparameter explizit zugewiesen werden, bevor die anonyme Methode normal zurückkehrt (§5.1.6).
Wenn die Steuerung an den Programmblock des anonymen Methodenausdrucks übergeben wird, ist der explizite Zuweisungsstatus der externen Variablen v derselbe wie der explizite Zuweisungsstatus von v vor dem anonymen Methodenausdruck. Das heißt, explizite Zuweisungen an externe Variablen werden vom Kontext des anonymen Methodenausdrucks geerbt. Innerhalb anonymer Methodenblöcke werden explizite Zuweisungen wie innerhalb gewöhnlicher Blöcke abgeleitet (§5.3.3).
Der explizite Zuweisungsstatus der Variablen v nach dem anonymen Methodenausdruck ist derselbe wie ihr expliziter Zuweisungsstatus vor dem anonymen Methodenausdruck.

Beispielsweise generiert

delegate bool Filter(int i);
void F() {
int max;
// 错误,max没有明确赋值
Filter f = delegate(int n) { return n < max; }
max = 5;
DoWork(f);
}
Nach dem Login kopieren

einen Fehler bei der Kompilierung, da max nicht explizit dort zugewiesen wird, wo die anonyme Methode deklariert ist. Beispiel

delegate void D();
void F() {
int n;
D d = delegate { n = 1; };
d();
//错误,n没有明确赋值
Console.WriteLine(n);
}
Nach dem Login kopieren

generiert ebenfalls einen Fehler bei der Kompilierung, da die Zuweisung von n innerhalb der anonymen Methode keinen Einfluss auf den expliziten Zuweisungsstatus von n außerhalb der anonymen Methode hat.

21.9 Methodengruppenkonvertierung

Ähnlich wie bei der in §21.3 beschriebenen impliziten anonymen Methodenkonvertierung gibt es auch eine implizite Konvertierung von einer Methodengruppe (§7.1) in einen kompatiblen Delegattyp Konvertieren.
Wenn für eine gegebene Methodengruppe E und einen Delegatentyp D Delegatenerstellungsausdrücke der Form „new D(E)“ zulässig sind (§7.5.10.3 und §20.9.6), dann gibt es einen impliziten Pfad von E nach D Konvertierung, und das Ergebnis der Konvertierung entspricht genau dem neuen D(E).
Im folgenden Beispiel erstellt der Konstruktor

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) {
...
}
}
Nach dem Login kopieren

zwei Delegateninstanzen mit new. Implizite Methodengruppenkonvertierungen ermöglichen eine Vereinfachung auf

public AlertDialog() {
okButton.Click += OkClick;
cancelButton.Click += CancelClick;
...
}
Nach dem Login kopieren

Wie bei allen anderen impliziten und expliziten Konvertierungen können Konvertierungsoperatoren verwendet werden, um eine bestimmte Konvertierung explizit durchzuführen. Dazu kann das Beispiel

object obj = new EventHandler(myDialog.OkClick);
Nach dem Login kopieren

stattdessen wie folgt geschrieben werden.

object obj = (EventHandler)myDialog.OkClick;
Nach dem Login kopieren

Anonyme Methodenausdrücke der Methodenzusammensetzung können die Überladungsauflösung beeinflussen, sind jedoch nicht an der Typinferenz beteiligt. Weitere Einzelheiten finden Sie in §20.6.4.

21.10 Implementierungsbeispiel

In diesem Abschnitt werden mögliche Implementierungen anonymer Methoden in Form von Standard-C#-Komponenten beschrieben. Die hier beschriebene Implementierung basiert auf denselben Prinzipien, die auch der Microsoft C#-Compiler verwendet, ist jedoch keineswegs obligatorisch oder die einzig mögliche Implementierung.
Der letzte Teil dieses Abschnitts enthält mehrere Beispielcodes, die anonyme Methoden mit unterschiedlichen Eigenschaften enthalten. Für jedes Beispiel stellen wir eine entsprechende Transformation des Codes mithilfe eines eindeutigen Standard-C#-Konstrukts bereit. In diesen Beispielen wird davon ausgegangen, dass der Bezeichner D den folgenden Delegatentyp darstellt.

public delegate void D();
Nach dem Login kopieren

Die einfachste Form einer anonymen Methode ist die, die keine externen Variablen erfasst.

class Test
{
static void F() {
D d = delegate { Console.WriteLine("test"); };
}
}
Nach dem Login kopieren

Dieser Code kann in eine Delegate-Instanz konvertiert werden, die auf eine vom Compiler generierte statische Methode verweist, und der Code der anonymen Methode wird in die statische Methode eingefügt. ,

class Test
{
static void F() {
D d = new D(__Method1);
}
static void __Method1() {
Console.WriteLine("test");
}
}
Nach dem Login kopieren

Im folgenden Beispiel verweist die anonyme Methode auf das Instanzmitglied davon.

class Test
{
int x;
void F() {
D d = delegate { Console.WriteLine(x); };
}
}
Nach dem Login kopieren

Dies kann in eine vom Compiler generierte Instanzmethode konvertiert werden, die anonymen Methodencode enthält.

class Test
{
int x;
void F() {
D d = new D(__Method1);
}
void __Method1() {
Console.WriteLine(x);
}
}
Nach dem Login kopieren

In diesem Beispiel erfasst die anonyme Methode eine lokale Variable.


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

该局部变量的生存期现在至少必须延长到匿名方法委托的生存期为止。这可以通过将局部变量“提升(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);
}
}
}
Nach dem Login kopieren

最后,如下匿名方法将捕获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); };
}
}
}
Nach dem Login kopieren

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

__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);
}
}
}
Nach dem Login kopieren

(匿名方法完)


以上就是C# 2.0 Specification(匿名方法)(二)的内容,更多相关内容请关注PHP中文网(www.php.cn)!


Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!