AusdrückeExpressions
Ein Ausdruck ist eine Folge von Operatoren und Operanden.An expression is a sequence of operators and operands. In diesem Kapitel werden die Syntax, die Reihenfolge der Auswertung von Operanden und Operatoren sowie die Bedeutung von Ausdrücken definiert.This chapter defines the syntax, order of evaluation of operands and operators, and meaning of expressions.
Expression classifications (Ausdrucksklassifizierungen)Expression classifications
Ein Ausdruck ist eines der folgenden Elemente:An expression is classified as one of the following:
- Ein Wert.A value. Jeder Wert verfügt über einen zugeordneten Typ.Every value has an associated type.
- Eine Variable.A variable. Jede Variable verfügt über einen zugeordneten Typ, nämlich den deklarierten Typ der Variablen.Every variable has an associated type, namely the declared type of the variable.
- Ein Namespace.A namespace. Ein Ausdruck mit dieser Klassifizierung kann nur auf der linken Seite eines member_access (Member Access) angezeigt werden.An expression with this classification can only appear as the left hand side of a member_access (Member access). In jedem anderen Kontext verursacht ein Ausdruck, der als Namespace klassifiziert ist, einen Kompilierzeitfehler.In any other context, an expression classified as a namespace causes a compile-time error.
- Ein Typ.A type. Ein Ausdruck mit dieser Klassifizierung kann nur als linke Seite eines member_access (Member Access) oder als Operand für den
as
Operator (as-Operator),is
Operator (is-Operator) odertypeof
Operator (der typeof-Operator) angezeigt werden.An expression with this classification can only appear as the left hand side of a member_access (Member access), or as an operand for theas
operator (The as operator), theis
operator (The is operator), or thetypeof
operator (The typeof operator). In jedem anderen Kontext verursacht ein Ausdruck, der als Typ klassifiziert ist, einen Kompilierzeitfehler.In any other context, an expression classified as a type causes a compile-time error. - Eine Methoden Gruppe, bei der es sich um eine Reihe von überladenen Methoden handelt, die sich aus einer Element Suche (Member Suche) ergeben.A method group, which is a set of overloaded methods resulting from a member lookup (Member lookup). Eine Methoden Gruppe kann über einen zugeordneten Instanzausdruck und eine zugeordnete Typargument Liste verfügen.A method group may have an associated instance expression and an associated type argument list. Wenn eine Instanzmethode aufgerufen wird, wird das Ergebnis der Auswertung des Instanzausdrucks zu der durch dargestellten Instanz
this
(dieser Zugriff).When an instance method is invoked, the result of evaluating the instance expression becomes the instance represented bythis
(This access). Eine Methoden Gruppe ist in einem invocation_expression (Aufruf Ausdrücke), einem delegate_creation_expression (delegaterstellungs Ausdruck) und als linke Seite eines is-Operators zulässig und kann implizit in einen kompatiblen Delegattyp (Methoden Gruppen Konvertierungen) konvertiert werden.A method group is permitted in an invocation_expression (Invocation expressions) , a delegate_creation_expression (Delegate creation expressions) and as the left hand side of an is operator, and can be implicitly converted to a compatible delegate type (Method group conversions). In jedem anderen Kontext verursacht ein Ausdruck, der als Methoden Gruppe klassifiziert ist, einen Kompilierzeitfehler.In any other context, an expression classified as a method group causes a compile-time error. - Ein NULL-Literale.A null literal. Ein Ausdruck mit dieser Klassifizierung kann implizit in einen Verweistyp oder einen Werte zulässt-Typ konvertiert werden.An expression with this classification can be implicitly converted to a reference type or nullable type.
- Eine anonyme Funktion.An anonymous function. Ein Ausdruck mit dieser Klassifizierung kann implizit in einen kompatiblen Delegattyp oder Ausdrucks Strukturtyp konvertiert werden.An expression with this classification can be implicitly converted to a compatible delegate type or expression tree type.
- Ein Eigenschaften Zugriff.A property access. Jeder Eigenschaften Zugriff verfügt über einen zugeordneten Typ, nämlich den Typ der Eigenschaft.Every property access has an associated type, namely the type of the property. Außerdem kann ein Eigenschaften Zugriff über einen zugeordneten Instanzausdruck verfügen.Furthermore, a property access may have an associated instance expression. Wenn ein Accessor (der-
get
oder-set
Block) eines Instanzeigenschaft Zugriffs aufgerufen wird, wird das Ergebnis der Auswertung des Instanzausdrucks zu der durch dargestellten Instanzthis
(dieser Zugriff).When an accessor (theget
orset
block) of an instance property access is invoked, the result of evaluating the instance expression becomes the instance represented bythis
(This access). - Ein Ereignis Zugriff.An event access. Jedem Ereignis Zugriff ist ein Typ zugeordnet, nämlich der Typ des Ereignisses.Every event access has an associated type, namely the type of the event. Außerdem kann ein Ereignis Zugriff über einen zugeordneten Instanzausdruck verfügen.Furthermore, an event access may have an associated instance expression. Ein Ereignis Zugriff kann als Linker Operand des
+=
-=
Operators und (Ereignis Zuweisung) angezeigt werden.An event access may appear as the left hand operand of the+=
and-=
operators (Event assignment). In jedem anderen Kontext verursacht ein Ausdruck, der als Ereignis Zugriff klassifiziert ist, einen Kompilierzeitfehler.In any other context, an expression classified as an event access causes a compile-time error. - Ein Indexer-Zugriff.An indexer access. Jedem Indexer-Zugriff ist ein Typ zugeordnet, nämlich der Elementtyp des Indexers.Every indexer access has an associated type, namely the element type of the indexer. Außerdem verfügt ein Indexer-Zugriff über einen zugeordneten Instanzausdruck und eine zugeordnete Argumentliste.Furthermore, an indexer access has an associated instance expression and an associated argument list. Wenn ein Accessor (der-
get
oder-set
Block) eines Indexerzugriffs aufgerufen wird, wird das Ergebnis der Auswertung des Instanzausdrucks zu der durch dargestellten Instanzthis
(dieser Zugriff), und das Ergebnis der Auswertung der Argumentliste wird zur Parameterliste des aufzurufenden aufzurufenden.When an accessor (theget
orset
block) of an indexer access is invoked, the result of evaluating the instance expression becomes the instance represented bythis
(This access), and the result of evaluating the argument list becomes the parameter list of the invocation. - Nichts.Nothing. Dies tritt auf, wenn der Ausdruck ein Aufruf einer Methode mit dem Rückgabetyp ist
void
.This occurs when the expression is an invocation of a method with a return type ofvoid
. Ein Ausdruck, der als Nothing klassifiziert ist, ist nur im Kontext einer statement_expression (Ausdrucks Anweisungen) gültig.An expression classified as nothing is only valid in the context of a statement_expression (Expression statements).
Das Endergebnis eines Ausdrucks ist nie ein Namespace, ein Typ, eine Methoden Gruppe oder ein Ereignis Zugriff.The final result of an expression is never a namespace, type, method group, or event access. Wie oben bereits erwähnt, sind diese Kategorien von Ausdrücken zwischenkonstrukte, die nur in bestimmten Kontexten zulässig sind.Rather, as noted above, these categories of expressions are intermediate constructs that are only permitted in certain contexts.
Ein Eigenschaften Zugriff oder Indexer-Zugriff wird immer als Wert neu klassifiziert, indem ein Aufruf des Get-Accessor oder des set-Accessors ausgeführt wird.A property access or indexer access is always reclassified as a value by performing an invocation of the get accessor or the set accessor. Der jeweilige Accessor wird durch den Kontext der Eigenschaft oder des Indexerzugriffs bestimmt: Wenn der Zugriff das Ziel einer Zuweisung ist, wird der Set-Accessor aufgerufen, um einen neuen Wert zuzuweisen (einfache Zuweisung).The particular accessor is determined by the context of the property or indexer access: If the access is the target of an assignment, the set accessor is invoked to assign a new value (Simple assignment). Andernfalls wird der Get-Accessor aufgerufen, um den aktuellen Wert zu erhalten (Werte von Ausdrücken).Otherwise, the get accessor is invoked to obtain the current value (Values of expressions).
Werte von AusdrückenValues of expressions
Die meisten Konstrukte, die einen Ausdruck einschließen, erfordern letztendlich, dass der Ausdruck einen Wert angibt.Most of the constructs that involve an expression ultimately require the expression to denote a value. In solchen Fällen tritt ein Kompilierzeitfehler auf, wenn der tatsächliche Ausdruck einen Namespace, einen Typ, eine Methoden Gruppe oder nichts angibt.In such cases, if the actual expression denotes a namespace, a type, a method group, or nothing, a compile-time error occurs. Wenn der Ausdruck jedoch einen Eigenschaften Zugriff, einen Indexer-Zugriff oder eine Variable angibt, wird der Wert der Eigenschaft, des Indexers oder der Variablen implizit ersetzt:However, if the expression denotes a property access, an indexer access, or a variable, the value of the property, indexer, or variable is implicitly substituted:
- Der Wert einer Variablen ist einfach der Wert, der zurzeit an dem von der Variablen identifizierten Speicherort gespeichert ist.The value of a variable is simply the value currently stored in the storage location identified by the variable. Eine Variable muss als definitiv zugewiesen (definitive Zuweisung) betrachtet werden, bevor ihr Wert abgerufen werden kann. andernfalls tritt ein Kompilierzeitfehler auf.A variable must be considered definitely assigned (Definite assignment) before its value can be obtained, or otherwise a compile-time error occurs.
- Der Wert eines Eigenschafts Zugriffs Ausdrucks wird abgerufen, indem der Get-Accessor der Eigenschaft aufgerufen wird.The value of a property access expression is obtained by invoking the get accessor of the property. Wenn die Eigenschaft keinen Get-Accessor aufweist, tritt ein Kompilierzeitfehler auf.If the property has no get accessor, a compile-time error occurs. Andernfalls wird ein Funktionsmember-Aufruf (Kompilierzeit Überprüfung der dynamischen Überladungs Auflösung) ausgeführt, und das Ergebnis des aufzurufenden Ausdrucks wird zum Wert des Eigenschafts Zugriffs Ausdrucks.Otherwise, a function member invocation (Compile-time checking of dynamic overload resolution) is performed, and the result of the invocation becomes the value of the property access expression.
- Der Wert eines indexerzugriffsausdrucks wird abgerufen, indem der Get-Accessor des Indexers aufgerufen wird.The value of an indexer access expression is obtained by invoking the get accessor of the indexer. Wenn der Indexer keinen Get-Accessor aufweist, tritt ein Kompilierzeitfehler auf.If the indexer has no get accessor, a compile-time error occurs. Andernfalls wird ein Funktionsmember-Aufruf (Kompilierzeit Überprüfung der dynamischen Überladungs Auflösung) mit der Argumentliste ausgeführt, die dem indexerzugriffsausdruck zugeordnet ist, und das Ergebnis des aufzurufenden Ausdrucks wird zum Wert des Zugriffs Ausdrucks des Indexers.Otherwise, a function member invocation (Compile-time checking of dynamic overload resolution) is performed with the argument list associated with the indexer access expression, and the result of the invocation becomes the value of the indexer access expression.
Static and Dynamic Binding (Statische und dynamische Bindung)Static and Dynamic Binding
Der Prozess der Bestimmung der Bedeutung eines Vorgangs basierend auf dem Typ oder Wert von konstituierenden Ausdrücken (Argumente, Operanden, Empfänger) wird häufig als Bindung bezeichnet.The process of determining the meaning of an operation based on the type or value of constituent expressions (arguments, operands, receivers) is often referred to as binding. Zum Beispiel wird die Bedeutung eines Methoden Aufrufes basierend auf dem Typ des Empfängers und der Argumente bestimmt.For instance the meaning of a method call is determined based on the type of the receiver and arguments. Die Bedeutung eines Operators wird basierend auf dem Typ seiner Operanden bestimmt.The meaning of an operator is determined based on the type of its operands.
In c# wird die Bedeutung eines Vorgangs in der Regel zur Kompilierzeit bestimmt, basierend auf dem Kompilier Zeittyp der enthaltenen Ausdrücke.In C# the meaning of an operation is usually determined at compile-time, based on the compile-time type of its constituent expressions. Wenn ein Ausdruck einen Fehler enthält, wird der Fehler auch vom Compiler erkannt und gemeldet.Likewise, if an expression contains an error, the error is detected and reported by the compiler. Diese Vorgehensweise wird als statische Bindung bezeichnet.This approach is known as static binding.
Wenn ein Ausdruck jedoch ein dynamischer Ausdruck ist (d. h. den-Typ aufweist dynamic
), gibt dies an, dass jede Bindung, an der Sie teilnimmt, auf dem Lauf Zeittyp (d. h. dem tatsächlichen Typ des Objekts, das Sie zur Laufzeit bezeichnet) und nicht auf dem Typ, der zur Kompilierzeit vorhanden ist, basieren soll.However, if an expression is a dynamic expression (i.e. has the type dynamic
) this indicates that any binding that it participates in should be based on its run-time type (i.e. the actual type of the object it denotes at run-time) rather than the type it has at compile-time. Die Bindung eines solchen Vorgangs wird daher bis zu der Zeit verzögert, in der der Vorgang während der Ausführung des Programms ausgeführt werden soll.The binding of such an operation is therefore deferred until the time where the operation is to be executed during the running of the program. Dies wird als dynamische Bindung bezeichnet.This is referred to as dynamic binding.
Wenn ein Vorgang dynamisch gebunden ist, wird vom Compiler nur eine kleine oder keine Überprüfung durchgeführt.When an operation is dynamically bound, little or no checking is performed by the compiler. Wenn die Lauf Zeitbindung fehlschlägt, werden Fehler zur Laufzeit als Ausnahmen gemeldet.Instead if the run-time binding fails, errors are reported as exceptions at run-time.
Die folgenden Vorgänge in c# unterliegen der Bindung:The following operations in C# are subject to binding:
- Mitgliederzugriff:
e.M
Member access:e.M
- Methodenaufruf:
e.M(e1, ..., eN)
Method invocation:e.M(e1, ..., eN)
- Delegataufruf:
e(e1, ..., eN)
Delegate invocation:e(e1, ..., eN)
- Element Zugriff:
e[e1, ..., eN]
Element access:e[e1, ..., eN]
- Objekt Erstellung:
new C(e1, ..., eN)
Object creation:new C(e1, ..., eN)
- Überladene unäre Operatoren:
+
,-
,!
,~
,++
,--
,true
,false
Overloaded unary operators:+
,-
,!
,~
,++
,--
,true
,false
- Überladene binäre Operatoren:
+
,-
,*
,/
,%
,&
,&&
,|
,||
,??
,^
,<<
,>>
,==
,!=
,>
,<
,>=
,<=
Overloaded binary operators:+
,-
,*
,/
,%
,&
,&&
,|
,||
,??
,^
,<<
,>>
,==
,!=
,>
,<
,>=
,<=
- Zuweisungs Operatoren:
=
,+=
,-=
,*=
,/=
,%=
,&=
,|=
,^=
,<<=
,>>=
Assignment operators:=
,+=
,-=
,*=
,/=
,%=
,&=
,|=
,^=
,<<=
,>>=
- Implizite und explizite KonvertierungenImplicit and explicit conversions
Wenn keine dynamischen Ausdrücke beteiligt sind, wird in c# standardmäßig die statische Bindung verwendet. Dies bedeutet, dass die Kompilierzeit Typen von konstituierenden Ausdrücken im Auswahl Vorgang verwendet werden.When no dynamic expressions are involved, C# defaults to static binding, which means that the compile-time types of constituent expressions are used in the selection process. Wenn jedoch einer der in den oben aufgeführten Vorgängen aufgeführten Ausdrücke ein dynamischer Ausdruck ist, wird der Vorgang stattdessen dynamisch gebunden.However, when one of the constituent expressions in the operations listed above is a dynamic expression, the operation is instead dynamically bound.
Bindungs ZeitBinding-time
Die statische Bindung erfolgt zur Kompilierzeit, während die dynamische Bindung zur Laufzeit stattfindet.Static binding takes place at compile-time, whereas dynamic binding takes place at run-time. In den folgenden Abschnitten bezieht sich der Begriff " Bindungs Zeit " entweder auf die Kompilierzeit oder die Laufzeit, je nachdem, wann die Bindung stattfindet.In the following sections, the term binding-time refers to either compile-time or run-time, depending on when the binding takes place.
Das folgende Beispiel veranschaulicht die Begriffe der statischen und dynamischen Bindung und der Bindungs Zeit:The following example illustrates the notions of static and dynamic binding and of binding-time:
object o = 5;
dynamic d = 5;
Console.WriteLine(5); // static binding to Console.WriteLine(int)
Console.WriteLine(o); // static binding to Console.WriteLine(object)
Console.WriteLine(d); // dynamic binding to Console.WriteLine(int)
Die ersten beiden Aufrufe sind statisch gebunden: die Überladung von Console.WriteLine
wird basierend auf dem Kompilier Zeittyp ihres Arguments ausgewählt.The first two calls are statically bound: the overload of Console.WriteLine
is picked based on the compile-time type of their argument. Folglich ist die Bindungs Zeit die Kompilierzeit.Thus, the binding-time is compile-time.
Der dritte Aufruf ist dynamisch gebunden: die Überladung von Console.WriteLine
wird basierend auf dem Lauf Zeittyp des Arguments ausgewählt.The third call is dynamically bound: the overload of Console.WriteLine
is picked based on the run-time type of its argument. Dies liegt daran, dass das-Argument ein dynamischer Ausdruck ist, der Kompilier Zeittyp ist dynamic
.This happens because the argument is a dynamic expression -- its compile-time type is dynamic
. Folglich ist die Bindungs Zeit für den dritten Aufruf Lauf Zeit.Thus, the binding-time for the third call is run-time.
Dynamische BindungDynamic binding
Der Zweck der dynamischen Bindung besteht darin, dass c#-Programme mit dynamischen Objekten interagieren können, d. h. Objekte, die nicht den normalen Regeln des c#-Typsystems entsprechen.The purpose of dynamic binding is to allow C# programs to interact with dynamic objects, i.e. objects that do not follow the normal rules of the C# type system. Dynamische Objekte können Objekte aus anderen Programmiersprachen mit unterschiedlichen Typen Systemen sein, oder es handelt sich um Objekte, die Programm gesteuert eingerichtet werden, um Ihre eigene Bindungs Semantik für verschiedene Vorgänge zu implementieren.Dynamic objects may be objects from other programming languages with different types systems, or they may be objects that are programmatically setup to implement their own binding semantics for different operations.
Der Mechanismus, mit dem ein dynamisches Objekt seine eigene Semantik implementiert, ist die Implementierung definiert.The mechanism by which a dynamic object implements its own semantics is implementation defined. Eine bestimmte Schnittstelle, die wieder implementiert wird, wird von dynamischen Objekten implementiert, um der c#-Laufzeit zu signalisieren, dass Sie über eine besondere Semantik verfügen.A given interface -- again implementation defined -- is implemented by dynamic objects to signal to the C# run-time that they have special semantics. Wenn also Vorgänge für ein dynamisches Objekt dynamisch gebunden werden, übernehmen Sie die eigene Bindungs Semantik anstelle von c#-Daten, die in diesem Dokument angegeben sind.Thus, whenever operations on a dynamic object are dynamically bound, their own binding semantics, rather than those of C# as specified in this document, take over.
Der Zweck der dynamischen Bindung besteht darin, die Interoperabilität mit dynamischen Objekten zuzulassen, aber c# ermöglicht die dynamische Bindung für alle Objekte, unabhängig davon, ob Sie dynamisch sind oder nicht.While the purpose of dynamic binding is to allow interoperation with dynamic objects, C# allows dynamic binding on all objects, whether they are dynamic or not. Dies ermöglicht eine reibungslosere Integration dynamischer Objekte, da die Ergebnisse von Vorgängen für diese nicht selbst dynamische Objekte sein können, aber immer noch ein Typ ist, der dem Programmierer zur Kompilierzeit unbekannt ist.This allows for a smoother integration of dynamic objects, as the results of operations on them may not themselves be dynamic objects, but are still of a type unknown to the programmer at compile-time. Außerdem kann die dynamische Bindung helfen, fehleranfälligen reflektionsbasierten Code zu eliminieren, auch wenn keine Objekte an dynamischen Objekten beteiligt sind.Also dynamic binding can help eliminate error-prone reflection-based code even when no objects involved are dynamic objects.
In den folgenden Abschnitten wird für jedes Konstrukt in der Sprache exakt beschrieben, wann die dynamische Bindung angewendet wird, welche Kompilierzeit Überprüfung (sofern vorhanden) angewendet wird und wie das Ergebnis und die Ausdrucks Klassifizierung der Kompilierung ist.The following sections describe for each construct in the language exactly when dynamic binding is applied, what compile time checking -- if any -- is applied, and what the compile-time result and expression classification is.
Typen von konstituierenden AusdrückenTypes of constituent expressions
Wenn ein Vorgang statisch gebunden ist, wird der Typ eines einzelnen Ausdrucks (z. b. ein Empfänger, ein Argument, ein Index oder ein Operand) immer als der Kompilier Zeittyp dieses Ausdrucks betrachtet.When an operation is statically bound, the type of a constituent expression (e.g. a receiver, an argument, an index or an operand) is always considered to be the compile-time type of that expression.
Wenn ein Vorgang dynamisch gebunden wird, wird der Typ eines einzelnen Ausdrucks basierend auf dem Kompilier Zeittyp des konstituierenden Ausdrucks auf unterschiedliche Weise bestimmt:When an operation is dynamically bound, the type of a constituent expression is determined in different ways depending on the compile-time type of the constituent expression:
- Ein konstituierender Ausdruck des Kompilierzeit Typs
dynamic
wird als der Typ des tatsächlichen Werts betrachtet, zu dem der Ausdruck zur Laufzeit ausgewertet wird.A constituent expression of compile-time typedynamic
is considered to have the type of the actual value that the expression evaluates to at runtime - Ein konstituierender Ausdruck, dessen Kompilier Zeittyp ein Typparameter ist, wird als Typ betrachtet, an den der Typparameter zur Laufzeit gebunden ist.A constituent expression whose compile-time type is a type parameter is considered to have the type which the type parameter is bound to at runtime
- Andernfalls wird der entsprechende Kompilier Zeittyp für den enthaltenen Ausdruck berücksichtigt.Otherwise the constituent expression is considered to have its compile-time type.
OperatorenOperators
Ausdrücke werden aus Operanden _-und- _Operatoren*_ erstellt.Expressions are constructed from operands _ and _operators*_. Die Operatoren eines Ausdrucks geben an, welche Operationen auf die Operanden angewendet werden.The operators of an expression indicate which operations to apply to the operands. Beispiele für Operatoren sind +
, -
, _
, /
und new
.Examples of operators include +
, -
, _
, /
, and new
. Beispiele für Operanden sind Literale, Felder, lokale Variablen und Ausdrücke.Examples of operands include literals, fields, local variables, and expressions.
Es gibt drei Arten von Operatoren:There are three kinds of operators:
- Unäre Operatoren.Unary operators. Die unären Operatoren nehmen einen Operanden an und verwenden entweder eine Präfix Notation (z. b.
--x
) oder eine Postfix Notation (zx++
. b.).The unary operators take one operand and use either prefix notation (such as--x
) or postfix notation (such asx++
). - Binäre Operatoren.Binary operators. Die binären Operatoren nehmen zwei Operanden an und verwenden die Infix-Notation (z
x + y
. b.).The binary operators take two operands and all use infix notation (such asx + y
). - Ternärer Operator.Ternary operator. Nur ein ternärer Operator,
?:
, ist vorhanden; er nimmt drei Operanden an und verwendet die Infix-Notation (c ? x : y
).Only one ternary operator,?:
, exists; it takes three operands and uses infix notation (c ? x : y
).
Die Reihenfolge der Auswertung von Operatoren in einem Ausdruck wird durch die * Rang Folge _ und _ Assoziativität* der Operatoren (Operator Rangfolge und Assoziativität) bestimmt.The order of evaluation of operators in an expression is determined by the precedence _ and _ associativity of the operators (Operator precedence and associativity).
Operanden in einem Ausdruck werden von links nach rechts ausgewertet.Operands in an expression are evaluated from left to right. In wird die-Methode z. b. mit F(i) + G(i++) * H(i)
F
dem alten Wert von aufgerufen. i
anschließend G
wird die-Methode mit dem alten Wert von aufgerufen, i
und schließlich H
wird die-Methode mit dem neuen Wert von aufgerufen i
.For example, in F(i) + G(i++) * H(i)
, method F
is called using the old value of i
, then method G
is called with the old value of i
, and, finally, method H
is called with the new value of i
. Dies ist getrennt von und nicht mit der Operator Rangfolge.This is separate from and unrelated to operator precedence.
Bestimmte Operatoren können überladen werden.Certain operators can be overloaded. Die Operator Überladung ermöglicht das Angeben von benutzerdefinierten Operator Implementierungen für Vorgänge, bei denen einer oder beide der Operanden eine benutzerdefinierte Klasse oder ein Strukturtyp sind (Operator Überladung).Operator overloading permits user-defined operator implementations to be specified for operations where one or both of the operands are of a user-defined class or struct type (Operator overloading).
Operatorrangfolge und AssoziativitätOperator precedence and associativity
Wenn ein Ausdruck mehrere Operatoren enthält, steuert die *Rangfolge _ der Operatoren die Reihenfolge, in der die einzelnen Operatoren ausgewertet werden.When an expression contains multiple operators, the *precedence _ of the operators controls the order in which the individual operators are evaluated. Beispielsweise wird der Ausdruck x + y _ z
als x + (y * z)
ausgewertet, da der *
-Operator eine höhere Rangfolge aufweist als der binäre +
-Operator.For example, the expression x + y _ z
is evaluated as x + (y * z)
because the *
operator has higher precedence than the binary +
operator. Die Rangfolge eines Operators wird durch die Definition der zugehörigen Grammatikproduktion festgelegt.The precedence of an operator is established by the definition of its associated grammar production. Ein additive_expression besteht z. b. aus einer Sequenz von multiplicative_expression s, die durch +
or- -
Operatoren getrennt sind, sodass der +
-Operator und der- -
Operator eine niedrigere Rangfolge als die *
/
%
Operatoren, undFor example, an additive_expression consists of a sequence of multiplicative_expression s separated by +
or -
operators, thus giving the +
and -
operators lower precedence than the *
, /
, and %
operators.
In der folgenden Tabelle werden alle Operatoren in der Rangfolge von der höchsten zur niedrigsten aufgeführt:The following table summarizes all operators in order of precedence from highest to lowest:
Tritt ein Operand zwischen zwei Operatoren mit gleicher Rangfolge auf, steuert die Assoziativität der Operatoren die Reihenfolge, in der die Vorgänge ausgeführt werden:When an operand occurs between two operators with the same precedence, the associativity of the operators controls the order in which the operations are performed:
- Mit Ausnahme der Zuweisungs Operatoren und des NULL-Sammel Operators sind alle binären Operatoren Links bündig. Dies bedeutet, dass Vorgänge von links nach rechts ausgeführt werden.Except for the assignment operators and the null coalescing operator, all binary operators are left-associative, meaning that operations are performed from left to right.
x + y + z
wird beispielsweise als(x + y) + z
ausgewertet.For example,x + y + z
is evaluated as(x + y) + z
. - Die Zuweisungs Operatoren, der NULL-Sammel Operator und der bedingte Operator (
?:
) sind Rechts assoziativ, was bedeutet, dass Vorgänge von rechts nach links ausgeführt werden.The assignment operators, the null coalescing operator and the conditional operator (?:
) are right-associative, meaning that operations are performed from right to left.x = y = z
wird beispielsweise alsx = (y = z)
ausgewertet.For example,x = y = z
is evaluated asx = (y = z)
.
Rangfolge und Assoziativität können mit Klammern gesteuert werden.Precedence and associativity can be controlled using parentheses. In x + y * z
wird beispielsweise zuerst y
mit z
multipliziert und dann das Ergebnis zu x
addiert, aber in (x + y) * z
werden zunächst x
und y
addiert, und dann wird das Ergebnis mit z
multipliziert.For example, x + y * z
first multiplies y
by z
and then adds the result to x
, but (x + y) * z
first adds x
and y
and then multiplies the result by z
.
Überladen von OperatorenOperator overloading
Alle unären und binären Operatoren verfügen über vordefinierte Implementierungen, die automatisch in jedem Ausdruck verfügbar sind.All unary and binary operators have predefined implementations that are automatically available in any expression. Zusätzlich zu den vordefinierten Implementierungen können benutzerdefinierte Implementierungen durch Einschließen von operator
Deklarationen in Klassen und Strukturen (Operatoren) eingeführt werden.In addition to the predefined implementations, user-defined implementations can be introduced by including operator
declarations in classes and structs (Operators). Implementierungen von benutzerdefinierten Operatoren haben immer Vorrang vor vordefinierten Operator Implementierungen: nur wenn keine anwendbaren benutzerdefinierten Operator Implementierungen vorhanden sind, werden die vordefinierten Operator Implementierungen in Erwägung gezogen, wie unter unäre Operator Überladungs Auflösung und binäre Operator Überladungs Auflösungbeschrieben.User-defined operator implementations always take precedence over predefined operator implementations: Only when no applicable user-defined operator implementations exist will the predefined operator implementations be considered, as described in Unary operator overload resolution and Binary operator overload resolution.
Die über ladbaren unären Operatoren sind:The overloadable unary operators are:
+ - ! ~ ++ -- true false
Obwohl true
und false
nicht explizit in Ausdrücken verwendet werden (und daher nicht in der Rang folgen Tabelle in der Operator Rangfolge und Assoziativitätenthalten sind), werden Sie als Operatoren angesehen, da Sie in mehreren Ausdrucks Kontexten aufgerufen werden: boolesche Ausdrücke (boolesche Ausdrücke) und Ausdrücke mit bedingtem (bedingtem Operator) und bedingten logischen Operatoren (bedingte logische Operatoren).Although true
and false
are not used explicitly in expressions (and therefore are not included in the precedence table in Operator precedence and associativity), they are considered operators because they are invoked in several expression contexts: boolean expressions (Boolean expressions) and expressions involving the conditional (Conditional operator), and conditional logical operators (Conditional logical operators).
Die über ladbaren binären Operatoren sind:The overloadable binary operators are:
+ - * / % & | ^ << >> == != > < >= <=
Nur die oben aufgeführten Operatoren können überladen werden.Only the operators listed above can be overloaded. Insbesondere ist es nicht möglich, Element Zugriffe, Methodenaufrufe oder die =
&&
||
Operatoren,,,, ??
?:
, =>
, checked
, unchecked
,,, new
typeof
default
, as
und is
zu überladen.In particular, it is not possible to overload member access, method invocation, or the =
, &&
, ||
, ??
, ?:
, =>
, checked
, unchecked
, new
, typeof
, default
, as
, and is
operators.
Wenn ein binärer Operator überladen ist, wird der zugehörige Zuweisungsoperator, sofern er vorhanden ist, auch implizit überladen.When a binary operator is overloaded, the corresponding assignment operator, if any, is also implicitly overloaded. Beispielsweise ist eine Überladung des-Operators *
auch eine Überladung des-Operators *=
.For example, an overload of operator *
is also an overload of operator *=
. Dies wird in der Verbund Zuweisungweiter unten beschrieben.This is described further in Compound assignment. Beachten Sie, dass der Zuweisungs Operator selbst ( =
) nicht überladen werden kann.Note that the assignment operator itself (=
) cannot be overloaded. Eine Zuweisung führt immer eine einfache bitweise Kopie eines Werts in eine Variable aus.An assignment always performs a simple bit-wise copy of a value into a variable.
Umwandlungs Vorgänge, wie z (T)x
. b., werden durch die Bereitstellung von benutzerdefinierten Konvertierungen (benutzerdefinierte Konvertierungen) überladen.Cast operations, such as (T)x
, are overloaded by providing user-defined conversions (User-defined conversions).
Der Element Zugriff, z a[x]
. b., wird nicht als über ladbarer Operator angesehen.Element access, such as a[x]
, is not considered an overloadable operator. Stattdessen wird die benutzerdefinierte Indizierung durch Indexer (Indexer) unterstützt.Instead, user-defined indexing is supported through indexers (Indexers).
In Ausdrücken wird mithilfe der Operator Notation auf Operatoren verwiesen, und in Deklarationen wird auf Operatoren mithilfe der funktionalen Notation verwiesen.In expressions, operators are referenced using operator notation, and in declarations, operators are referenced using functional notation. In der folgenden Tabelle wird die Beziehung zwischen Operator-und Funktions Notizen für unäre und binäre Operatoren veranschaulicht.The following table shows the relationship between operator and functional notations for unary and binary operators. Im ersten Eintrag bezeichnet op alle über ladbaren unären Präfix Operatoren.In the first entry, op denotes any overloadable unary prefix operator. Im zweiten Eintrag bezeichnet op die unären postfix ++
-und- --
Operatoren.In the second entry, op denotes the unary postfix ++
and --
operators. Im dritten Eintrag bezeichnet op jeden über ladbaren binären Operator.In the third entry, op denotes any overloadable binary operator.
Operator NotationOperator notation | Funktionale NotationFunctional notation |
---|---|
op x |
operator op(x) |
x op |
operator op(x) |
x op y |
operator op(x,y) |
Benutzerdefinierte Operator Deklarationen erfordern immer, dass mindestens einer der Parameter vom Klassen-oder Strukturtyp ist, der die Operator Deklaration enthält.User-defined operator declarations always require at least one of the parameters to be of the class or struct type that contains the operator declaration. Daher ist es nicht möglich, dass ein benutzerdefinierter Operator dieselbe Signatur wie ein vordefinierter Operator hat.Thus, it is not possible for a user-defined operator to have the same signature as a predefined operator.
Benutzerdefinierte Operator Deklarationen können die Syntax, Rangfolge oder Assoziativität eines Operators nicht ändern.User-defined operator declarations cannot modify the syntax, precedence, or associativity of an operator. Beispielsweise ist der- /
Operator immer ein binärer Operator, verfügt immer über die in Operator Rangfolge und Assoziativitätangegebene Rang folgen Ebene und ist immer links assoziativ.For example, the /
operator is always a binary operator, always has the precedence level specified in Operator precedence and associativity, and is always left-associative.
Obwohl es möglich ist, dass ein benutzerdefinierter Operator jede beliebige Berechnung durchführt, wird dringend davon abgeraten, Implementierungen, die andere Ergebnisse als diejenigen ergeben, die intuitiv erwartet werden.While it is possible for a user-defined operator to perform any computation it pleases, implementations that produce results other than those that are intuitively expected are strongly discouraged. Beispielsweise sollte eine Implementierung von operator ==
die beiden Operanden auf Gleichheit vergleichen und ein entsprechendes Ergebnis zurückgeben bool
.For example, an implementation of operator ==
should compare the two operands for equality and return an appropriate bool
result.
Die Beschreibungen der einzelnen Operatoren in Primary Expressions durch bedingte logische Operatoren geben die vordefinierten Implementierungen der Operatoren sowie alle zusätzlichen Regeln an, die für die einzelnen Operatoren gelten.The descriptions of individual operators in Primary expressions through Conditional logical operators specify the predefined implementations of the operators and any additional rules that apply to each operator. Die Beschreibungen verwenden die Begriffe unäre Operator Überladungs Auflösung _, _binäre Operator Überladungs Auflösung*_ und _ *numerische herauf Stufung * *, Definitionen von, die in den folgenden Abschnitten zu finden sind.The descriptions make use of the terms unary operator overload resolution _, _binary operator overload resolution_, and _numeric promotion**, definitions of which are found in the following sections.
Überladungs Auflösung für unären OperatorUnary operator overload resolution
Ein Vorgang des Formulars op x
oder x op
, wobei op
ein über ladbarer unärer Operator ist und x
ein Ausdruck vom Typ ist X
, wird wie folgt verarbeitet:An operation of the form op x
or x op
, where op
is an overloadable unary operator, and x
is an expression of type X
, is processed as follows:
- Der Satz von benutzerdefinierten Operatoren, die von
X
für den Vorgang bereitgestellt werden,operator op(x)
wird mithilfe der Regeln von benutzerdefinierten Operatoren des Kandidatenbestimmt.The set of candidate user-defined operators provided byX
for the operationoperator op(x)
is determined using the rules of Candidate user-defined operators. - Wenn der Satz von benutzerdefinierten Operatoren des Kandidaten nicht leer ist, wird dies zur Gruppe der Kandidaten Operatoren für den Vorgang.If the set of candidate user-defined operators is not empty, then this becomes the set of candidate operators for the operation. Andernfalls werden die vordefinierten unären
operator op
Implementierungen, einschließlich ihrer angehobenen Formulare, zur Gruppe der Kandidaten Operatoren für den Vorgang.Otherwise, the predefined unaryoperator op
implementations, including their lifted forms, become the set of candidate operators for the operation. Die vordefinierten Implementierungen eines angegebenen Operators werden in der Beschreibung des Operators (primär Ausdrücke und unäre Operatoren) angegeben.The predefined implementations of a given operator are specified in the description of the operator (Primary expressions and Unary operators). - Die Regeln für die Überladungs Auflösung der Überladungs Auflösung werden auf den Satz von Kandidaten Operatoren angewendet, um den besten Operator in Bezug auf die Argumentliste auszuwählen
(x)
, und dieser Operator wird zum Ergebnis der Überladungs Auflösung.The overload resolution rules of Overload resolution are applied to the set of candidate operators to select the best operator with respect to the argument list(x)
, and this operator becomes the result of the overload resolution process. Wenn bei der Überladungs Auflösung nicht der einzige beste Operator ausgewählt werden kann, tritt ein Bindungs Zeitfehler auf.If overload resolution fails to select a single best operator, a binding-time error occurs.
Binäre Operator Überladungs AuflösungBinary operator overload resolution
Ein Vorgang in der Form x op y
, wobei op
ein über ladbarer binärer Operator ist, x
ein Ausdruck vom Typ X
und y
ein Ausdruck vom Typ ist Y
, wird wie folgt verarbeitet:An operation of the form x op y
, where op
is an overloadable binary operator, x
is an expression of type X
, and y
is an expression of type Y
, is processed as follows:
- Der Satz von benutzerdefinierten Operatoren, die von
X
und für den-Vorgang bereitgestellt werden,Y
operator op(x,y)
wird bestimmt.The set of candidate user-defined operators provided byX
andY
for the operationoperator op(x,y)
is determined. Der Satz besteht aus der Vereinigung der Kandidaten Operatoren, die von bereitgestellt werdenX
, und der von bereitgestellten Kandidaten OperatorenY
, die jeweils mithilfe der Regeln von benutzerdefinierten Operatoren des Kandidatenbestimmt werden.The set consists of the union of the candidate operators provided byX
and the candidate operators provided byY
, each determined using the rules of Candidate user-defined operators. WennX
undY
denselben Typ haben oder wennX
undY
von einem gemeinsamen Basistyp abgeleitet sind, treten freigegebene Kandidaten Operatoren nur einmal in der kombinierten Menge auf.IfX
andY
are the same type, or ifX
andY
are derived from a common base type, then shared candidate operators only occur in the combined set once. - Wenn der Satz von benutzerdefinierten Operatoren des Kandidaten nicht leer ist, wird dies zur Gruppe der Kandidaten Operatoren für den Vorgang.If the set of candidate user-defined operators is not empty, then this becomes the set of candidate operators for the operation. Andernfalls werden die vordefinierten binären
operator op
Implementierungen, einschließlich ihrer angehobenen Formulare, zur Gruppe der Kandidaten Operatoren für den Vorgang.Otherwise, the predefined binaryoperator op
implementations, including their lifted forms, become the set of candidate operators for the operation. Die vordefinierten Implementierungen eines angegebenen Operators werden in der Beschreibung des Operators (arithmetische Operatoren durch bedingte logische Operatoren) angegeben.The predefined implementations of a given operator are specified in the description of the operator (Arithmetic operators through Conditional logical operators). Bei vordefinierten Aufzählungs-und delegatoperatoren sind die einzigen Operatoren, die von einem Aufzählungs-oder Delegattyp definiert werden, der der Bindungstyp von einem der Operanden ist.For predefined enum and delegate operators, the only operators considered are those defined by an enum or delegate type that is the binding-time type of one of the operands. - Die Regeln für die Überladungs Auflösung der Überladungs Auflösung werden auf den Satz von Kandidaten Operatoren angewendet, um den besten Operator in Bezug auf die Argumentliste auszuwählen
(x,y)
, und dieser Operator wird zum Ergebnis der Überladungs Auflösung.The overload resolution rules of Overload resolution are applied to the set of candidate operators to select the best operator with respect to the argument list(x,y)
, and this operator becomes the result of the overload resolution process. Wenn bei der Überladungs Auflösung nicht der einzige beste Operator ausgewählt werden kann, tritt ein Bindungs Zeitfehler auf.If overload resolution fails to select a single best operator, a binding-time error occurs.
Benutzerdefinierte Operatoren für KandidatenCandidate user-defined operators
Bei einem Typ T
und einem Vorgang operator op(A)
, bei dem op
es sich um einen über ladbaren Operator handelt und A
es sich um eine Argumentliste handelt, wird der von for bereitgestellte Satz von benutzerdefinierten Operatoren T
operator op(A)
wie folgt bestimmt:Given a type T
and an operation operator op(A)
, where op
is an overloadable operator and A
is an argument list, the set of candidate user-defined operators provided by T
for operator op(A)
is determined as follows:
- Bestimmen Sie den Typ
T0
.Determine the typeT0
. WennT
ein Typ ist, der NULL-Werte zulässt,T0
ist der zugrunde liegende Typ, andernfallsT0
ist gleichT
.IfT
is a nullable type,T0
is its underlying type, otherwiseT0
is equal toT
. - Bei allen
operator op
Deklarationen inT0
und allen aufgelegten Formen solcher Operatoren, wenn mindestens ein Operator anwendbar ist (anwendbarer Funktionsmember), der sich auf die Argumentliste betrifftA
, besteht der Satz von Kandidaten Operatoren aus allen anwendbaren Operatoren inT0
.For alloperator op
declarations inT0
and all lifted forms of such operators, if at least one operator is applicable (Applicable function member) with respect to the argument listA
, then the set of candidate operators consists of all such applicable operators inT0
. - Andernfalls
T0
object
ist der Satz von Kandidaten Operatoren leer, wenn ist.Otherwise, ifT0
isobject
, the set of candidate operators is empty. - Andernfalls ist der Satz von Kandidaten Operatoren, der von bereitgestellt
T0
wird, der Satz von Kandidaten Operatoren, der von der direkten Basisklasse von bereitgestellt wirdT0
, oder die effektive Basisklasse von,T0
WennT0
ein Typparameter ist.Otherwise, the set of candidate operators provided byT0
is the set of candidate operators provided by the direct base class ofT0
, or the effective base class ofT0
ifT0
is a type parameter.
Numerische HeraufstufungenNumeric promotions
Die numerische herauf Stufung besteht aus dem automatischen Ausführen bestimmter impliziter Konvertierungen der Operanden der vordefinierten unären und binären numerischen Operatoren.Numeric promotion consists of automatically performing certain implicit conversions of the operands of the predefined unary and binary numeric operators. Die numerische herauf Stufung ist kein eindeutiger Mechanismus, sondern wirkt sich eher auf die Anwendung der Überladungs Auflösung auf die vordefinierten Operatoren aus.Numeric promotion is not a distinct mechanism, but rather an effect of applying overload resolution to the predefined operators. Die numerische herauf Stufung wirkt sich nicht auf die Auswertung von benutzerdefinierten Operatoren aus, obwohl benutzerdefinierte Operatoren implementiert werden können, um ähnliche Effekte zu erzeugen.Numeric promotion specifically does not affect evaluation of user-defined operators, although user-defined operators can be implemented to exhibit similar effects.
Sehen Sie sich als Beispiel für die numerische herauf Stufung die vordefinierten Implementierungen des binären *
Operators an:As an example of numeric promotion, consider the predefined implementations of the binary *
operator:
int operator *(int x, int y);
uint operator *(uint x, uint y);
long operator *(long x, long y);
ulong operator *(ulong x, ulong y);
float operator *(float x, float y);
double operator *(double x, double y);
decimal operator *(decimal x, decimal y);
Wenn Regeln zur Überladungs Auflösung (ÜberladungsAuflösung) auf diese Gruppe von Operatoren angewendet werden, besteht der Effekt darin, den ersten Operator auszuwählen, für den implizite Konvertierungen aus den Operanden Typen vorhanden sind.When overload resolution rules (Overload resolution) are applied to this set of operators, the effect is to select the first of the operators for which implicit conversions exist from the operand types. Für den b * s
-Vorgang, bei dem b
ein byte
und s
ein ist short
, wählt die Überladungs Auflösung beispielsweise operator *(int,int)
als besten Operator aus.For example, for the operation b * s
, where b
is a byte
and s
is a short
, overload resolution selects operator *(int,int)
as the best operator. Folglich ist der Effekt, dass b
und s
in konvertiert werden int
, und der Ergebnistyp ist int
.Thus, the effect is that b
and s
are converted to int
, and the type of the result is int
. Entsprechend i * d
wählt die Überladungs Auflösung für den-Vorgang, bei dem i
ein int
und d
ein ist double
, operator *(double,double)
als besten Operator aus.Likewise, for the operation i * d
, where i
is an int
and d
is a double
, overload resolution selects operator *(double,double)
as the best operator.
Unäre numerische AktionenUnary numeric promotions
Unäre numerische herauf Stufung tritt für die Operanden der vordefinierten +
-
Operatoren, und auf ~
.Unary numeric promotion occurs for the operands of the predefined +
, -
, and ~
unary operators. Die Unäre numerische herauf Stufung besteht einfach aus der Umstellung von Operanden vom Typ sbyte
, byte
, short
, ushort
oder char
in den-Typ int
.Unary numeric promotion simply consists of converting operands of type sbyte
, byte
, short
, ushort
, or char
to type int
. Außerdem konvertiert die Unäre numerische herauf Stufung für den unären -
Operator Operanden vom Typ uint
in den Typ long
.Additionally, for the unary -
operator, unary numeric promotion converts operands of type uint
to type long
.
Binäre numerische AktionenBinary numeric promotions
Die binäre numerische herauf Stufung erfolgt bei den Operanden der vordefinierten +
Operatoren,,,, -
*
/
%
, &
, |
, ^
,,,,, ==
!=
>
<
>=
und <=
.Binary numeric promotion occurs for the operands of the predefined +
, -
, *
, /
, %
, &
, |
, ^
, ==
, !=
, >
, <
, >=
, and <=
binary operators. Die binäre numerische herauf Stufung konvertiert beide Operanden implizit in einen gemeinsamen Typ, der bei nicht relationalen Operatoren auch zum Ergebnistyp des Vorgangs wird.Binary numeric promotion implicitly converts both operands to a common type which, in case of the non-relational operators, also becomes the result type of the operation. Die binäre numerische herauf Stufung besteht aus der Anwendung der folgenden Regeln in der Reihenfolge, in der Sie angezeigt werden:Binary numeric promotion consists of applying the following rules, in the order they appear here:
- Wenn einer der beiden Operanden vom Typ ist
decimal
, wird der andere Operand in den Typ konvertiertdecimal
, oder es tritt ein Bindungs Zeitfehler auf, wenn der andere Operand vom Typfloat
oder istdouble
.If either operand is of typedecimal
, the other operand is converted to typedecimal
, or a binding-time error occurs if the other operand is of typefloat
ordouble
. - Wenn einer der beiden Operanden vom Typ ist
double
, wird der andere Operand in den Typ konvertiertdouble
.Otherwise, if either operand is of typedouble
, the other operand is converted to typedouble
. - Wenn einer der beiden Operanden vom Typ ist
float
, wird der andere Operand in den Typ konvertiertfloat
.Otherwise, if either operand is of typefloat
, the other operand is converted to typefloat
. - Andernfalls, wenn einer der beiden Operanden vom Typ ist
ulong
, wird der andere Operand in den Typ konvertiertulong
, oder es tritt ein Bindungs Zeitfehler auf, wenn der andere Operand vom Typsbyte
,short
,int
oder istlong
.Otherwise, if either operand is of typeulong
, the other operand is converted to typeulong
, or a binding-time error occurs if the other operand is of typesbyte
,short
,int
, orlong
. - Wenn einer der beiden Operanden vom Typ ist
long
, wird der andere Operand in den Typ konvertiertlong
.Otherwise, if either operand is of typelong
, the other operand is converted to typelong
. - Wenn einer der beiden
uint
Operanden vom Typ und der andere Operand vom Typsbyte
, oder istshort
int
, werden beide Operanden in den Typ konvertiertlong
.Otherwise, if either operand is of typeuint
and the other operand is of typesbyte
,short
, orint
, both operands are converted to typelong
. - Wenn einer der beiden Operanden vom Typ ist
uint
, wird der andere Operand in den Typ konvertiertuint
.Otherwise, if either operand is of typeuint
, the other operand is converted to typeuint
. - Andernfalls werden beide Operanden in den Typ konvertiert
int
.Otherwise, both operands are converted to typeint
.
Beachten Sie, dass die erste Regel Vorgänge, die den decimal
Typ mit den double
Typen und mischen, nicht zulässt float
.Note that the first rule disallows any operations that mix the decimal
type with the double
and float
types. Die Regel folgt der Tatsache, dass keine impliziten Konvertierungen zwischen dem- decimal
Typ und dem-Typ und dem-Typ vorhanden sind double
float
.The rule follows from the fact that there are no implicit conversions between the decimal
type and the double
and float
types.
Beachten Sie außerdem, dass es nicht möglich ist, dass ein Operand vom Typ ulong
ist, wenn der andere Operand einen ganzzahligen Typ mit Vorzeichen hat.Also note that it is not possible for an operand to be of type ulong
when the other operand is of a signed integral type. Der Grund dafür ist, dass kein ganzzahliger Typ vorhanden ist, der den vollständigen Bereich von und die ganzzahligen Typen mit Vorzeichen darstellen kann ulong
.The reason is that no integral type exists that can represent the full range of ulong
as well as the signed integral types.
In beiden oben genannten Fällen kann ein Umwandlungs Ausdruck verwendet werden, um einen Operanden explizit in einen Typ zu konvertieren, der mit dem anderen Operanden kompatibel ist.In both of the above cases, a cast expression can be used to explicitly convert one operand to a type that is compatible with the other operand.
Im BeispielIn the example
decimal AddPercent(decimal x, double percent) {
return x * (1.0 + percent / 100.0);
}
ein Fehler bei der Bindungs Zeit tritt auf, weil ein decimal
nicht mit einem multipliziert werden kann double
.a binding-time error occurs because a decimal
cannot be multiplied by a double
. Der Fehler wird behoben, indem der zweite Operand wie folgt explizit in umgerechnet wird decimal
:The error is resolved by explicitly converting the second operand to decimal
, as follows:
decimal AddPercent(decimal x, double percent) {
return x * (decimal)(1.0 + percent / 100.0);
}
„Lifted“ OperatorenLifted operators
Mithilfe von aufzurufenden Operatoren können vordefinierte und benutzerdefinierte Operatoren, die nicht auf NULL festleg Bare Werttypen angewendet werden, auch mit null-fähigen Formularen dieser Typen verwendet werdenLifted operators permit predefined and user-defined operators that operate on non-nullable value types to also be used with nullable forms of those types. Gesteigerte Operatoren werden aus vordefinierten und benutzerdefinierten Operatoren erstellt, die bestimmte Anforderungen erfüllen, wie im folgenden beschrieben:Lifted operators are constructed from predefined and user-defined operators that meet certain requirements, as described in the following:
Für die unären OperatorenFor the unary operators
+ ++ - -- ! ~
eine angehobene Form eines Operators ist vorhanden, wenn der Operand und die Ergebnistypen beide Werttypen sind, die keine NULL-Werte zulassen.a lifted form of an operator exists if the operand and result types are both non-nullable value types. Das angefügte Formular wird erstellt, indem ein einzelner
?
Modifizierer zu den Operanden-und Ergebnistypen hinzugefügt wird.The lifted form is constructed by adding a single?
modifier to the operand and result types. Der Operator "angehoben" erzeugt einen NULL-Wert, wenn der Operand NULL ist.The lifted operator produces a null value if the operand is null. Andernfalls entpackt der angehobene Operator den Operanden, wendet den zugrunde liegenden Operator an und umschließt das Ergebnis.Otherwise, the lifted operator unwraps the operand, applies the underlying operator, and wraps the result.Für die binären OperatorenFor the binary operators
+ - * / % & | ^ << >>
ein angezeigter Typ eines Operators ist vorhanden, wenn der Operand und die Ergebnistypen alle Werttypen darstellen, die keine NULL-Werte zulassen.a lifted form of an operator exists if the operand and result types are all non-nullable value types. Das angefügte Formular wird erstellt
?
, indem jedem Operanden und Ergebnistyp ein einzelner Modifizierer hinzugefügt wird.The lifted form is constructed by adding a single?
modifier to each operand and result type. Der gesteigerte Operator erzeugt einen NULL-Wert, wenn ein oder beide Operanden NULL sind (eine Ausnahme ist der&
-Operator und der-Operator|
des-bool?
Typs, wie in booleschen logischen Operatorenbeschrieben).The lifted operator produces a null value if one or both operands are null (an exception being the&
and|
operators of thebool?
type, as described in Boolean logical operators). Andernfalls entpackt der angehobene Operator die Operanden, wendet den zugrunde liegenden Operator an und umschließt das Ergebnis.Otherwise, the lifted operator unwraps the operands, applies the underlying operator, and wraps the result.Für die Gleichheits OperatorenFor the equality operators
== !=
eine angehobene Form eines Operators ist vorhanden, wenn die Operanden Typen sowohl nicht auf NULL festleg Bare Werttypen als auch, wenn der Ergebnistyp ist
bool
.a lifted form of an operator exists if the operand types are both non-nullable value types and if the result type isbool
. Das angefügte Formular wird erstellt, indem einem?
Operanden ein einzelner Modifizierer hinzugefügt wird.The lifted form is constructed by adding a single?
modifier to each operand type. Der Operator "angehoben" berücksichtigt zwei NULL-Werte gleich, und ein NULL-Wert entspricht keinem Wert, der ungleich NULL ist.The lifted operator considers two null values equal, and a null value unequal to any non-null value. Wenn beide Operanden nicht NULL sind, entpackt der angehobene Operator die Operanden und wendet den zugrunde liegenden Operator an, um das Ergebnis zu erhaltenbool
.If both operands are non-null, the lifted operator unwraps the operands and applies the underlying operator to produce thebool
result.Für die relationalen OperatorenFor the relational operators
< > <= >=
eine angehobene Form eines Operators ist vorhanden, wenn die Operanden Typen sowohl nicht auf NULL festleg Bare Werttypen als auch, wenn der Ergebnistyp ist
bool
.a lifted form of an operator exists if the operand types are both non-nullable value types and if the result type isbool
. Das angefügte Formular wird erstellt, indem einem?
Operanden ein einzelner Modifizierer hinzugefügt wird.The lifted form is constructed by adding a single?
modifier to each operand type. Der Operator "angehoben" erzeugt den Wert,false
Wenn ein oder beide Operanden NULL sind.The lifted operator produces the valuefalse
if one or both operands are null. Andernfalls entpackt der angehobene Operator die Operanden und wendet den zugrunde liegenden Operator an, um das Ergebnis zu erhaltenbool
.Otherwise, the lifted operator unwraps the operands and applies the underlying operator to produce thebool
result.
Member lookup (Membersuche)Member lookup
Bei der Suche nach Membern handelt es sich um den Prozess, bei dem die Bedeutung eines Namens im Kontext eines Typs bestimmt wird.A member lookup is the process whereby the meaning of a name in the context of a type is determined. Eine Element Suche kann als Teil der Auswertung eines Simple_name (einfache Namen) oder eines member_access (Member Access) in einem Ausdruck auftreten.A member lookup can occur as part of evaluating a simple_name (Simple names) or a member_access (Member access) in an expression. Wenn die Simple_name oder member_access als primary_expression einer invocation_expression (Methodenaufrufe) auftritt, wird der Member als aufgerufen bezeichnet.If the simple_name or member_access occurs as the primary_expression of an invocation_expression (Method invocations), the member is said to be invoked.
Wenn ein Member eine Methode oder ein Ereignis ist, oder wenn es sich um eine Konstante, ein Feld oder eine Eigenschaft eines Delegattyps (Delegaten ) oderdes Typs dynamic
(des dynamischen Typs) handelt, wird der Member als Aufruf barer Ausdruck bezeichnet.If a member is a method or event, or if it is a constant, field or property of either a delegate type (Delegates) or the type dynamic
(The dynamic type), then the member is said to be invocable.
Die Element Suche berücksichtigt nicht nur den Namen eines Members, sondern auch die Anzahl der Typparameter, die der Member hat und ob auf den Member zugegriffen werden kann.Member lookup considers not only the name of a member but also the number of type parameters the member has and whether the member is accessible. Für die Suche nach Membern verfügen generische Methoden und generische generische Typen über die Anzahl der Typparameter, die in den jeweiligen Deklarationen angegeben sind, und alle anderen Member haben keine Typparameter.For the purposes of member lookup, generic methods and nested generic types have the number of type parameters indicated in their respective declarations and all other members have zero type parameters.
Eine Member-Suche mit einem Namen N
mit K
Typparametern in einem Typ T
wird wie folgt verarbeitet:A member lookup of a name N
with K
type parameters in a type T
is processed as follows:
- Zuerst wird ein Satz barrierefreier Member mit dem Namen
N
bestimmt:First, a set of accessible members namedN
is determined:- Wenn
T
ein Typparameter ist, dann entspricht der Satz der Menge der zugreif baren Member, dieN
in jedem der Typen benannt sind, die als primäre Einschränkung oder sekundäre Einschränkung (Typparameter Einschränkungen) für angegebenT
sind, sowie der Menge der zugänglichen Member, die in benannt sindN
object
.IfT
is a type parameter, then the set is the union of the sets of accessible members namedN
in each of the types specified as a primary constraint or secondary constraint (Type parameter constraints) forT
, along with the set of accessible members namedN
inobject
. - Andernfalls besteht der Satz aus allen zugänglichen (Member Access) Membern
N
, die in benanntT
sind, einschließlich der geerbten Member und der zugänglichen MemberN
inobject
.Otherwise, the set consists of all accessible (Member access) members namedN
inT
, including inherited members and the accessible members namedN
inobject
. WennT
ein konstruierter Typ ist, wird der Satz von Membern durch Ersetzen von Typargumenten abgerufen, wie in Members von konstruierten Typenbeschrieben.IfT
is a constructed type, the set of members is obtained by substituting type arguments as described in Members of constructed types. Member, die einen-override
Modifizierer einschließen, werden aus dem Satz ausgeschlossen.Members that include anoverride
modifier are excluded from the set.
- Wenn
- Wenn dann auf
K
0 (null) gesetzt ist, werden alle nsted-Typen, deren Deklarationen Typparameter enthalten, entferntNext, ifK
is zero, all nested types whose declarations include type parameters are removed. WennK
nicht 0 (null) ist, werden alle Elemente mit einer anderen Anzahl von Typparametern entfernt.IfK
is not zero, all members with a different number of type parameters are removed. Beachten Sie, dassK
, wenn 0 (null) ist, keine Methoden mit Typparametern entfernt werden, da der Typrückschluss-Prozess (Typrückschluss) möglicherweise die Typargumente ableiten kann.Note that whenK
is zero, methods having type parameters are not removed, since the type inference process (Type inference) might be able to infer the type arguments. - Wenn der Member aufgerufen wird, werden alle nicht Aufruf baren Member aus dem Satz entfernt.Next, if the member is invoked, all non-invocable members are removed from the set.
- Als nächstes werden Elemente, die von anderen Membern ausgeblendet werden, aus dem Satz entfernt.Next, members that are hidden by other members are removed from the set. Für jedes Element
S.M
im Satz, wobeiS
der Typ ist, in dem der MemberM
deklariert wird, werden die folgenden Regeln angewendet:For every memberS.M
in the set, whereS
is the type in which the memberM
is declared, the following rules are applied:- Wenn
M
eine Konstante, ein Feld, eine Eigenschaft, ein Ereignis oder ein Enumerationsmember ist, werden alle in einem Basistyp von deklarierten MemberS
aus dem Satz entfernt.IfM
is a constant, field, property, event, or enumeration member, then all members declared in a base type ofS
are removed from the set. - Wenn
M
eine Typdeklaration ist, werden alle nicht-Typen, die in einem Basistyp von deklariertS
sind, aus dem Satz entfernt, und alle Typdeklarationen mit der gleichen Anzahl von Typparametern, dieM
in einem Basistyp von deklariertS
werden, werden aus dem Satz entfernt.IfM
is a type declaration, then all non-types declared in a base type ofS
are removed from the set, and all type declarations with the same number of type parameters asM
declared in a base type ofS
are removed from the set. - Wenn
M
eine Methode ist, werden alle nicht-Methoden Elemente, die in einem Basistyp von deklariertS
sind, aus dem Satz entfernt.IfM
is a method, then all non-method members declared in a base type ofS
are removed from the set.
- Wenn
- Als nächstes werden Schnittstellenmember, die von Klassenmembern ausgeblendet werden, aus dem Satz entfernt.Next, interface members that are hidden by class members are removed from the set. Dieser Schritt wirkt sich nur dann aus, wenn
T
ein Typparameter ist undT
sowohl eine effektive Basisklasse als alsobject
auch eine nicht leere effektive Schnittstellen Menge aufweist (Typparameter Einschränkungen).This step only has an effect ifT
is a type parameter andT
has both an effective base class other thanobject
and a non-empty effective interface set (Type parameter constraints). Für jeden MemberS.M
in der Menge, wobeiS
der Typ ist, in dem der MemberM
deklariert wird, werden die folgenden Regeln angewendet, wennS
eine andere Klassen Deklaration als istobject
:For every memberS.M
in the set, whereS
is the type in which the memberM
is declared, the following rules are applied ifS
is a class declaration other thanobject
:- Wenn
M
eine Konstante, ein Feld, eine Eigenschaft, ein Ereignis, ein Enumerationsmember oder eine Typdeklaration ist, werden alle in einer Schnittstellen Deklaration deklarierten Member aus dem Satz entfernt.IfM
is a constant, field, property, event, enumeration member, or type declaration, then all members declared in an interface declaration are removed from the set. - Wenn
M
eine Methode ist, werden alle nicht-Methoden Member, die in einer Schnittstellen Deklaration deklariert sind, aus dem Satz entfernt, und alle Methoden mit derselben Signatur, wie SieM
in einer Schnittstellen Deklaration deklariert sind, werden aus dem Satz entfernt.IfM
is a method, then all non-method members declared in an interface declaration are removed from the set, and all methods with the same signature asM
declared in an interface declaration are removed from the set.
- Wenn
- Schließlich wird das Ergebnis der Suche bestimmt, wenn verborgene Member entfernt wurden:Finally, having removed hidden members, the result of the lookup is determined:
- Wenn der Satz aus einem einzelnen Member besteht, der keine Methode ist, dann ist dieser Member das Ergebnis der Suche.If the set consists of a single member that is not a method, then this member is the result of the lookup.
- Andernfalls ist diese Gruppe von Methoden das Ergebnis der Suche, wenn der Satz nur Methoden enthält.Otherwise, if the set contains only methods, then this group of methods is the result of the lookup.
- Andernfalls ist die Suche mehrdeutig, und es tritt ein Bindungs Zeitfehler auf.Otherwise, the lookup is ambiguous, and a binding-time error occurs.
Für Member-suchen in anderen Typen als Typparameter und Schnittstellen und für Member-suchen in Schnittstellen, die nur eine einzelne Vererbung haben (jede Schnittstelle in der Vererbungs Kette weist genau null oder eine direkte Basisschnittstelle auf), besteht die Auswirkung der Such Regeln lediglich darin, dass abgeleitete Member Basiselemente mit dem gleichen Namen oder der gleichen Signatur ausblenden.For member lookups in types other than type parameters and interfaces, and member lookups in interfaces that are strictly single-inheritance (each interface in the inheritance chain has exactly zero or one direct base interface), the effect of the lookup rules is simply that derived members hide base members with the same name or signature. Solche Suchvorgänge mit einer einzelnen Vererbung sind nie mehrdeutig.Such single-inheritance lookups are never ambiguous. Die Mehrdeutigkeiten, die möglicherweise von Member-suchen in Schnittstellen mit mehreren Vererbungen auftreten können, werden unter Zugreifen auf die Benutzeroberflächebeschrieben.The ambiguities that can possibly arise from member lookups in multiple-inheritance interfaces are described in Interface member access.
Basis TypenBase types
Für Zwecke der Element Suche wird ein Typ T
als die folgenden Basis Typen betrachtet:For purposes of member lookup, a type T
is considered to have the following base types:
- Wenn
T
istobject
, dannT
hat keinen Basistyp.IfT
isobject
, thenT
has no base type. - Wenn
T
ein enum_type ist, sind die Basis Typen vonT
die KlassentypenSystem.Enum
,System.ValueType
undobject
.IfT
is an enum_type, the base types ofT
are the class typesSystem.Enum
,System.ValueType
, andobject
. - Wenn
T
ein struct_type ist, sind die Basis Typen vonT
die KlassentypenSystem.ValueType
undobject
.IfT
is a struct_type, the base types ofT
are the class typesSystem.ValueType
andobject
. - Wenn
T
ein class_type ist, sind die Basis Typen von dieT
Basisklassen vonT
, einschließlich des Klassen Typsobject
.IfT
is a class_type, the base types ofT
are the base classes ofT
, including the class typeobject
. - Wenn
T
ein INTERFACE_TYPE ist, sind die Basis Typen vonT
die Basis Schnittstellen vonT
und der-Klassentypobject
.IfT
is an interface_type, the base types ofT
are the base interfaces ofT
and the class typeobject
. - Wenn
T
ein array_type ist, sind die Basis Typen vonT
die KlassentypenSystem.Array
undobject
.IfT
is an array_type, the base types ofT
are the class typesSystem.Array
andobject
. - Wenn
T
ein delegate_type ist, sind die Basis Typen vonT
die KlassentypenSystem.Delegate
undobject
.IfT
is a delegate_type, the base types ofT
are the class typesSystem.Delegate
andobject
.
Function members (Funktionselemente)Function members
Funktionsmember sind Elemente, die ausführbare Anweisungen enthalten.Function members are members that contain executable statements. Funktionsmember sind immer Member von Typen und können keine Member von Namespaces sein.Function members are always members of types and cannot be members of namespaces. C# definiert die folgenden Kategorien von Funktionsmembern:C# defines the following categories of function members:
- MethodenMethods
- EigenschaftenProperties
- EreignisseEvents
- IndexerIndexers
- Benutzerdefinierte OperatorenUser-defined operators
- InstanzkonstruktorenInstance constructors
- Statische KonstruktorenStatic constructors
- DestruktorenDestructors
Mit Ausnahme der destrukturtoren und statischer Konstruktoren (die nicht explizit aufgerufen werden können) werden die in Funktionsmembern enthaltenen Anweisungen durch Funktionselement Aufrufe ausgeführt.Except for destructors and static constructors (which cannot be invoked explicitly), the statements contained in function members are executed through function member invocations. Die tatsächliche Syntax zum Schreiben eines Funktionsmember-aufzurufenden ist von der jeweiligen Funktionsmember-Kategorie abhängig.The actual syntax for writing a function member invocation depends on the particular function member category.
Die Argumentliste (Argumentlisten) eines Funktionsmember-aufzurufenden enthält tatsächliche Werte oder Variablen Verweise für die Parameter des Funktionsmembers.The argument list (Argument lists) of a function member invocation provides actual values or variable references for the parameters of the function member.
Aufrufe generischer Methoden können den Typrückschluss verwenden, um den Satz von Typargumenten zu ermitteln, die an die Methode übergeben werden sollen.Invocations of generic methods may employ type inference to determine the set of type arguments to pass to the method. Dieser Prozess wird unter Typrückschlussbeschrieben.This process is described in Type inference.
Aufrufe von Methoden, Indexern, Operatoren und Instanzkonstruktoren verwenden die Überladungs Auflösung, um zu bestimmen, welcher Satz von Funktions Membern aufgerufen werden soll.Invocations of methods, indexers, operators and instance constructors employ overload resolution to determine which of a candidate set of function members to invoke. Dieser Prozess wird in der Überladungs Auflösungbeschrieben.This process is described in Overload resolution.
Sobald ein bestimmter Funktionsmember zur Bindungs Zeit (möglicherweise durch Überladungs Auflösung) identifiziert wurde, wird der tatsächliche Lauf Zeit Prozess des Aufrufs des Funktionsmembers in der Kompilierzeit Überprüfung der dynamischen Überladungs Auflösungbeschrieben.Once a particular function member has been identified at binding-time, possibly through overload resolution, the actual run-time process of invoking the function member is described in Compile-time checking of dynamic overload resolution.
In der folgenden Tabelle wird die Verarbeitung zusammengefasst, die in-Konstrukten mit den sechs Kategorien von Funktionsmembern stattfindet, die explizit aufgerufen werden können.The following table summarizes the processing that takes place in constructs involving the six categories of function members that can be explicitly invoked. In der-Tabelle e
geben,, x
y
und value
Ausdrücke an, die als Variablen oder Werte klassifiziert sind, T
einen Ausdruck, der als Typ klassifiziert ist, F
den einfachen Namen einer Methode und P
den einfachen Namen einer Eigenschaft angibt.In the table, e
, x
, y
, and value
indicate expressions classified as variables or values, T
indicates an expression classified as a type, F
is the simple name of a method, and P
is the simple name of a property.
ErstellenConstruct | BeispielExample | BeschreibungDescription |
---|---|---|
MethodenaufrufMethod invocation | F(x,y) |
Die Überladungs Auflösung wird angewendet, um die beste Methode F in der enthaltenden Klasse oder Struktur auszuwählen.Overload resolution is applied to select the best method F in the containing class or struct. Die-Methode wird mit der Argumentliste aufgerufen (x,y) .The method is invoked with the argument list (x,y) . Wenn die-Methode nicht ist static , ist der Instanzausdruck this .If the method is not static , the instance expression is this . |
T.F(x,y) |
Die Überladungs Auflösung wird angewendet, um die beste Methode F in der Klasse oder Struktur auszuwählen T .Overload resolution is applied to select the best method F in the class or struct T . Ein Bindungs Zeit Fehler tritt auf, wenn die Methode nicht ist static .A binding-time error occurs if the method is not static . Die-Methode wird mit der Argumentliste aufgerufen (x,y) .The method is invoked with the argument list (x,y) . |
|
e.F(x,y) |
Die Überladungs Auflösung wird angewendet, um die beste Methode F in der Klasse, Struktur oder Schnittstelle auszuwählen, die durch den Typ von angegeben wird e .Overload resolution is applied to select the best method F in the class, struct, or interface given by the type of e . Ein Bindungs Zeit Fehler tritt auf, wenn die-Methode ist static .A binding-time error occurs if the method is static . Die-Methode wird mit dem Instanzausdruck e und der Argumentliste aufgerufen (x,y) .The method is invoked with the instance expression e and the argument list (x,y) . |
|
EigenschaftenzugriffProperty access | P |
Der- get Accessor der Eigenschaft P in der enthaltenden Klasse oder Struktur wird aufgerufen.The get accessor of the property P in the containing class or struct is invoked. Ein Kompilierzeitfehler tritt auf, wenn P schreibgeschützt ist.A compile-time error occurs if P is write-only. Wenn P nicht ist static , ist der Instanzausdruck this .If P is not static , the instance expression is this . |
P = value |
Der- set Accessor der Eigenschaft P in der enthaltenden Klasse oder Struktur wird mit der Argumentliste (value) aufgerufen.The set accessor of the property P in the containing class or struct is invoked with the argument list (value) . Ein Kompilierzeitfehler tritt auf, wenn schreibgeschützt P ist.A compile-time error occurs if P is read-only. Wenn P nicht ist static , ist der Instanzausdruck this .If P is not static , the instance expression is this . |
|
T.P |
Der- get Accessor der Eigenschaft P in der Klasse oder Struktur T wird aufgerufen.The get accessor of the property P in the class or struct T is invoked. Ein Kompilierzeitfehler tritt auf, wenn P nicht ist static oder wenn P schreibgeschützt ist.A compile-time error occurs if P is not static or if P is write-only. |
|
T.P = value |
Der- set Accessor der Eigenschaft P in der Klasse oder Struktur T wird mit der Argumentliste aufgerufen (value) .The set accessor of the property P in the class or struct T is invoked with the argument list (value) . Ein Kompilierzeitfehler tritt auf, wenn P nicht ist static oder wenn schreibgeschützt P ist.A compile-time error occurs if P is not static or if P is read-only. |
|
e.P |
Der- get Accessor der Eigenschaft P in der Klasse, Struktur oder Schnittstelle, die durch den-Typ angegeben e wird, wird mit dem Instanzausdruck aufgerufen e .The get accessor of the property P in the class, struct, or interface given by the type of e is invoked with the instance expression e . Ein Fehler bei der Bindungs Zeit tritt auf, wenn P ist static oder wenn P schreibgeschützt ist.A binding-time error occurs if P is static or if P is write-only. |
|
e.P = value |
Der set -Accessor der Eigenschaft P in der Klasse, Struktur oder Schnittstelle, die durch den Typ von angegeben e wird, wird mit dem Instanzausdruck e und der Argumentliste aufgerufen (value) .The set accessor of the property P in the class, struct, or interface given by the type of e is invoked with the instance expression e and the argument list (value) . Ein Fehler bei der Bindungs Zeit tritt auf, wenn P ist static oder wenn schreibgeschützt P ist.A binding-time error occurs if P is static or if P is read-only. |
|
Ereignis ZugriffEvent access | E += value |
Der- add Accessor des Ereignisses E in der enthaltenden Klasse oder Struktur wird aufgerufen.The add accessor of the event E in the containing class or struct is invoked. Wenn E nicht statisch ist, ist der Instanzausdruck this .If E is not static, the instance expression is this . |
E -= value |
Der- remove Accessor des Ereignisses E in der enthaltenden Klasse oder Struktur wird aufgerufen.The remove accessor of the event E in the containing class or struct is invoked. Wenn E nicht statisch ist, ist der Instanzausdruck this .If E is not static, the instance expression is this . |
|
T.E += value |
Der- add Accessor des Ereignisses E in der Klasse oder Struktur T wird aufgerufen.The add accessor of the event E in the class or struct T is invoked. Ein Fehler bei der Bindungs Zeit tritt auf, wenn E nicht statisch ist.A binding-time error occurs if E is not static. |
|
T.E -= value |
Der- remove Accessor des Ereignisses E in der Klasse oder Struktur T wird aufgerufen.The remove accessor of the event E in the class or struct T is invoked. Ein Fehler bei der Bindungs Zeit tritt auf, wenn E nicht statisch ist.A binding-time error occurs if E is not static. |
|
e.E += value |
Der- add Accessor des Ereignisses E in der Klasse, Struktur oder Schnittstelle, die durch den-Typ angegeben e wird, wird mit dem Instanzausdruck aufgerufen e .The add accessor of the event E in the class, struct, or interface given by the type of e is invoked with the instance expression e . Ein Fehler bei der Bindungs Zeit tritt auf, wenn E statisch ist.A binding-time error occurs if E is static. |
|
e.E -= value |
Der- remove Accessor des Ereignisses E in der Klasse, Struktur oder Schnittstelle, die durch den-Typ angegeben e wird, wird mit dem Instanzausdruck aufgerufen e .The remove accessor of the event E in the class, struct, or interface given by the type of e is invoked with the instance expression e . Ein Fehler bei der Bindungs Zeit tritt auf, wenn E statisch ist.A binding-time error occurs if E is static. |
|
IndexerzugriffIndexer access | e[x,y] |
Die Überladungs Auflösung wird angewendet, um den besten Indexer in der Klasse, Struktur oder Schnittstelle auszuwählen, die durch den Typ von e angegeben wird.Overload resolution is applied to select the best indexer in the class, struct, or interface given by the type of e. Der get -Accessor des Indexers wird mit dem Instanzausdruck e und der Argumentliste aufgerufen (x,y) .The get accessor of the indexer is invoked with the instance expression e and the argument list (x,y) . Ein Bindungs Zeit Fehler tritt auf, wenn der Indexer schreibgeschützt ist.A binding-time error occurs if the indexer is write-only. |
e[x,y] = value |
Die Überladungs Auflösung wird angewendet, um den besten Indexer in der Klasse, Struktur oder Schnittstelle auszuwählen, die durch den Typ von angegeben wird e .Overload resolution is applied to select the best indexer in the class, struct, or interface given by the type of e . Der set -Accessor des Indexers wird mit dem Instanzausdruck e und der Argumentliste aufgerufen (x,y,value) .The set accessor of the indexer is invoked with the instance expression e and the argument list (x,y,value) . Ein Bindungs Zeit Fehler tritt auf, wenn der Indexer schreibgeschützt ist.A binding-time error occurs if the indexer is read-only. |
|
Operator AufrufOperator invocation | -x |
Die Überladungs Auflösung wird angewendet, um den besten unären Operator in der Klasse oder Struktur auszuwählen, die durch den Typ von angegeben wird x .Overload resolution is applied to select the best unary operator in the class or struct given by the type of x . Der ausgewählte Operator wird mit der Argumentliste aufgerufen (x) .The selected operator is invoked with the argument list (x) . |
x + y |
Die Überladungs Auflösung wird angewendet, um den besten binären Operator in den Klassen oder Strukturen auszuwählen, die von den Typen von und angegeben werden x y .Overload resolution is applied to select the best binary operator in the classes or structs given by the types of x and y . Der ausgewählte Operator wird mit der Argumentliste aufgerufen (x,y) .The selected operator is invoked with the argument list (x,y) . |
|
InstanzkonstruktoraufrufInstance constructor invocation | new T(x,y) |
Die Überladungs Auflösung wird angewendet, um den besten Instanzkonstruktor in der Klasse oder Struktur auszuwählen T .Overload resolution is applied to select the best instance constructor in the class or struct T . Der Instanzkonstruktor wird mit der Argumentliste aufgerufen (x,y) .The instance constructor is invoked with the argument list (x,y) . |
Argument ListenArgument lists
Jeder Funktionsmember und Delegataufruf enthält eine Argumentliste, die tatsächliche Werte oder Variablen Verweise für die Parameter des Funktionsmembers bereitstellt.Every function member and delegate invocation includes an argument list which provides actual values or variable references for the parameters of the function member. Die Syntax zum Angeben der Argumentliste eines Funktionsmember-aufzurufenden ist von der Funktionsmember-Kategorie abhängig:The syntax for specifying the argument list of a function member invocation depends on the function member category:
- Bei Instanzkonstruktoren, Methoden, Indexern und Delegaten werden die Argumente als argument_list angegeben, wie unten beschrieben.For instance constructors, methods, indexers and delegates, the arguments are specified as an argument_list, as described below. Bei Indexers schließt beim Aufrufen der-Zugriffsmethode die
set
Argumentliste zusätzlich den Ausdruck ein, der als rechter Operand des Zuweisungs Operators angegeben ist.For indexers, when invoking theset
accessor, the argument list additionally includes the expression specified as the right operand of the assignment operator. - Bei-Eigenschaften ist die Argumentliste leer, wenn der-
get
Accessor aufgerufen wird, und besteht aus dem Ausdruck, der beim Aufrufen der Zugriffsmethode als rechter Operand des Zuweisungs Operators angegeben wurdeset
.For properties, the argument list is empty when invoking theget
accessor, and consists of the expression specified as the right operand of the assignment operator when invoking theset
accessor. - Bei Ereignissen besteht die Argumentliste aus dem Ausdruck, der als rechter Operand des or-
+=
Operators angegeben ist-=
.For events, the argument list consists of the expression specified as the right operand of the+=
or-=
operator. - Bei benutzerdefinierten Operatoren besteht die Argumentliste aus dem einzelnen Operanden des unären Operators oder den beiden Operanden des binären Operators.For user-defined operators, the argument list consists of the single operand of the unary operator or the two operands of the binary operator.
Die Argumente von Eigenschaften (Eigenschaften), Ereignissen (Ereignissen) und benutzerdefinierten Operatoren (Operatoren) werden immer als Wert Parameter (value-Parameter) übermittelt.The arguments of properties (Properties), events (Events), and user-defined operators (Operators) are always passed as value parameters (Value parameters). Die Argumente von Indexer (Indexer) werden immer als Wert Parameter (Wert Parameter) oder Parameter Arrays (Parameter Arrays) übergeben.The arguments of indexers (Indexers) are always passed as value parameters (Value parameters) or parameter arrays (Parameter arrays). Verweis-und Ausgabeparameter werden für diese Kategorien von Funktionsmembern nicht unterstützt.Reference and output parameters are not supported for these categories of function members.
Die Argumente eines Instanzkonstruktors, einer Methode, eines Indexers oder eines delegataufrufers werden als argument_list angegeben:The arguments of an instance constructor, method, indexer or delegate invocation are specified as an argument_list:
argument_list
: argument (',' argument)*
;
argument
: argument_name? argument_value
;
argument_name
: identifier ':'
;
argument_value
: expression
| 'ref' variable_reference
| 'out' variable_reference
;
Ein argument_list besteht aus einem oder mehreren Argumenten, getrennt durch Kommas.An argument_list consists of one or more argument s, separated by commas. Jedes Argument besteht aus einem optionalen argument_name gefolgt von einem argument_value.Each argument consists of an optional argument_name followed by an argument_value. Ein Argument mit einem argument_name wird als *benanntes Argument _ bezeichnet, wohingegen ein Argument * ohne argument_name ein *Positions Argument ist.An argument with an argument_name is referred to as a named argument _, whereas an _argument without an argument_name is a *positional argument_. Es ist ein Fehler für ein Positions Argument, das nach einem benannten Argument in einem _argument_list * angezeigt wird.It is an error for a positional argument to appear after a named argument in an _argument_list*.
Der argument_value kann eine der folgenden Formen annehmen:The argument_value can take one of the following forms:
- Ein Ausdruck, der angibt, dass das Argument als Wert Parameter (Wert Parameter) übergeben wird.An expression, indicating that the argument is passed as a value parameter (Value parameters).
- Das Schlüsselwort
ref
, gefolgt von einem variable_reference (Variablen Verweise), das angibt, dass das Argument als Verweis Parameter (Verweis Parameter) übergeben wird.The keywordref
followed by a variable_reference (Variable references), indicating that the argument is passed as a reference parameter (Reference parameters). Eine Variable muss definitiv zugewiesen werden (definitive Zuweisung), bevor Sie als Verweis Parameter übergeben werden kann.A variable must be definitely assigned (Definite assignment) before it can be passed as a reference parameter. Das Schlüsselwortout
, gefolgt von einem variable_reference (Variablen Verweise), das angibt, dass das Argument als Ausgabeparameter (Ausgabeparameter) übergeben wird.The keywordout
followed by a variable_reference (Variable references), indicating that the argument is passed as an output parameter (Output parameters). Eine Variable wird als definitiv zugewiesen (definitive Zuweisung) nach einem Funktionselement Aufruf, bei dem die Variable als Output-Parameter übergeben wird.A variable is considered definitely assigned (Definite assignment) following a function member invocation in which the variable is passed as an output parameter.
Entsprechende ParameterCorresponding parameters
Für jedes Argument in einer Argumentliste muss ein entsprechender Parameter im Funktions Member oder Delegaten vorhanden sein, der aufgerufen wird.For each argument in an argument list there has to be a corresponding parameter in the function member or delegate being invoked.
Die im folgenden verwendete Parameterliste wird wie folgt bestimmt:The parameter list used in the following is determined as follows:
- Bei virtuellen Methoden und indexatoren, die in Klassen definiert sind, wird die Parameterliste aus der spezifischsten Deklaration oder Überschreibung des Funktionsmembers ausgewählt, beginnend mit dem statischen Typ des Empfängers und Durchsuchen der zugehörigen Basisklassen.For virtual methods and indexers defined in classes, the parameter list is picked from the most specific declaration or override of the function member, starting with the static type of the receiver, and searching through its base classes.
- Für Schnittstellen Methoden und Indexer wird die Parameterliste aus der spezifischsten Definition des Members ausgewählt, beginnend mit dem Schnittstellentyp und Durchsuchen der Basis Schnittstellen.For interface methods and indexers, the parameter list is picked form the most specific definition of the member, starting with the interface type and searching through the base interfaces. Wenn keine eindeutige Parameterliste gefunden wird, wird eine Parameterliste mit nicht zugänglichen Namen und optionalen Parametern erstellt, sodass Aufrufe keine benannten Parameter verwenden können oder keine optionalen Argumente weglassen.If no unique parameter list is found, a parameter list with inaccessible names and no optional parameters is constructed, so that invocations cannot use named parameters or omit optional arguments.
- Bei partiellen Methoden wird die Parameterliste der definierenden partiellen Methoden Deklaration verwendet.For partial methods, the parameter list of the defining partial method declaration is used.
- Für alle anderen Funktionsmember und Delegaten gibt es nur eine einzige Parameterliste, die verwendet wird.For all other function members and delegates there is only a single parameter list, which is the one used.
Die Position eines Arguments oder Parameters wird als die Anzahl der Argumente oder Parameter definiert, die in der Argumentliste oder Parameterliste vorangestellt sind.The position of an argument or parameter is defined as the number of arguments or parameters preceding it in the argument list or parameter list.
Die entsprechenden Parameter für Funktionsmember-Argumente werden wie folgt festgelegt:The corresponding parameters for function member arguments are established as follows:
- Argumente im argument_list von Instanzkonstruktoren, Methoden, Indexern und Delegaten:Arguments in the argument_list of instance constructors, methods, indexers and delegates:
- Ein Positions Argument, bei dem ein fester Parameter an derselben Position in der Parameterliste auftritt, entspricht diesem Parameter.A positional argument where a fixed parameter occurs at the same position in the parameter list corresponds to that parameter.
- Ein Positions Argument eines Funktionsmembers mit einem Parameter Array, das in der normalen Form aufgerufen wird, entspricht dem Parameter Array, das an derselben Position in der Parameterliste vorkommen muss.A positional argument of a function member with a parameter array invoked in its normal form corresponds to the parameter array, which must occur at the same position in the parameter list.
- Ein Positions Argument eines Funktionsmembers mit einem Parameter Array, das in der erweiterten Form aufgerufen wird, wobei kein fester Parameter an derselben Position in der Parameterliste auftritt, entspricht einem Element im Parameter Array.A positional argument of a function member with a parameter array invoked in its expanded form, where no fixed parameter occurs at the same position in the parameter list, corresponds to an element in the parameter array.
- Ein benanntes Argument entspricht dem-Parameter mit dem gleichen Namen in der Parameterliste.A named argument corresponds to the parameter of the same name in the parameter list.
- Bei Indexers
set
entspricht der als rechter Operand des Zuweisungs Operators angegebene Ausdruck dem implizitenvalue
Parameter der Accessor-Deklaration, wenn der Accessor aufgerufen wirdset
.For indexers, when invoking theset
accessor, the expression specified as the right operand of the assignment operator corresponds to the implicitvalue
parameter of theset
accessor declaration.
- Bei-Eigenschaften
get
gibt es keine Argumente, wenn der-Accessor aufgerufen wird.For properties, when invoking theget
accessor there are no arguments. Wenn der-set
Accessor aufgerufen wird, entspricht der als rechter Operand des Zuweisungs Operators angegebene Ausdruck dem implizitenvalue
Parameter derset
Accessordeklaration.When invoking theset
accessor, the expression specified as the right operand of the assignment operator corresponds to the implicitvalue
parameter of theset
accessor declaration. - Bei benutzerdefinierten unären Operatoren (einschließlich Konvertierungen) entspricht der einzelne Operand dem einzelnen Parameter der Operator Deklaration.For user-defined unary operators (including conversions), the single operand corresponds to the single parameter of the operator declaration.
- Für benutzerdefinierte binäre Operatoren entspricht der linke Operand dem ersten Parameter, und der rechte Operand entspricht dem zweiten Parameter der Operator Deklaration.For user-defined binary operators, the left operand corresponds to the first parameter, and the right operand corresponds to the second parameter of the operator declaration.
Lauf Zeit Auswertung von ArgumentlistenRun-time evaluation of argument lists
Während der Lauf Zeit Verarbeitung eines Funktionsmember-aufzurufenden (Kompilierzeit Überprüfung der dynamischen Überladungs Auflösung) werden die Ausdrücke oder Variablen Verweise einer Argumentliste in der Reihenfolge von links nach rechts ausgewertet, wie folgt:During the run-time processing of a function member invocation (Compile-time checking of dynamic overload resolution), the expressions or variable references of an argument list are evaluated in order, from left to right, as follows:
- Bei einem value-Parameter wird der Argument Ausdruck ausgewertet und eine implizite Konvertierung (implizite Konvertierungen) in den entsprechenden Parametertyp durchgeführt.For a value parameter, the argument expression is evaluated and an implicit conversion (Implicit conversions) to the corresponding parameter type is performed. Der resultierende Wert wird zum Anfangswert des value-Parameters im Funktionselement Aufruf.The resulting value becomes the initial value of the value parameter in the function member invocation.
- Bei einem Verweis-oder Ausgabeparameter wird der Variablen Verweis ausgewertet, und der resultierende Speicherort wird zu dem Speicherort, der durch den-Parameter im Aufruf der Funktionselemente dargestellt wird.For a reference or output parameter, the variable reference is evaluated and the resulting storage location becomes the storage location represented by the parameter in the function member invocation. Wenn der als Verweis oder Ausgabeparameter angegebene Variablen Verweis ein Array Element einer reference_type ist, wird eine Lauf Zeit Überprüfung durchgeführt, um sicherzustellen, dass der Elementtyp des Arrays mit dem Parametertyp identisch ist.If the variable reference given as a reference or output parameter is an array element of a reference_type, a run-time check is performed to ensure that the element type of the array is identical to the type of the parameter. Wenn bei dieser Überprüfung ein Fehler auftritt, wird eine ausgelöst
System.ArrayTypeMismatchException
.If this check fails, aSystem.ArrayTypeMismatchException
is thrown.
Methoden, Indexer und Instanzkonstruktoren können Ihren äußersten ganz rechts Parameter als Parameter Array deklarieren (Parameter Arrays).Methods, indexers, and instance constructors may declare their right-most parameter to be a parameter array (Parameter arrays). Solche Funktionsmember werden entweder in ihrer normalen Form oder in der erweiterten Form aufgerufen, je nachdem, welche anwendbar ist (anwendbares Funktionsmember):Such function members are invoked either in their normal form or in their expanded form depending on which is applicable (Applicable function member):
- Wenn ein Funktionsmember mit einem Parameter Array in der normalen Form aufgerufen wird, muss das für das Parameter Array angegebene Argument ein einzelner Ausdruck sein, der implizit konvertierbar (implizite Konvertierungen) in den Typ des Parameter Arrays ist.When a function member with a parameter array is invoked in its normal form, the argument given for the parameter array must be a single expression that is implicitly convertible (Implicit conversions) to the parameter array type. In diesem Fall verhält sich das Parameter Array genau wie ein value-Parameter.In this case, the parameter array acts precisely like a value parameter.
- Wenn ein Funktionsmember mit einem Parameter Array in der erweiterten Form aufgerufen wird, muss der Aufruf NULL oder mehr Positions Argumente für das Parameter Array angeben, wobei jedes Argument ein Ausdruck ist, der implizit konvertierbar (implizite Konvertierungen) in den Elementtyp des Parameter Arrays ist.When a function member with a parameter array is invoked in its expanded form, the invocation must specify zero or more positional arguments for the parameter array, where each argument is an expression that is implicitly convertible (Implicit conversions) to the element type of the parameter array. In diesem Fall erstellt der Aufruf eine Instanz des Parameter Array Typs mit einer Länge, die der Anzahl der Argumente entspricht, initialisiert die Elemente der Array Instanz mit den angegebenen Argument Werten und verwendet die neu erstellte Array Instanz als tatsächliches Argument.In this case, the invocation creates an instance of the parameter array type with a length corresponding to the number of arguments, initializes the elements of the array instance with the given argument values, and uses the newly created array instance as the actual argument.
Die Ausdrücke einer Argumentliste werden immer in der Reihenfolge ausgewertet, in der Sie geschrieben werden.The expressions of an argument list are always evaluated in the order they are written. Das BeispielThus, the example
class Test
{
static void F(int x, int y = -1, int z = -2) {
System.Console.WriteLine("x = {0}, y = {1}, z = {2}", x, y, z);
}
static void Main() {
int i = 0;
F(i++, i++, i++);
F(z: i++, x: i++);
}
}
erzeugt die Ausgabeproduces the output
x = 0, y = 1, z = 2
x = 4, y = -1, z = 3
Die Array-Co-Varianz Regeln (Array-Kovarianz) erlauben, dass ein Wert eines Arraytyps A[]
ein Verweis auf eine Instanz eines Arraytyps B[]
ist, vorausgesetzt, dass eine implizite Verweis Konvertierung von in vorhanden ist B
A
.The array co-variance rules (Array covariance) permit a value of an array type A[]
to be a reference to an instance of an array type B[]
, provided an implicit reference conversion exists from B
to A
. Aufgrund dieser Regeln ist eine Lauf Zeit Überprüfung erforderlich, wenn ein Array Element einer reference_type als Verweis-oder Ausgabeparameter übergeben wird, um sicherzustellen, dass der tatsächliche Elementtyp des Arrays mit dem des Parameters identisch ist.Because of these rules, when an array element of a reference_type is passed as a reference or output parameter, a run-time check is required to ensure that the actual element type of the array is identical to that of the parameter. Im BeispielIn the example
class Test
{
static void F(ref object x) {...}
static void Main() {
object[] a = new object[10];
object[] b = new string[10];
F(ref a[0]); // Ok
F(ref b[1]); // ArrayTypeMismatchException
}
}
der zweite Aufruf von F
bewirkt System.ArrayTypeMismatchException
, dass eine ausgelöst wird, da der tatsächliche Elementtyp von b
ist string
und nicht object
.the second invocation of F
causes a System.ArrayTypeMismatchException
to be thrown because the actual element type of b
is string
and not object
.
Wenn ein Funktionsmember mit einem Parameter Array in der erweiterten Form aufgerufen wird, wird der Aufruf genau so verarbeitet, als ob ein Array Erstellungs Ausdruck mit einem Arrayinitialisierer (Array Erstellungs Ausdrücke) um die erweiterten Parameter eingefügt wurde.When a function member with a parameter array is invoked in its expanded form, the invocation is processed exactly as if an array creation expression with an array initializer (Array creation expressions) was inserted around the expanded parameters. Beispielsweise mit der DeklarationFor example, given the declaration
void F(int x, int y, params object[] args);
die folgenden Aufrufe der erweiterten Form der Methodethe following invocations of the expanded form of the method
F(10, 20);
F(10, 20, 30, 40);
F(10, 20, 1, "hello", 3.0);
genau entsprechencorrespond exactly to
F(10, 20, new object[] {});
F(10, 20, new object[] {30, 40});
F(10, 20, new object[] {1, "hello", 3.0});
Beachten Sie insbesondere, dass ein leeres Array erstellt wird, wenn keine Argumente für das Parameter Array angegeben werden.In particular, note that an empty array is created when there are zero arguments given for the parameter array.
Wenn Argumente von einem Funktionsmember mit entsprechenden optionalen Parametern ausgelassen werden, werden die Standardargumente der Deklaration des Funktions Members implizit übermittelt.When arguments are omitted from a function member with corresponding optional parameters, the default arguments of the function member declaration are implicitly passed. Da diese immer konstant sind, wirkt sich Ihre Auswertung nicht auf die Auswertungs Reihenfolge der restlichen Argumente aus.Because these are always constant, their evaluation will not impact the evaluation order of the remaining arguments.
TyprückschlussType inference
Wenn eine generische Methode ohne Angabe von Typargumenten aufgerufen wird, versucht ein Typrückschluss -Prozess, Typargumente für den Aufruf abzuleiten.When a generic method is called without specifying type arguments, a type inference process attempts to infer type arguments for the call. Das vorhanden sein des Typrückschlusses ermöglicht die Verwendung einer bequemeren Syntax zum Aufrufen einer generischen Methode und ermöglicht dem Programmierer, das Angeben von redundanten Typinformationen zu vermeiden.The presence of type inference allows a more convenient syntax to be used for calling a generic method, and allows the programmer to avoid specifying redundant type information. Beispielsweise mit der Methoden Deklaration:For example, given the method declaration:
class Chooser
{
static Random rand = new Random();
public static T Choose<T>(T first, T second) {
return (rand.Next(2) == 0)? first: second;
}
}
Es ist möglich, die Methode aufzurufen, Choose
ohne explizit ein Typargument anzugeben:it is possible to invoke the Choose
method without explicitly specifying a type argument:
int i = Chooser.Choose(5, 213); // Calls Choose<int>
string s = Chooser.Choose("foo", "bar"); // Calls Choose<string>
Durch den Typrückschluss werden die Typargumente int
und string
aus den Argumenten der Methode ermittelt.Through type inference, the type arguments int
and string
are determined from the arguments to the method.
Der Typrückschluss tritt als Teil der Bindungs Zeit Verarbeitung eines Methoden Aufrufs (Methodenaufrufe) auf und findet vor dem Schritt zur Überladungs Auflösung des Aufrufs statt.Type inference occurs as part of the binding-time processing of a method invocation (Method invocations) and takes place before the overload resolution step of the invocation. Wenn eine bestimmte Methoden Gruppe in einem Methodenaufruf angegeben wird und im Rahmen des Methoden aufruschlusses keine Typargumente angegeben werden, wird der Typrückschluss auf jede generische Methode in der Methoden Gruppe angewendet.When a particular method group is specified in a method invocation, and no type arguments are specified as part of the method invocation, type inference is applied to each generic method in the method group. Wenn der Typrückschluss erfolgreich ist, werden die Typargumente abgeleitet, um die Argument Typen für die nachfolgende Überladungs Auflösung zu bestimmen.If type inference succeeds, then the inferred type arguments are used to determine the types of arguments for subsequent overload resolution. Wenn die Überladungs Auflösung eine generische Methode als die aufzurufende Methode auswählt, werden die abgerufenen Typargumente als tatsächliche Typargumente für den Aufruf verwendet.If overload resolution chooses a generic method as the one to invoke, then the inferred type arguments are used as the actual type arguments for the invocation. Wenn der Typrückschluss für eine bestimmte Methode fehlschlägt, wird diese Methode nicht an der Überladungs Auflösung beteiligt.If type inference for a particular method fails, that method does not participate in overload resolution. Der Fehler beim Typrückschluss in und von sich führt nicht zu einem Bindungs Fehler.The failure of type inference, in and of itself, does not cause a binding-time error. Allerdings führt dies häufig zu einem Bindungs Fehler, wenn die Überladungs Auflösung dann keine anwendbaren Methoden findet.However, it often leads to a binding-time error when overload resolution then fails to find any applicable methods.
Wenn sich die angegebene Anzahl von Argumenten von der Anzahl der Parameter in der Methode unterscheidet, schlägt die Ableitung sofort fehl.If the supplied number of arguments is different than the number of parameters in the method, then inference immediately fails. Angenommen, die generische Methode hat die folgende Signatur:Otherwise, assume that the generic method has the following signature:
Tr M<X1,...,Xn>(T1 x1, ..., Tm xm)
Mit einem Methoden Aufrufder Form M(E1...Em)
ist die Aufgabe des Typrückschlusses das Auffinden eindeutiger Typargumente S1...Sn
für jeden der Typparameter, X1...Xn
sodass der-Befehl M<S1...Sn>(E1...Em)
gültig wird.With a method call of the form M(E1...Em)
the task of type inference is to find unique type arguments S1...Sn
for each of the type parameters X1...Xn
so that the call M<S1...Sn>(E1...Em)
becomes valid.
Während des Xi
Abschlusses wird jeder Typparameter entweder mit einem bestimmten Typ korrigiert Si
oder mit einem zugeordneten Satz von Begrenzungen nicht korrigiert .During the process of inference each type parameter Xi
is either fixed to a particular type Si
or unfixed with an associated set of bounds. Jede der Begrenzungen ist ein Typ T
.Each of the bounds is some type T
. Anfänglich wird jede Typvariable Xi
mit einem leeren Satz von Begrenzungen nicht korrigiert.Initially each type variable Xi
is unfixed with an empty set of bounds.
Der Typrückschluss findet in Phasen statt.Type inference takes place in phases. In jeder Phase wird versucht, Typargumente für weitere Typvariablen basierend auf den Ergebnissen der vorherigen Phase abzuleiten.Each phase will try to infer type arguments for more type variables based on the findings of the previous phase. In der ersten Phase werden einige anfängliche Rückschlüsse von Begrenzungen erstellt, während in der zweiten Phase Typvariablen für bestimmte Typen korrigiert und weitere Begrenzungen abgeleitet werden.The first phase makes some initial inferences of bounds, whereas the second phase fixes type variables to specific types and infers further bounds. Die zweite Phase muss möglicherweise mehrmals wiederholt werden.The second phase may have to be repeated a number of times.
Hinweis: Der Typrückschluss findet nicht nur statt, wenn eine generische Methode aufgerufen wird.Note: Type inference takes place not only when a generic method is called. Der Typrückschluss für die Konvertierung von Methoden Gruppen wird unter Typrückschluss für die Konvertierung von Methoden Gruppen beschrieben und der beste allgemeine Typ eines Satzes von Ausdrücken finden Sie unter Ermitteln des besten allgemeinen Typs eines Satzes von Ausdrücken.Type inference for conversion of method groups is described in Type inference for conversion of method groups and finding the best common type of a set of expressions is described in Finding the best common type of a set of expressions.
Die erste PhaseThe first phase
Für jedes der Methodenargumente Ei
:For each of the method arguments Ei
:
- Wenn
Ei
eine anonyme Funktion ist, wird ein expliziter parametertyprückschluss (explizite parametertyprückschluss) vonEi
zuTi
IfEi
is an anonymous function, an explicit parameter type inference (Explicit parameter type inferences) is made fromEi
toTi
- Andernfalls, wenn
Ei
einen-Typ aufweistU
undxi
ein value-Parameter ist, wird ein untergeordneter Daten Rückschluss vonU
bis erstelltTi
.Otherwise, ifEi
has a typeU
andxi
is a value parameter then a lower-bound inference is made fromU
toTi
. - Andernfalls, wenn
Ei
einen-Typ aufweistU
undxi
ein-oder-Parameter ist,ref
out
wird ein genauer Rückschluss vonU
auf vorgenommenTi
.Otherwise, ifEi
has a typeU
andxi
is aref
orout
parameter then an exact inference is made fromU
toTi
. - Andernfalls wird kein Rückschluss für dieses Argument gemacht.Otherwise, no inference is made for this argument.
Die zweite PhaseThe second phase
Die zweite Phase verläuft wie folgt:The second phase proceeds as follows:
- Alle unfixed -Typvariablen
Xi
, die nicht von abhängen (Abhängigkeit),Xj
werden korrigiert (Korrektur).All unfixed type variablesXi
which do not depend on (Dependence) anyXj
are fixed (Fixing). - Wenn keine derartigen Typvariablen vorhanden sind, werden alle nicht fixierten Typvariablen
Xi
korrigiert , für die Folgendes gilt:If no such type variables exist, all unfixed type variablesXi
are fixed for which all of the following hold:- Es ist mindestens eine Typvariable vorhanden
Xj
, von der abhängig ist.Xi
There is at least one type variableXj
that depends onXi
Xi
weist einen nicht leeren Satz von Begrenzungen auf.Xi
has a non-empty set of bounds
- Es ist mindestens eine Typvariable vorhanden
- Wenn keine Typvariablen vorhanden sind und noch immer unfixe Typvariablen vorhanden sind, schlägt der Typrückschluss fehl.If no such type variables exist and there are still unfixed type variables, type inference fails.
- Andernfalls ist der Typrückschluss erfolgreich, wenn keine weiteren unfixed -Typvariablen vorhanden sind.Otherwise, if no further unfixed type variables exist, type inference succeeds.
- Andernfalls wird für alle Argumente
Ei
mit dem entsprechenden Parametertyp,Ti
bei dem die Ausgabetypen (Ausgabetypen) nicht fixierte Typvariablen enthaltenXj
, die Eingabetypen (Eingabetypen) jedoch nicht, ein Ausgabetyp Rückschluss (Ausgabetyp Rückschlüsse) vonEi
auf erstelltTi
.Otherwise, for all argumentsEi
with corresponding parameter typeTi
where the output types (Output types) contain unfixed type variablesXj
but the input types (Input types) do not, an output type inference (Output type inferences) is made fromEi
toTi
. Die zweite Phase wird wiederholt.Then the second phase is repeated.
EingabetypenInput types
Wenn E
eine Methoden Gruppe oder implizit typisierte anonyme Funktion ist und T
ein Delegattyp oder ein Ausdrucks Strukturtyp ist, sind alle Parametertypen von T
Eingabetypen vom E
Typ T
.If E
is a method group or implicitly typed anonymous function and T
is a delegate type or expression tree type then all the parameter types of T
are input types of E
with type T
.
AusgabetypenOutput types
Wenn E
eine Methoden Gruppe oder eine anonyme Funktion ist und T
ein Delegattyp oder ein Ausdrucks Strukturtyp ist, ist der T
Rückgabetyp von ein Ausgabetyp von E
mit dem Typ T
.If E
is a method group or an anonymous function and T
is a delegate type or expression tree type then the return type of T
is an output type of E
with type T
.
HänDependence
Eine Variable vom Typ " unfixed " Xi
ist direkt von einer Variablen vom Typ "unfixed" abhängig , Xj
Wenn für ein Argument vom Ek
Typ Tk
Xj
in einem Eingabetyp von Ek
mit Type auftritt Tk
und Xi
in einem Ausgabetyp von Ek
mit Type auftritt Tk
.An unfixed type variable Xi
depends directly on an unfixed type variable Xj
if for some argument Ek
with type Tk
Xj
occurs in an input type of Ek
with type Tk
and Xi
occurs in an output type of Ek
with type Tk
.
Xj
hängt von ab Xi
, wenn direkt von oder abhängig ist, von der abhängig ist Xj
Xi
und abhängig ist Xi
Xk
Xk
Xj
.Xj
depends on Xi
if Xj
depends directly on Xi
or if Xi
depends directly on Xk
and Xk
depends on Xj
. Daher ist "hängt von" der transitiv, aber nicht reflexive Abschluss von "ist direkt abhängig".Thus "depends on" is the transitive but not reflexive closure of "depends directly on".
Ausschlüsse auf AusgabetypOutput type inferences
Ein ausgabetyprückschluss erfolgt auf folgende Weise von einem Ausdruck E
zu einem Typ T
:An output type inference is made from an expression E
to a type T
in the following way:
- Wenn
E
eine anonyme Funktion mit einem abzurufenden RückgabetypU
(Rückgabetyp abgeleitet) ist undT
ein Delegattyp oder ein Ausdrucks Strukturtyp mit dem Rückgabetyp istTb
, wird ein niedrigerer gebundener Typrückschluss (niedrigerer gebundener Rückschluss) vonU
bis vorgenommenTb
.IfE
is an anonymous function with inferred return typeU
(Inferred return type) andT
is a delegate type or expression tree type with return typeTb
, then a lower-bound inference (Lower-bound inferences) is made fromU
toTb
. - Andernfalls, wenn
E
eine Methoden Gruppe ist undT
ein Delegattyp oder ein Ausdrucks Strukturtyp mit ParametertypenT1...Tk
und dem Rückgabetyp istTb
und die Überladungs Auflösung vonE
mit den-TypenT1...Tk
eine einzelne Methode mit dem Rückgabetyp ergibtU
, wird ein untergeordneter Daten Rückschluss vonU
in vorgenommenTb
.Otherwise, ifE
is a method group andT
is a delegate type or expression tree type with parameter typesT1...Tk
and return typeTb
, and overload resolution ofE
with the typesT1...Tk
yields a single method with return typeU
, then a lower-bound inference is made fromU
toTb
. - Andernfalls, wenn
E
ein Ausdruck mit dem Typ istU
, wird ein untergeordneter Daten Rückschluss vonU
bis erstelltT
.Otherwise, ifE
is an expression with typeU
, then a lower-bound inference is made fromU
toT
. - Andernfalls werden keine Rückschlüsse gemacht.Otherwise, no inferences are made.
Explizite Parametertyp RückschlüsseExplicit parameter type inferences
Ein expliziter Parameter-Typrückschluss erfolgt auf folgende Weise von einem Ausdruck E
zu einem Typ T
:An explicit parameter type inference is made from an expression E
to a type T
in the following way:
- Wenn
E
eine explizit typisierte anonyme Funktion mit ParametertypenU1...Uk
ist undT
ein Delegattyp oder ein Ausdrucks Strukturtyp mit Parametertypen istV1...Vk
Ui
, wird für jeden ein genauer Rück Schluss (exakte Rückschlüsse) vonUi
auf das entsprechende-Objekt erstelltVi
.IfE
is an explicitly typed anonymous function with parameter typesU1...Uk
andT
is a delegate type or expression tree type with parameter typesV1...Vk
then for eachUi
an exact inference (Exact inferences) is made fromUi
to the correspondingVi
.
Exakte RückschlüsseExact inferences
Eine genaue Ableitung von einem Typ U
zu einem Typ V
erfolgt wie folgt:An exact inference from a type U
to a type V
is made as follows:
Wenn
V
eine der unfixen istXi
U
, wird dem Satz der exakten Begrenzungen für hinzugefügtXi
.IfV
is one of the unfixedXi
thenU
is added to the set of exact bounds forXi
.Andernfalls legt
V1...Vk
undU1...Uk
fest, indem überprüft wird, ob eines der folgenden Fälle zutrifft:Otherwise, setsV1...Vk
andU1...Uk
are determined by checking if any of the following cases apply:V
ist ein ArraytypV1[...]
undU
ist ein ArraytypU1[...]
desselben Rang.V
is an array typeV1[...]
andU
is an array typeU1[...]
of the same rankV
der TypV1?
undU
ist der Typ.U1?
V
is the typeV1?
andU
is the typeU1?
V
ist ein konstruierter TypC<V1...Vk>
undU
ist ein konstruierter Typ.C<U1...Uk>
V
is a constructed typeC<V1...Vk>
andU
is a constructed typeC<U1...Uk>
Wenn einer dieser Fälle zutrifft, erfolgt ein genauer Rückschluss von jedem
Ui
zum entsprechendenVi
.If any of these cases apply then an exact inference is made from eachUi
to the correspondingVi
.Andernfalls werden keine Rückschlüsse gemacht.Otherwise no inferences are made.
Unten gebundene RückschlüsseLower-bound inferences
Ein untergeordneter Daten Rückschluss von einem Typ U
zu einem Typ V
wird wie folgt erstellt:A lower-bound inference from a type U
to a type V
is made as follows:
Wenn
V
eine der nicht fixierten istXi
U
, wird der Gruppe der unteren Grenzen für hinzugefügtXi
.IfV
is one of the unfixedXi
thenU
is added to the set of lower bounds forXi
.Andernfalls, wenn
V
der-TypV1?
undU
der-Typ ist,U1?
wird ein niedrigerer gebundener Rückschluss vonU1
auf vorgenommenV1
.Otherwise, ifV
is the typeV1?
andU
is the typeU1?
then a lower bound inference is made fromU1
toV1
.Andernfalls legt
U1...Uk
undV1...Vk
fest, indem überprüft wird, ob eines der folgenden Fälle zutrifft:Otherwise, setsU1...Uk
andV1...Vk
are determined by checking if any of the following cases apply:V
ist ein ArraytypV1[...]
undU
ist ein ArraytypU1[...]
(oder ein Typparameter, dessen effektiver Basistyp istU1[...]
) desselben Rang.V
is an array typeV1[...]
andU
is an array typeU1[...]
(or a type parameter whose effective base type isU1[...]
) of the same rankV
ist eine vonIEnumerable<V1>
,ICollection<V1>
oder,IList<V1>
undU
ist ein eindimensionaler ArraytypU1[]
(oder ein Typparameter, dessen effektiver Basistyp istU1[]
).V
is one ofIEnumerable<V1>
,ICollection<V1>
orIList<V1>
andU
is a one-dimensional array typeU1[]
(or a type parameter whose effective base type isU1[]
)V
ist eine konstruierte Klasse, eine Struktur, eine Schnittstelle oder ein Delegattyp,C<V1...Vk>
und es gibt einen eindeutigen Typ,C<U1...Uk>
sodassU
(oder, wennU
ein Typparameter ist, die effektive Basisklasse oder ein beliebiger Member des effektiven Schnittstellen Satzes) mit identisch ist, von (direkt oder indirekt) erbt oder (direkt oder indirekt) implementiertC<U1...Uk>
.V
is a constructed class, struct, interface or delegate typeC<V1...Vk>
and there is a unique typeC<U1...Uk>
such thatU
(or, ifU
is a type parameter, its effective base class or any member of its effective interface set) is identical to, inherits from (directly or indirectly), or implements (directly or indirectly)C<U1...Uk>
.(Die "Eindeutigkeits Einschränkung" bedeutet, dass in der Fall Schnittstelle
C<T> {} class U: C<X>, C<Y> {}
kein Rückschluss erfolgt, wenn von zu abgeleitet wird,U
C<T>
daU1
möglicherweiseX
oder istY
.)(The "uniqueness" restriction means that in the case interfaceC<T> {} class U: C<X>, C<Y> {}
, then no inference is made when inferring fromU
toC<T>
becauseU1
could beX
orY
.)
Wenn einer dieser Fälle zutrifft, erfolgt ein Rückschluss von jedem
Ui
zum entsprechenden,Vi
wie folgt:If any of these cases apply then an inference is made from eachUi
to the correspondingVi
as follows:- Wenn
Ui
nicht bekannt ist, dass es sich um einen Verweistyp handelt, wird ein genauer Rückschluss gemacht.IfUi
is not known to be a reference type then an exact inference is made - Andernfalls, wenn
U
ein Arraytyp ist, wird ein Rück Schluss mit niedrigerer Bindung erstellt.Otherwise, ifU
is an array type then a lower-bound inference is made - Andernfalls
V
C<V1...Vk>
hängt der Rückschluss vom i-th Type-Parameter von abC
:Otherwise, ifV
isC<V1...Vk>
then inference depends on the i-th type parameter ofC
:- Wenn Sie kovariant ist, wird ein Rück Schluss ausgelöst.If it is covariant then a lower-bound inference is made.
- Wenn Sie kontra Variant ist, wird eine obere gebundene Ableitung vorgenommen.If it is contravariant then an upper-bound inference is made.
- Wenn Sie invariante ist, wird ein genauer Rückschluss gemacht.If it is invariant then an exact inference is made.
Andernfalls werden keine Rückschlüsse gemacht.Otherwise, no inferences are made.
Obere gebundene RückschlüsseUpper-bound inferences
Eine obere gebundene Ableitung von einem Typ U
zu einem Typ V
wird wie folgt durchgeführt:An upper-bound inference from a type U
to a type V
is made as follows:
Wenn
V
eine der nicht fixierten istXi
U
, wird dem Satz von oberen Begrenzungen für hinzugefügtXi
.IfV
is one of the unfixedXi
thenU
is added to the set of upper bounds forXi
.Andernfalls legt
V1...Vk
undU1...Uk
fest, indem überprüft wird, ob eines der folgenden Fälle zutrifft:Otherwise, setsV1...Vk
andU1...Uk
are determined by checking if any of the following cases apply:U
ist ein ArraytypU1[...]
undV
ist ein ArraytypV1[...]
desselben Rang.U
is an array typeU1[...]
andV
is an array typeV1[...]
of the same rankU
ist eine vonIEnumerable<Ue>
,ICollection<Ue>
oder,IList<Ue>
undV
ist ein eindimensionaler Arraytyp.Ve[]
U
is one ofIEnumerable<Ue>
,ICollection<Ue>
orIList<Ue>
andV
is a one-dimensional array typeVe[]
U
der TypU1?
undV
ist der Typ.V1?
U
is the typeU1?
andV
is the typeV1?
U
ist eine konstruierte Klasse, Struktur, Schnittstelle oder DelegattypC<U1...Uk>
undV
ist eine Klasse, Struktur, Schnittstelle oder ein Delegattyp, der mit identisch ist, von (direkt oder indirekt) erbt oder (direkt oder indirekt) einen eindeutigen Typ implementiert.C<V1...Vk>
U
is constructed class, struct, interface or delegate typeC<U1...Uk>
andV
is a class, struct, interface or delegate type which is identical to, inherits from (directly or indirectly), or implements (directly or indirectly) a unique typeC<V1...Vk>
(Die "Eindeutigkeits Einschränkung" bedeutet, dass, wenn dies der Fall ist
interface C<T>{} class V<Z>: C<X<Z>>, C<Y<Z>>{}
, kein Rückschluss erfolgt, wenn von zu abgeleitet wirdC<U1>
V<Q>
.(The "uniqueness" restriction means that if we haveinterface C<T>{} class V<Z>: C<X<Z>>, C<Y<Z>>{}
, then no inference is made when inferring fromC<U1>
toV<Q>
. Rückschlüsse werden nicht vonU1
entweder in oder aus vorgenommenX<Q>
Y<Q>
.)Inferences are not made fromU1
to eitherX<Q>
orY<Q>
.)
Wenn einer dieser Fälle zutrifft, erfolgt ein Rückschluss von jedem
Ui
zum entsprechenden,Vi
wie folgt:If any of these cases apply then an inference is made from eachUi
to the correspondingVi
as follows:- Wenn
Ui
nicht bekannt ist, dass es sich um einen Verweistyp handelt, wird ein genauer Rückschluss gemacht.IfUi
is not known to be a reference type then an exact inference is made - Andernfalls, wenn
V
ein Arraytyp ist, wird eine obere gebundene Ableitung vorgenommen.Otherwise, ifV
is an array type then an upper-bound inference is made - Andernfalls
U
C<U1...Uk>
hängt der Rückschluss vom i-th Type-Parameter von abC
:Otherwise, ifU
isC<U1...Uk>
then inference depends on the i-th type parameter ofC
:- Wenn Sie kovariant ist, wird eine obere gebundene Ableitung vorgenommen.If it is covariant then an upper-bound inference is made.
- Wenn Sie kontra Variant ist, wird ein Rück Schluss festgestellt.If it is contravariant then a lower-bound inference is made.
- Wenn Sie invariante ist, wird ein genauer Rückschluss gemacht.If it is invariant then an exact inference is made.
Andernfalls werden keine Rückschlüsse gemacht.Otherwise, no inferences are made.
Korrektur von Fixing
Eine Variable vom Typ " unfixed " Xi
mit einem Satz von Begrenzungen ist wie folgt festgelegt :An unfixed type variable Xi
with a set of bounds is fixed as follows:
- Der Satz von Kandidaten Typen
Uj
beginnt als der Satz aller Typen im Satz von Begrenzungen fürXi
.The set of candidate typesUj
starts out as the set of all types in the set of bounds forXi
. - Anschließend untersuchen wir jede gebundene Grenze
Xi
: für jede exakte GrenzeU
Xi
aller TypenUj
, die nicht identisch sind,U
werden aus dem Kandidaten Satz entfernt.We then examine each bound forXi
in turn: For each exact boundU
ofXi
all typesUj
which are not identical toU
are removed from the candidate set. Für jede untere GrenzeU
Xi
aller TypenUj
, auf die keine implizite Konvertierung von erfolgt,U
werden aus dem Kandidaten Satz entfernt.For each lower boundU
ofXi
all typesUj
to which there is not an implicit conversion fromU
are removed from the candidate set. Für jede obere GrenzeU
Xi
aller TypenUj
, von denen keine implizite Konvertierung in vorhanden ist,U
werden aus dem Kandidaten Satz entfernt.For each upper boundU
ofXi
all typesUj
from which there is not an implicit conversion toU
are removed from the candidate set. - Wenn es sich bei den verbleibenden Kandidaten Typen um
Uj
einen eindeutigen Typ handeltV
, von dem eine implizite Konvertierung in alle anderen Kandidaten Typen erfolgt, dannXi
ist auf festV
.If among the remaining candidate typesUj
there is a unique typeV
from which there is an implicit conversion to all the other candidate types, thenXi
is fixed toV
. - Andernfalls schlägt der Typrückschluss fehl.Otherwise, type inference fails.
Rückgabetyp abgeleitetInferred return type
Der abzurufende Rückgabetyp einer anonymen Funktion F
wird bei der Typrückschluss-und Überladungs Auflösung verwendet.The inferred return type of an anonymous function F
is used during type inference and overload resolution. Der zurückgegebene Rückgabetyp kann nur für eine anonyme Funktion bestimmt werden, bei der alle Parametertypen bekannt sind, da Sie entweder explizit angegeben werden, indem Sie durch eine anonyme Funktions Konvertierung bereitgestellt oder während des Typrückschlusses bei einem einschließenden generischen Methodenaufruf abgeleitet werden.The inferred return type can only be determined for an anonymous function where all parameter types are known, either because they are explicitly given, provided through an anonymous function conversion or inferred during type inference on an enclosing generic method invocation.
Der abhergelegte Ergebnistyp wird wie folgt bestimmt:The inferred result type is determined as follows:
- Wenn der Text von
F
ein Ausdruck ist, der über einen-Typ verfügt, ist der herausgestellte Ergebnistyp vonF
der Typ dieses Ausdrucks.If the body ofF
is an expression that has a type, then the inferred result type ofF
is the type of that expression. - Wenn es sich bei dem Text von
F
um einen- Block handelt und der Satz von Ausdrücken in den-Anweisungen des Blocksreturn
einen am besten allgemeinen Typ aufweist (suchen SieT
den am besten allgemeinen Typ eines Satzes von Ausdrücken), dann ist der abhergelegte Ergebnistyp vonF
T
.If the body ofF
is a block and the set of expressions in the block'sreturn
statements has a best common typeT
(Finding the best common type of a set of expressions), then the inferred result type ofF
isT
. - Andernfalls kann ein Ergebnistyp nicht für abgeleitet werden
F
.Otherwise, a result type cannot be inferred forF
.
Der zurückgegebene Rückgabetyp wird wie folgt bestimmt:The inferred return type is determined as follows:
- Wenn
F
Async ist und der Text vonF
entweder ein Ausdruck ist, der als Nothing (Ausdrucks Klassifizierungen) klassifiziert ist, oder ein Anweisungsblock, in dem keine Return-Anweisungen über Ausdrücke verfügen, ist der Rückschluss Rückgabetyp.System.Threading.Tasks.Task
IfF
is async and the body ofF
is either an expression classified as nothing (Expression classifications), or a statement block where no return statements have expressions, the inferred return type isSystem.Threading.Tasks.Task
- Wenn
F
Async ist und einen abhergelegten Ergebnistyp aufweistT
, ist der Rückschluss RückgabetypSystem.Threading.Tasks.Task<T>
.IfF
is async and has an inferred result typeT
, the inferred return type isSystem.Threading.Tasks.Task<T>
. - Wenn
F
nicht Async ist und einen abhergelegten Ergebnistyp aufweistT
, ist der Rückschluss RückgabetypT
.IfF
is non-async and has an inferred result typeT
, the inferred return type isT
. - Andernfalls kann kein Rückgabetyp für abgeleitet werden
F
.Otherwise a return type cannot be inferred forF
.
Sehen Sie sich als Beispiel für den Typrückschluss mit anonymen Funktionen die Select
in der-Klasse deklarierte Erweiterungsmethode an System.Linq.Enumerable
:As an example of type inference involving anonymous functions, consider the Select
extension method declared in the System.Linq.Enumerable
class:
namespace System.Linq
{
public static class Enumerable
{
public static IEnumerable<TResult> Select<TSource,TResult>(
this IEnumerable<TSource> source,
Func<TSource,TResult> selector)
{
foreach (TSource element in source) yield return selector(element);
}
}
}
Vorausgesetzt, System.Linq
dass der Namespace mit einer using
-Klausel importiert wurde und eine-Klasse Customer
mit einer- Name
Eigenschaft des Typs angegeben wurde string
, kann die- Select
Methode verwendet werden, um die Namen einer Kundenliste auszuwählen:Assuming the System.Linq
namespace was imported with a using
clause, and given a class Customer
with a Name
property of type string
, the Select
method can be used to select the names of a list of customers:
List<Customer> customers = GetCustomerList();
IEnumerable<string> names = customers.Select(c => c.Name);
Der Aufruf der Erweiterungsmethode (Erweiterungs Methodenaufrufe) von Select
wird verarbeitet, indem der Aufruf in einen statischen Methodenaufruf umgeschrieben wird:The extension method invocation (Extension method invocations) of Select
is processed by rewriting the invocation to a static method invocation:
IEnumerable<string> names = Enumerable.Select(customers, c => c.Name);
Da Typargumente nicht explizit angegeben wurden, wird der Typrückschluss verwendet, um die Typargumente abzuleiten.Since type arguments were not explicitly specified, type inference is used to infer the type arguments. Zuerst ist das- customers
Argument mit dem-Parameter verknüpft und wird als source
abgeleitet T
Customer
.First, the customers
argument is related to the source
parameter, inferring T
to be Customer
. Anschließend wird mit dem oben beschriebenen Prozess der anonymen Funktionstyp Ableitung der c
Typ angegeben Customer
, und der Ausdruck c.Name
ist mit dem Rückgabetyp des selector
Parameters verknüpft, S
string
der als abgeleitet wird.Then, using the anonymous function type inference process described above, c
is given type Customer
, and the expression c.Name
is related to the return type of the selector
parameter, inferring S
to be string
. Daher entspricht der Aufruf demThus, the invocation is equivalent to
Sequence.Select<Customer,string>(customers, (Customer c) => c.Name)
und das Ergebnis ist vom Typ IEnumerable<string>
.and the result is of type IEnumerable<string>
.
Im folgenden Beispiel wird veranschaulicht, wie der anonyme Funktionstyp Rückschluss das Eingeben von Typinformationen zwischen Argumenten in einem generischen Methodenaufruf zulässt.The following example demonstrates how anonymous function type inference allows type information to "flow" between arguments in a generic method invocation. Bei Angabe der-Methode:Given the method:
static Z F<X,Y,Z>(X value, Func<X,Y> f1, Func<Y,Z> f2) {
return f2(f1(value));
}
Typrückschluss für den Aufruf:Type inference for the invocation:
double seconds = F("1:15:30", s => TimeSpan.Parse(s), t => t.TotalSeconds);
geht wie folgt vor: zuerst wird das-Argument mit "1:15:30"
dem-Parameter verknüpft, der als value
abgeleitet wird X
string
.proceeds as follows: First, the argument "1:15:30"
is related to the value
parameter, inferring X
to be string
. Anschließend erhält der-Parameter der ersten anonymen Funktion, s
, den abzurufenden Typ string
, und der Ausdruck TimeSpan.Parse(s)
ist mit dem Rückgabetyp von verknüpft f1
, der als abgeleitet wird Y
System.TimeSpan
.Then, the parameter of the first anonymous function, s
, is given the inferred type string
, and the expression TimeSpan.Parse(s)
is related to the return type of f1
, inferring Y
to be System.TimeSpan
. Schließlich erhält der-Parameter der zweiten anonymen Funktion, t
, den abzurufenden Typ System.TimeSpan
, und der Ausdruck t.TotalSeconds
ist mit dem Rückgabetyp von verknüpft, der als f2
abgeleitet wird Z
double
.Finally, the parameter of the second anonymous function, t
, is given the inferred type System.TimeSpan
, and the expression t.TotalSeconds
is related to the return type of f2
, inferring Z
to be double
. Daher ist das Ergebnis des auf-aufgabens vom Typ double
.Thus, the result of the invocation is of type double
.
Typrückschluss für die Konvertierung von Methoden GruppenType inference for conversion of method groups
Ähnlich wie bei Aufrufen von generischen Methoden muss der Typrückschluss auch angewendet werden, wenn eine Methoden Gruppe M
, die eine generische Methode enthält, in einen angegebenen Delegattyp konvertiert wird D
(Methoden Gruppen Konvertierungen).Similar to calls of generic methods, type inference must also be applied when a method group M
containing a generic method is converted to a given delegate type D
(Method group conversions). Bei Angabe einer MethodeGiven a method
Tr M<X1...Xn>(T1 x1 ... Tm xm)
und die Methoden Gruppe, die M
dem Delegattyp zugewiesen wird, D
ist die Aufgabe des Typrückschlusses, die Typargumente zu suchen S1...Sn
, sodass der Ausdruck:and the method group M
being assigned to the delegate type D
the task of type inference is to find type arguments S1...Sn
so that the expression:
M<S1...Sn>
wird mit kompatibel (Delegatdeklarationen) D
.becomes compatible (Delegate declarations) with D
.
Im Gegensatz zum Typrückschluss-Algorithmus für generische Methodenaufrufe gibt es in diesem Fall nur Argument Typen, keine Argument Ausdrücke.Unlike the type inference algorithm for generic method calls, in this case there are only argument types, no argument expressions. Insbesondere gibt es keine anonymen Funktionen und daher keinen Bedarf an mehreren Phasen des Inferenz.In particular, there are no anonymous functions and hence no need for multiple phases of inference.
Stattdessen werden alle Xi
als nicht korrigiert betrachtet, und es wird ein Rück Schluss aus jedem Argumenttyp Uj
von D
auf den entsprechenden Parametertyp von erstellt Tj
M
.Instead, all Xi
are considered unfixed, and a lower-bound inference is made from each argument type Uj
of D
to the corresponding parameter type Tj
of M
. Wenn für eine beliebige Grenze Xi
keine Begrenzungen gefunden werden, schlägt der Typrückschluss fehl.If for any of the Xi
no bounds were found, type inference fails. Andernfalls werden alle Xi
entsprechend korrigiert Si
, was das Ergebnis des Typrückschlusses ist.Otherwise, all Xi
are fixed to corresponding Si
, which are the result of type inference.
Ermitteln des am häufigsten verbreiteten Typs eines Satzes von AusdrückenFinding the best common type of a set of expressions
In einigen Fällen muss ein gemeinsamer Typ für einen Satz von Ausdrücken abgeleitet werden.In some cases, a common type needs to be inferred for a set of expressions. Insbesondere werden die Elementtypen von implizit typisierten Arrays und die Rückgabe Typen anonymer Funktionen mit Block Text auf diese Weise gefunden.In particular, the element types of implicitly typed arrays and the return types of anonymous functions with block bodies are found in this way.
Intuitiv, wenn ein Satz von Ausdrücken ist, E1...Em
sollte dieser Rückschluss dem Aufrufen einer Methode entsprechen.Intuitively, given a set of expressions E1...Em
this inference should be equivalent to calling a method
Tr M<X>(X x1 ... X xm)
mit den Ei
As-Argumenten.with the Ei
as arguments.
Genauer ist, dass der Rückschluss mit einer Variablen vom Typ " unfixed " beginnt X
.More precisely, the inference starts out with an unfixed type variable X
. Die Ausschlüsse auf Ausgabetyp werden dann von jedem Ei
in vorgenommen X
.Output type inferences are then made from each Ei
to X
. Schließlich X
ist korrigiert , und wenn der Vorgang erfolgreich ist, ist der resultierende Typ S
der resultierende am besten geeignete Typ für die Ausdrücke.Finally, X
is fixed and, if successful, the resulting type S
is the resulting best common type for the expressions. Wenn kein solcher S
vorhanden ist, haben die Ausdrücke keinen besten allgemeinen Typ.If no such S
exists, the expressions have no best common type.
ÜberladungsauflösungOverload resolution
Bei der Überladungs Auflösung handelt es sich um einen Bindungs zeitmechanismus zum Auswählen des besten Funktionsmembers, der beim Aufrufen einer Argumentliste und eines Satzes von Kandidaten Funktions Membern aufgerufen wird.Overload resolution is a binding-time mechanism for selecting the best function member to invoke given an argument list and a set of candidate function members. Die Überladungs Auflösung wählt den Funktions Member aus, der in den folgenden unterschiedlichen Kontexten in c# aufgerufen werden soll:Overload resolution selects the function member to invoke in the following distinct contexts within C#:
- Aufruf einer Methode mit dem Namen in einem invocation_expression (Methodenaufrufe).Invocation of a method named in an invocation_expression (Method invocations).
- Aufruf eines Instanzkonstruktors, der in einem object_creation_expression namens (Objekt Erstellungs Ausdrücke) genannt wird.Invocation of an instance constructor named in an object_creation_expression (Object creation expressions).
- Aufruf eines Indexeraccessors über einen element_access (Element Zugriff).Invocation of an indexer accessor through an element_access (Element access).
- Aufruf eines vordefinierten oder benutzerdefinierten Operators, auf den in einem Ausdruck verwiesen wird (unäre Operator Überladungs Auflösung und binäre Operator Überladungs Auflösung).Invocation of a predefined or user-defined operator referenced in an expression (Unary operator overload resolution and Binary operator overload resolution).
Jeder dieser Kontexte definiert den Satz von Kandidaten Funktionsmembern und die Liste der Argumente in der eigenen, eindeutigen Weise, wie in den oben aufgeführten Abschnitten ausführlich beschrieben.Each of these contexts defines the set of candidate function members and the list of arguments in its own unique way, as described in detail in the sections listed above. Beispielsweise enthält der Satz von Kandidaten für einen Methodenaufruf keine Methoden, die als override
(Member Suche) markiert sind, und Methoden in einer Basisklasse sind keine Kandidaten, wenn eine Methode in einer abgeleiteten Klasse anwendbar ist (MethodenAufrufe).For example, the set of candidates for a method invocation does not include methods marked override
(Member lookup), and methods in a base class are not candidates if any method in a derived class is applicable (Method invocations).
Nachdem die Kandidaten Funktions Member und die Argumentliste identifiziert wurden, ist die Auswahl des besten Funktionsmembers in allen Fällen identisch:Once the candidate function members and the argument list have been identified, the selection of the best function member is the same in all cases:
- In Anbetracht der Menge der anwendbaren Kandidaten Funktionsmember befindet sich das beste Funktionsmember in dieser Gruppe.Given the set of applicable candidate function members, the best function member in that set is located. Wenn die Menge nur ein Funktionsmember enthält, ist dieses Funktionsmember das beste Funktionsmember.If the set contains only one function member, then that function member is the best function member. Andernfalls ist das beste Funktionsmember der ein Funktionsmember, der besser als alle anderen Funktionsmember in Bezug auf die angegebene Argumentliste ist, vorausgesetzt, dass jeder Funktionsmember mit allen anderen Funktionsmembern verglichen wird, wobei die Regeln in einem besseren Funktionsmemberverwendet werden.Otherwise, the best function member is the one function member that is better than all other function members with respect to the given argument list, provided that each function member is compared to all other function members using the rules in Better function member. Wenn nicht genau ein Funktionsmember vorhanden ist, der besser als alle anderen Funktionsmember ist, dann ist der Funktionselement Aufruf mehrdeutig, und ein Bindungs Fehler tritt auf.If there is not exactly one function member that is better than all other function members, then the function member invocation is ambiguous and a binding-time error occurs.
In den folgenden Abschnitten wird die genaue Bedeutung der Begriffe *anwendbarer Funktionsmember _ und _ besseres Funktionsmember * definiert.The following sections define the exact meanings of the terms applicable function member _ and _better function member**.
Anwendbares FunktionsmemberApplicable function member
Ein Funktionsmember wird als anwendbares Funktionsmember in Bezug auf eine Argumentliste bezeichnet, A
Wenn alle folgenden Punkte zutreffen:A function member is said to be an applicable function member with respect to an argument list A
when all of the following are true:
- Jedes Argument in
A
entspricht einem Parameter in der Deklaration des Funktions Members, wie in den entsprechenden Parameternbeschrieben, und jeder Parameter, dem kein Argument entspricht, ist ein optionaler Parameter.Each argument inA
corresponds to a parameter in the function member declaration as described in Corresponding parameters, and any parameter to which no argument corresponds is an optional parameter. - Für jedes Argument in
A
ist der Parameter Übergabe Modus des Arguments (d. h. Value,ref
oderout
) identisch mit dem Parameter Übergabe Modus des entsprechenden Parameters.For each argument inA
, the parameter passing mode of the argument (i.e., value,ref
, orout
) is identical to the parameter passing mode of the corresponding parameter, and- für einen value-Parameter oder ein Parameter Array ist eine implizite Konvertierung (implizite Konvertierungen) vom-Argument in den Typ des entsprechenden Parameters vorhanden, oderfor a value parameter or a parameter array, an implicit conversion (Implicit conversions) exists from the argument to the type of the corresponding parameter, or
- bei einem-
ref
oder-out
Parameter ist der Typ des Arguments mit dem Typ des entsprechenden Parameters identisch.for aref
orout
parameter, the type of the argument is identical to the type of the corresponding parameter. Schließlichref
out
ist der-Parameter oder der-Parameter ein Alias für das übergebenen Argument.After all, aref
orout
parameter is an alias for the argument passed.
Bei einem Funktionsmember, der ein Parameter Array enthält, gilt Folgendes: Wenn das Funktionsmember durch die oben genannten Regeln anwendbar ist, wird es als anwendbar in der *normalen Form _ bezeichnet.For a function member that includes a parameter array, if the function member is applicable by the above rules, it is said to be applicable in its *normal form . Wenn ein Funktionsmember, der ein Parameter Array enthält, nicht in der normalen Form anwendbar ist, kann der Funktionsmember stattdessen in seiner Form " erweitert" ( *) angewendet werden:If a function member that includes a parameter array is not applicable in its normal form, the function member may instead be applicable in its _*expanded form**:
- Das erweiterte Formular wird erstellt, indem das Parameter Array in der Deklaration des Funktions Members durch Null oder mehr Wert Parameter des Elementtyps des Parameter Arrays ersetzt wird, sodass die Anzahl der Argumente in der Argumentliste mit
A
der Gesamtanzahl der Parameter übereinstimmt.The expanded form is constructed by replacing the parameter array in the function member declaration with zero or more value parameters of the element type of the parameter array such that the number of arguments in the argument listA
matches the total number of parameters. WennA
weniger Argumente aufweist als die Anzahl fester Parameter in der Deklaration des Funktions Members, kann die erweiterte Form des Funktionsmembers nicht erstellt werden und ist daher nicht anwendbar.IfA
has fewer arguments than the number of fixed parameters in the function member declaration, the expanded form of the function member cannot be constructed and is thus not applicable. - Andernfalls ist das erweiterte Formular anwendbar, wenn für jedes Argument im
A
Parameter Übergabe Modus des Arguments mit dem Parameter Übergabe Modus des entsprechenden Parameters identisch ist, undOtherwise, the expanded form is applicable if for each argument inA
the parameter passing mode of the argument is identical to the parameter passing mode of the corresponding parameter, and- bei einem Parameter mit festem Wert oder einem Wert Parameter, der durch die Erweiterung erstellt wurde, ist eine implizite Konvertierung (implizite Konvertierungen) vom Typ des Arguments in den Typ des entsprechenden Parameters vorhanden.for a fixed value parameter or a value parameter created by the expansion, an implicit conversion (Implicit conversions) exists from the type of the argument to the type of the corresponding parameter, or
- bei einem-
ref
oder-out
Parameter ist der Typ des Arguments mit dem Typ des entsprechenden Parameters identisch.for aref
orout
parameter, the type of the argument is identical to the type of the corresponding parameter.
Besseres FunktionsmemberBetter function member
Zum Ermitteln des besseren Funktionsmembers wird eine Liste der aus dem ausgebauten Argument enthaltenen Elemente erstellt, die nur die Argument Ausdrücke selbst in der Reihenfolge enthält, in der Sie in der ursprünglichen Argumentliste angezeigt werden.For the purposes of determining the better function member, a stripped-down argument list A is constructed containing just the argument expressions themselves in the order they appear in the original argument list.
Parameter Listen für jeden der Kandidaten Funktionsmember werden wie folgt erstellt:Parameter lists for each of the candidate function members are constructed in the following way:
- Das erweiterte Formular wird verwendet, wenn das Funktionsmember nur in der erweiterten Form anwendbar ist.The expanded form is used if the function member was applicable only in the expanded form.
- Optionale Parameter ohne entsprechende Argumente werden aus der Parameterliste entfernt.Optional parameters with no corresponding arguments are removed from the parameter list
- Die Parameter werden neu angeordnet, sodass Sie an derselben Position wie das entsprechende Argument in der Argumentliste auftreten.The parameters are reordered so that they occur at the same position as the corresponding argument in the argument list.
Wenn eine Argumentliste A
mit einem Satz von Argument Ausdrücken {E1, E2, ..., En}
und zwei anwendbaren Funktionsmembern Mp
und Mq
mit Parametertypen {P1, P2, ..., Pn}
und {Q1, Q2, ..., Qn}
Mp
definiert ist, wird ein besseres Funktionsmember definiert als Mq
ifGiven an argument list A
with a set of argument expressions {E1, E2, ..., En}
and two applicable function members Mp
and Mq
with parameter types {P1, P2, ..., Pn}
and {Q1, Q2, ..., Qn}
, Mp
is defined to be a better function member than Mq
if
- die implizite Konvertierung von in ist für jedes
Ex
ArgumentQx
nicht besser geeignet als bei der impliziten Konvertierung vonEx
inPx
.for each argument, the implicit conversion fromEx
toQx
is not better than the implicit conversion fromEx
toPx
, and - für mindestens ein Argument ist die Konvertierung von
Ex
inPx
besser als die Konvertierung vonEx
inQx
.for at least one argument, the conversion fromEx
toPx
is better than the conversion fromEx
toQx
.
Wenn Sie diese Auswertung durchführen, wenn Mp
oder Mq
in der erweiterten Form anwendbar ist Px
, Qx
verweist oder auf einen Parameter in der erweiterten Form der Parameterliste.When performing this evaluation, if Mp
or Mq
is applicable in its expanded form, then Px
or Qx
refers to a parameter in the expanded form of the parameter list.
Für den Fall, dass die Parametertyp Sequenzen {P1, P2, ..., Pn}
und {Q1, Q2, ..., Qn}
äquivalent sind (d. h. Pi
, jede verfügt über eine Identitäts Konvertierung in die entsprechende Qi
), werden die folgenden Regeln zum Durchbrechen von Regeln angewendet, um den besseren Funktionsmember zu ermitteln.In case the parameter type sequences {P1, P2, ..., Pn}
and {Q1, Q2, ..., Qn}
are equivalent (i.e. each Pi
has an identity conversion to the corresponding Qi
), the following tie-breaking rules are applied, in order, to determine the better function member.
- Wenn
Mp
eine nicht generische Methode ist undMq
eine generische Methode ist, dannMp
ist besser alsMq
.IfMp
is a non-generic method andMq
is a generic method, thenMp
is better thanMq
. - Andernfalls ist, wenn
Mp
in der normalen Form anwendbar undMq
einparams
-Array hat und nur in der erweiterten Form anwendbar ist,Mp
besser alsMq
.Otherwise, ifMp
is applicable in its normal form andMq
has aparams
array and is applicable only in its expanded form, thenMp
is better thanMq
. - Andernfalls ist, wenn
Mp
mehr deklarierte Parameter als aufweistMq
,Mp
besser alsMq
.Otherwise, ifMp
has more declared parameters thanMq
, thenMp
is better thanMq
. Dies kann vorkommen, wenn beide Methoden überparams
Arrays verfügen und nur in ihren erweiterten Formularen anwendbar sind.This can occur if both methods haveparams
arrays and are applicable only in their expanded forms. - Andernfalls, wenn alle Parameter von
Mp
ein entsprechendes Argument aufweisen, während Standardargumente mindestens einen optionalen Parameter in ersetzen müssen,Mq
Mp
ist besser alsMq
.Otherwise if all parameters ofMp
have a corresponding argument whereas default arguments need to be substituted for at least one optional parameter inMq
thenMp
is better thanMq
. - Wenn andernfalls
Mp
spezifischere Parametertypen als aufweistMq
, dannMp
ist besser alsMq
.Otherwise, ifMp
has more specific parameter types thanMq
, thenMp
is better thanMq
.{R1, R2, ..., Rn}
Stellen Sie{S1, S2, ..., Sn}
die nicht instanziierten und nicht erweiterten Parametertypen vonMp
und darMq
.Let{R1, R2, ..., Rn}
and{S1, S2, ..., Sn}
represent the uninstantiated and unexpanded parameter types ofMp
andMq
.Mp
die Parametertypen sind spezifischer als,Mq
Wenn für jeden ParameterRx
nicht weniger spezifisch als ist,Sx
und für mindestens einen ParameterRx
eher spezifischer alsSx
:Mp
's parameter types are more specific thanMq
's if, for each parameter,Rx
is not less specific thanSx
, and, for at least one parameter,Rx
is more specific thanSx
:- Ein Typparameter ist weniger spezifisch als ein nicht-Typparameter.A type parameter is less specific than a non-type parameter.
- Ein konstruierter Typ ist rekursiv spezifischer als ein anderer konstruierter Typ (mit der gleichen Anzahl von Typargumenten), wenn mindestens ein Typargument spezifischer ist und kein Typargument weniger spezifisch als das entsprechende Typargument in der anderen ist.Recursively, a constructed type is more specific than another constructed type (with the same number of type arguments) if at least one type argument is more specific and no type argument is less specific than the corresponding type argument in the other.
- Ein Arraytyp ist spezifischer als ein anderer Arraytyp (mit der gleichen Anzahl von Dimensionen), wenn der Elementtyp des ersten spezifischeren ist als der Elementtyp der zweiten.An array type is more specific than another array type (with the same number of dimensions) if the element type of the first is more specific than the element type of the second.
- Wenn ein Member ein nicht gesperrter Operator und der andere ein gesperrter Operator ist, ist der nicht--gesteigerte-Operator besser.Otherwise if one member is a non-lifted operator and the other is a lifted operator, the non-lifted one is better.
- Andernfalls ist keines der Funktionsmember besser.Otherwise, neither function member is better.
Bessere Konvertierung von AusdrückenBetter conversion from expression
Wenn eine implizite Konvertierung, C1
die von einem Ausdruck E
in einen-Typ konvertiert T1
wird, und eine implizite Konvertierung, C2
die von einem Ausdruck E
in einen-Typ konvertiert wird T2
, C1
eine bessere Konvertierung ist, als C2
Wenn E
nicht genau übereinstimmt T2
und mindestens einer der folgenden Punkte enthält:Given an implicit conversion C1
that converts from an expression E
to a type T1
, and an implicit conversion C2
that converts from an expression E
to a type T2
, C1
is a better conversion than C2
if E
does not exactly match T2
and at least one of the following holds:
E
genau ÜbereinstimmungenT1
(exakt übereinstimmenden Ausdruck)E
exactly matchesT1
(Exactly matching Expression)T1
ist ein besseres Konvertierungs Ziel alsT2
(besseres Konvertierungs Ziel)T1
is a better conversion target thanT2
(Better conversion target)
Exakt übereinstimmender AusdruckExactly matching Expression
Bei einem Ausdruck E
und einem Typ T
E
stimmt genau überein, T
Wenn eine der folgenden Punkte Folgendes enthält:Given an expression E
and a type T
, E
exactly matches T
if one of the following holds:
E
weist einen TypS
auf, und eine Identitäts Konvertierung ist vonS
zuT
E
has a typeS
, and an identity conversion exists fromS
toT
E
ist eine anonyme Funktion,T
ist entweder ein DelegattypD
oder ein Ausdrucks Strukturtyp,Expression<D>
und einer der folgenden enthält Folgendes:E
is an anonymous function,T
is either a delegate typeD
or an expression tree typeExpression<D>
and one of the following holds:- Für wird ein abherüberder Rückgabetyp
X
E
im Kontext der ParameterlisteD
(abgeleitet Rückgabetyp) und eine Identitäts Konvertierung von inX
den RückgabetypD
An inferred return typeX
exists forE
in the context of the parameter list ofD
(Inferred return type), and an identity conversion exists fromX
to the return type ofD
- Entweder
E
ist nicht Async undD
hat einen Rückgabetyp oder ist asynchronY
E
undD
verfügt über einen RückgabetypTask<Y>
, und eine der folgenden Punkte enthält:EitherE
is non-async andD
has a return typeY
orE
is async andD
has a return typeTask<Y>
, and one of the following holds:- Der Text von
E
ist ein Ausdruck, der genau übereinstimmt.Y
The body ofE
is an expression that exactly matchesY
- Der Text von
E
ist ein Anweisungsblock, in dem jede Return-Anweisung einen Ausdruck zurückgibt, der genau übereinstimmtY
The body ofE
is a statement block where every return statement returns an expression that exactly matchesY
- Der Text von
- Für wird ein abherüberder Rückgabetyp
Besseres Konvertierungs ZielBetter conversion target
Bei zwei verschiedenen Typen T1
und T2
T1
ist ein besseres Konvertierungs Ziel als, T2
Wenn keine implizite Konvertierung von T2
in vorhanden ist T1
, und mindestens eine der folgenden Werte enthält:Given two different types T1
and T2
, T1
is a better conversion target than T2
if no implicit conversion from T2
to T1
exists, and at least one of the following holds:
- Eine implizite Konvertierung von
T1
in istT2
vorhanden.An implicit conversion fromT1
toT2
exists T1
ist entweder ein DelegattypD1
oder ein Ausdrucks bauentypExpression<D1>
,T2
ist entweder ein DelegattypD2
oder ein Ausdrucks bauentypExpression<D2>
,D1
hat einen RückgabetypS1
und eine der folgenden Punkte:T1
is either a delegate typeD1
or an expression tree typeExpression<D1>
,T2
is either a delegate typeD2
or an expression tree typeExpression<D2>
,D1
has a return typeS1
and one of the following holds:D2
ist void-RückgabeD2
is void returningD2
hat einen RückgabetypS2
undS1
ist ein besseres Konvertierungs Ziel alsS2
D2
has a return typeS2
, andS1
is a better conversion target thanS2
T1
istTask<S1>
,T2
istTask<S2>
, undS1
ist ein besseres Konvertierungs Ziel alsS2
T1
isTask<S1>
,T2
isTask<S2>
, andS1
is a better conversion target thanS2
T1
istS1
oder, wobei ein ganzzahliger Typ mit Vorzeichen istS1?
S1
, undT2
ist oder, wenn ein ganzzahligerS2
S2?
S2
Typ ohne Vorzeichen ist.T1
isS1
orS1?
whereS1
is a signed integral type, andT2
isS2
orS2?
whereS2
is an unsigned integral type. Dies betrifft insbesondere:Specifically:S1
istsbyte
S2
, und istbyte
,ushort
,uint
oderulong
S1
issbyte
andS2
isbyte
,ushort
,uint
, orulong
S1
istshort
S2
, und istushort
,uint
oder.ulong
S1
isshort
andS2
isushort
,uint
, orulong
S1
istint
S2
, und istuint
, oderulong
S1
isint
andS2
isuint
, orulong
S1
ist,long
undS2
istulong
S1
islong
andS2
isulong
Überladen in generischen KlassenOverloading in generic classes
Obwohl Signaturen wie deklariert eindeutig sein müssen, ist es möglich, dass die Ersetzung von Typargumenten zu identischen Signaturen führt.While signatures as declared must be unique, it is possible that substitution of type arguments results in identical signatures. In solchen Fällen werden die oben genannten Regeln der Überladungs Auflösung über den spezifischsten Member ausgewählt.In such cases, the tie-breaking rules of overload resolution above will pick the most specific member.
Die folgenden Beispiele zeigen über Ladungen, die gemäß dieser Regel gültig und ungültig sind:The following examples show overloads that are valid and invalid according to this rule:
interface I1<T> {...}
interface I2<T> {...}
class G1<U>
{
int F1(U u); // Overload resolution for G<int>.F1
int F1(int i); // will pick non-generic
void F2(I1<U> a); // Valid overload
void F2(I2<U> a);
}
class G2<U,V>
{
void F3(U u, V v); // Valid, but overload resolution for
void F3(V v, U u); // G2<int,int>.F3 will fail
void F4(U u, I1<V> v); // Valid, but overload resolution for
void F4(I1<V> v, U u); // G2<I1<int>,int>.F4 will fail
void F5(U u1, I1<V> v2); // Valid overload
void F5(V v1, U u2);
void F6(ref U u); // valid overload
void F6(out V v);
}
Kompilierzeit Überprüfung der Auflösung dynamischer ÜberladungenCompile-time checking of dynamic overload resolution
Bei den meisten dynamisch gebundenen Vorgängen ist der Satz möglicher Kandidaten für die Auflösung zur Kompilierzeit nicht bekannt.For most dynamically bound operations the set of possible candidates for resolution is unknown at compile-time. In bestimmten Fällen ist der Kandidaten Satz jedoch zum Zeitpunkt der Kompilierung bekannt:In certain cases, however the candidate set is known at compile-time:
- Statische Methodenaufrufe mit dynamischen ArgumentenStatic method calls with dynamic arguments
- Instanzmethodenaufrufe, bei denen der Empfänger kein dynamischer Ausdruck istInstance method calls where the receiver is not a dynamic expression
- Indexer-Aufrufe, bei denen der Empfänger kein dynamischer Ausdruck istIndexer calls where the receiver is not a dynamic expression
- Konstruktoraufrufe mit dynamischen ArgumentenConstructor calls with dynamic arguments
In diesen Fällen wird für jeden Kandidaten eine beschränkte Kompilierzeit Überprüfung durchgeführt, um festzustellen, ob eine dieser Vorgänge möglicherweise zur Laufzeit angewendet werden könnte. Diese Überprüfung umfasst die folgenden Schritte:In these cases a limited compile-time check is performed for each candidate to see if any of them could possibly apply at run-time.This check consists of the following steps:
- Partieller Typrückschluss: alle Typargumente, die nicht direkt oder indirekt von einem Argument des Typs abhängen, werden
dynamic
mithilfe der Regeln des Typrückschlussesabgeleitet.Partial type inference: Any type argument that does not depend directly or indirectly on an argument of typedynamic
is inferred using the rules of Type inference. Die übrigen Typargumente sind unbekannt.The remaining type arguments are unknown. - Partielle Anwendbarkeit der Anwendbarkeit: die Anwendbarkeit wird gemäß dem anwendbaren Funktionsmemberüberprüft, wobei Parameter, deren Typen unbekannt sind, ignoriert werden.Partial applicability check: Applicability is checked according to Applicable function member, but ignoring parameters whose types are unknown.
- Wenn kein Kandidat diesen Test durchläuft, tritt ein Kompilierzeitfehler auf.If no candidate passes this test, a compile-time error occurs.
Funktionselement AufrufFunction member invocation
In diesem Abschnitt wird der Prozess beschrieben, der zur Laufzeit ausgeführt wird, um einen bestimmten Funktionsmember aufzurufen.This section describes the process that takes place at run-time to invoke a particular function member. Es wird davon ausgegangen, dass ein Bindungs Zeit Prozess bereits den aufzurufenden Member ermittelt hat, möglicherweise durch Anwenden der Überladungs Auflösung auf einen Satz von Kandidaten Funktionsmembern.It is assumed that a binding-time process has already determined the particular member to invoke, possibly by applying overload resolution to a set of candidate function members.
Um den Aufrufprozess zu beschreiben, werden Funktionsmember in zwei Kategorien unterteilt:For purposes of describing the invocation process, function members are divided into two categories:
- Statische Funktionsmember.Static function members. Dabei handelt es sich um Instanzkonstruktoren, statische Methoden, statische Eigenschaftenaccessoren und benutzerdefinierte Operatoren.These are instance constructors, static methods, static property accessors, and user-defined operators. Statische Funktionsmember sind immer nicht virtuell.Static function members are always non-virtual.
- Instanzfunktionsmember.Instance function members. Dabei handelt es sich um Instanzmethoden, Accessoren für Instanzeigenschaften und Indexer-Accessoren.These are instance methods, instance property accessors, and indexer accessors. Instanzfunktionsmember sind entweder nicht virtuell oder virtuell und werden immer für eine bestimmte Instanz aufgerufen.Instance function members are either non-virtual or virtual, and are always invoked on a particular instance. Die Instanz wird durch einen Instanzausdruck berechnet und kann innerhalb des Funktionsmembers als
this
(dieser Zugriff) aufgerufen werden.The instance is computed by an instance expression, and it becomes accessible within the function member asthis
(This access).
Die Lauf Zeit Verarbeitung eines Funktionsmember-aufzurufenden besteht aus den folgenden Schritten, wobei M
der Funktionsmember ist und, wenn M
ein Instanzmember ist, E
der Instanzausdruck ist:The run-time processing of a function member invocation consists of the following steps, where M
is the function member and, if M
is an instance member, E
is the instance expression:
Wenn
M
ein statischer Funktionsmember ist:IfM
is a static function member:- Die Argumentliste wird entsprechend der Beschreibung in den Argumentlistenausgewertet.The argument list is evaluated as described in Argument lists.
M
wird aufgerufen.M
is invoked.
Wenn
M
ein Instanzfunktionsmember ist, der in einem value_type deklariert ist:IfM
is an instance function member declared in a value_type:E
wird ausgewertet.E
is evaluated. Wenn diese Auswertung eine Ausnahme verursacht, werden keine weiteren Schritte ausgeführt.If this evaluation causes an exception, then no further steps are executed.- Wenn
E
nicht als Variable klassifiziert ist, wird eine temporäre lokale Variable vomE
Typ erstellt und der Wert von derE
Variablen zugewiesen.IfE
is not classified as a variable, then a temporary local variable ofE
's type is created and the value ofE
is assigned to that variable.E
wird dann als Verweis auf diese temporäre lokale Variable neu klassifiziert.E
is then reclassified as a reference to that temporary local variable. Der Zugriff auf die temporäre Variable ist alsthis
innerhalbM
möglich, aber nicht auf andere Weise.The temporary variable is accessible asthis
withinM
, but not in any other way. Folglich kann der Aufrufer nur dann, wennE
eine echte Variable ist, die Änderungen beobachten, dieM
an vornimmtthis
.Thus, only whenE
is a true variable is it possible for the caller to observe the changes thatM
makes tothis
. - Die Argumentliste wird entsprechend der Beschreibung in den Argumentlistenausgewertet.The argument list is evaluated as described in Argument lists.
M
wird aufgerufen.M
is invoked. Die Variable, auf die verweist,E
wird zur Variablen, auf die verweistthis
.The variable referenced byE
becomes the variable referenced bythis
.
Wenn
M
ein Instanzfunktionsmember ist, der in einem reference_type deklariert ist:IfM
is an instance function member declared in a reference_type:E
wird ausgewertet.E
is evaluated. Wenn diese Auswertung eine Ausnahme verursacht, werden keine weiteren Schritte ausgeführt.If this evaluation causes an exception, then no further steps are executed.- Die Argumentliste wird entsprechend der Beschreibung in den Argumentlistenausgewertet.The argument list is evaluated as described in Argument lists.
- Wenn der Typ von
E
ein value_type ist, wird eine Boxing-Konvertierung (Boxing-Konvertierungen) ausgeführt, umE
Sie in den-Typ zu konvertierenobject
, undE
wirdobject
in den folgenden Schritten als Typ betrachtet.If the type ofE
is a value_type, a boxing conversion (Boxing conversions) is performed to convertE
to typeobject
, andE
is considered to be of typeobject
in the following steps. In diesem FallM
kann nur ein Member von seinSystem.Object
.In this case,M
could only be a member ofSystem.Object
. - Der Wert von
E
wird als gültig geprüft.The value ofE
is checked to be valid. Wenn der Wert vonE
istnull
, wird eine ausgelöst,System.NullReferenceException
und es werden keine weiteren Schritte ausgeführt.If the value ofE
isnull
, aSystem.NullReferenceException
is thrown and no further steps are executed. - Die aufzurufende Funktionsmember-Implementierung wird bestimmt:The function member implementation to invoke is determined:
- Wenn der Bindungstyp von
E
eine Schnittstelle ist, ist das aufzurufende Funktionsmember die Implementierung von, dieM
von dem Lauf Zeittyp der Instanz bereitgestellt wird, auf die von verwiesen wirdE
.If the binding-time type ofE
is an interface, the function member to invoke is the implementation ofM
provided by the run-time type of the instance referenced byE
. Dieses Funktionsmember wird bestimmt, indem die Schnittstellen Zuordnungs Regeln (Schnittstellen Zuordnung) angewendet werden, um die Implementierung von zu bestimmen, dieM
durch den Lauf Zeittyp der Instanz bereitgestellt wird, auf die verweistE
.This function member is determined by applying the interface mapping rules (Interface mapping) to determine the implementation ofM
provided by the run-time type of the instance referenced byE
. - Andernfalls, wenn
M
ein virtuelles Funktionsmember ist, ist das aufzurufende Funktionsmember die Implementierung von, dieM
vom Lauf Zeittyp der Instanz bereitgestellt wird, auf die von verwiesen wirdE
.Otherwise, ifM
is a virtual function member, the function member to invoke is the implementation ofM
provided by the run-time type of the instance referenced byE
. Dieses Funktionsmember wird festgelegt, indem die Regeln zum Bestimmen der am weitesten abgeleiteten Implementierung (virtuelle Methoden) vonM
in Bezug auf den Lauf Zeittyp der Instanz, auf die von verwiesen wird, angewendet werdenE
.This function member is determined by applying the rules for determining the most derived implementation (Virtual methods) ofM
with respect to the run-time type of the instance referenced byE
. - Andernfalls
M
ist ein nicht virtuelles Funktionsmember, und der aufzurufende Funktionsmember istM
selbst.Otherwise,M
is a non-virtual function member, and the function member to invoke isM
itself.
- Wenn der Bindungstyp von
- Die im obigen Schritt festgelegte Funktionsmember-Implementierung wird aufgerufen.The function member implementation determined in the step above is invoked. Das Objekt, auf das verweist,
E
wird das Objekt, auf das verweistthis
.The object referenced byE
becomes the object referenced bythis
.
Aufrufe für geboxte InstanzenInvocations on boxed instances
Ein Funktionsmember, der in einem value_type implementiert ist, kann über eine geachtelte Instanz von aufgerufen werden, die in den folgenden Situationen value_type :A function member implemented in a value_type can be invoked through a boxed instance of that value_type in the following situations:
- Wenn das Funktionsmember eine einer Methode ist, die
override
vom-Typ geerbt wurde,object
und wird durch einen Instanzausdruck vom Typ aufgerufenobject
.When the function member is anoverride
of a method inherited from typeobject
and is invoked through an instance expression of typeobject
. - Wenn das Funktionsmember eine Implementierung eines Schnittstellenfunktionsmembers ist und durch einen Instanzausdruck eines INTERFACE_TYPE aufgerufen wird.When the function member is an implementation of an interface function member and is invoked through an instance expression of an interface_type.
- Wenn der Funktionsmember durch einen Delegaten aufgerufen wird.When the function member is invoked through a delegate.
In diesen Fällen wird die geschachtelte Instanz als eine Variable des value_type enthalten, und diese Variable wird zur Variablen, auf die this
innerhalb des Funktionselement aufzurufenden verwiesen wird.In these situations, the boxed instance is considered to contain a variable of the value_type, and this variable becomes the variable referenced by this
within the function member invocation. Dies bedeutet insbesondere, dass beim Aufrufen eines Funktionsmembers für eine geachtelte Instanz der Funktionsmember den in der geboxten Instanz enthaltenen Wert ändern kann.In particular, this means that when a function member is invoked on a boxed instance, it is possible for the function member to modify the value contained in the boxed instance.
Primäre AusdrückePrimary expressions
Primäre Ausdrücke enthalten die einfachsten Formen von Ausdrücken.Primary expressions include the simplest forms of expressions.
primary_expression
: primary_no_array_creation_expression
| array_creation_expression
;
primary_no_array_creation_expression
: literal
| interpolated_string_expression
| simple_name
| parenthesized_expression
| member_access
| invocation_expression
| element_access
| this_access
| base_access
| post_increment_expression
| post_decrement_expression
| object_creation_expression
| delegate_creation_expression
| anonymous_object_creation_expression
| typeof_expression
| checked_expression
| unchecked_expression
| default_value_expression
| nameof_expression
| anonymous_method_expression
| primary_no_array_creation_expression_unsafe
;
Primäre Ausdrücke werden zwischen array_creation_expression s und primary_no_array_creation_expression s aufgeteilt.Primary expressions are divided between array_creation_expression s and primary_no_array_creation_expression s. Wenn Sie Array-Creation-Expression auf diese Weise behandeln, anstatt sie zusammen mit den anderen einfachen Ausdrucks Formularen aufzulisten, ermöglicht die Grammatik, potenziell verwirrenden Code, wie z. b.Treating array-creation-expression in this way, rather than listing it along with the other simple expression forms, enables the grammar to disallow potentially confusing code such as
object o = new int[3][1];
der andernfalls interpretiert werden würde.which would otherwise be interpreted as
object o = (new int[3])[1];
LiteraleLiterals
Eine primary_expression , die aus einem Literalzeichen (Literale) besteht, wird als Wert klassifiziert.A primary_expression that consists of a literal (Literals) is classified as a value.
Interpolierte ZeichenfolgenInterpolated strings
Ein interpolated_string_expression besteht aus einem $
Vorzeichen, gefolgt von einem regulären oder ausführlichen Zeichenfolgenliteral, bei dem die durch und getrennten Lücken, die {
}
Ausdrücke und Formatierungs Spezifikationen einschließen.An interpolated_string_expression consists of a $
sign followed by a regular or verbatim string literal, wherein holes, delimited by {
and }
, enclose expressions and formatting specifications. Ein interintererter Zeichen folgen Ausdruck ist das Ergebnis einer interpolated_string_literal , die in einzelne Token unterteilt wurde, wie in interpoliert-Zeichenfolgenliteralenbeschrieben.An interpolated string expression is the result of an interpolated_string_literal that has been broken up into individual tokens, as described in Interpolated string literals.
interpolated_string_expression
: '$' interpolated_regular_string
| '$' interpolated_verbatim_string
;
interpolated_regular_string
: interpolated_regular_string_whole
| interpolated_regular_string_start interpolated_regular_string_body interpolated_regular_string_end
;
interpolated_regular_string_body
: interpolation (interpolated_regular_string_mid interpolation)*
;
interpolation
: expression
| expression ',' constant_expression
;
interpolated_verbatim_string
: interpolated_verbatim_string_whole
| interpolated_verbatim_string_start interpolated_verbatim_string_body interpolated_verbatim_string_end
;
interpolated_verbatim_string_body
: interpolation (interpolated_verbatim_string_mid interpolation)+
;
Der constant_expression in einer Interpolations muss über eine implizite Konvertierung in verfügen int
.The constant_expression in an interpolation must have an implicit conversion to int
.
Ein interpolated_string_expression wird als Wert klassifiziert.An interpolated_string_expression is classified as a value. Wenn Sie sofort in System.IFormattable
oder System.FormattableString
mit einer impliziten interkrelierten Zeichen folgen Konvertierung (implizite interpoliert-Zeichen folgen Konvertierungen) konvertiert wird, hat der interpoliert Zeichen folgen Ausdruck diesen Typ.If it is immediately converted to System.IFormattable
or System.FormattableString
with an implicit interpolated string conversion (Implicit interpolated string conversions), the interpolated string expression has that type. Andernfalls weist Sie den-Typ auf string
.Otherwise, it has the type string
.
Wenn der Typ einer interinterpolierten Zeichenfolge System.IFormattable
oder ist System.FormattableString
, ist die Bedeutung ein-Rückruf System.Runtime.CompilerServices.FormattableStringFactory.Create
.If the type of an interpolated string is System.IFormattable
or System.FormattableString
, the meaning is a call to System.Runtime.CompilerServices.FormattableStringFactory.Create
. Wenn der Typ ist string
, ist die Bedeutung des Ausdrucks ein-Rückruf string.Format
.If the type is string
, the meaning of the expression is a call to string.Format
. In beiden Fällen besteht die Argumentliste des Aufrufes aus einem Format Zeichenfolgenliteralzeichen mit Platzhaltern für jede interpolung und einem Argument für jeden Ausdruck, der den Platzhaltern entspricht.In both cases, the argument list of the call consists of a format string literal with placeholders for each interpolation, and an argument for each expression corresponding to the place holders.
Der Format Zeichenfolgenliterale wird wie folgt erstellt, wobei N
die Anzahl der Interpolationen in der interpolated_string_expression ist:The format string literal is constructed as follows, where N
is the number of interpolations in the interpolated_string_expression:
- Wenn ein interpolated_regular_string_whole oder eine interpolated_verbatim_string_whole auf das
$
Vorzeichen folgt, ist das Format Zeichenfolgenliteralzeichen das Token.If an interpolated_regular_string_whole or an interpolated_verbatim_string_whole follows the$
sign, then the format string literal is that token. - Andernfalls besteht das Format Zeichenfolgenliterale aus folgendem:Otherwise, the format string literal consists of:
- Zuerst die interpolated_regular_string_start oder interpolated_verbatim_string_startFirst the interpolated_regular_string_start or interpolated_verbatim_string_start
- Dann für jede Zahl
I
von0
zuN-1
:Then for each numberI
from0
toN-1
:- Die Dezimal Darstellung von.
I
The decimal representation ofI
- Wenn die entsprechende Interpolations constant_expression ist, dann ein
,
(Komma), gefolgt von der Dezimal Darstellung des Werts des constant_expressionThen, if the corresponding interpolation has a constant_expression, a,
(comma) followed by the decimal representation of the value of the constant_expression - Anschließend werden die interpolated_regular_string_mid, die interpolated_regular_string_end, interpolated_verbatim_string_mid oder interpolated_verbatim_string_end unmittelbar auf die entsprechende interpolung folgt.Then the interpolated_regular_string_mid, interpolated_regular_string_end, interpolated_verbatim_string_mid or interpolated_verbatim_string_end immediately following the corresponding interpolation.
- Die Dezimal Darstellung von.
Die nachfolgenden Argumente sind einfach die Ausdrücke aus den Interpolationen (sofern vorhanden), in der richtigen Reihenfolge.The subsequent arguments are simply the expressions from the interpolations (if any), in order.
TODO: Beispiele.TODO: examples.
Einfache NamenSimple names
Eine Simple_name besteht aus einem Bezeichner, optional gefolgt von einer Typargument Liste:A simple_name consists of an identifier, optionally followed by a type argument list:
simple_name
: identifier type_argument_list?
;
Ein Simple_name weist entweder das Formular I
oder das Format auf I<A1,...,Ak>
, wobei I
ein einzelner Bezeichner und <A1,...,Ak>
ein optionaler type_argument_list ist.A simple_name is either of the form I
or of the form I<A1,...,Ak>
, where I
is a single identifier and <A1,...,Ak>
is an optional type_argument_list. Wenn keine type_argument_list angegeben ist, sollten K
Sie den Wert 0 (null) angeben.When no type_argument_list is specified, consider K
to be zero. Die Simple_name wird wie folgt ausgewertet und klassifiziert:The simple_name is evaluated and classified as follows:
Wenn
K
0 (null) ist und die Simple_name in einem- Block angezeigt wird, und wenn der Block(oder ein einschließender Block) der Deklaration der lokalen Variablen Deklaration (Deklarationen) eine lokale Variable, einen Parameter oder eine Konstante mit Namen enthältI
, verweist der Simple_name auf diese lokale Variable, den Parameter oder die Konstante und wird als Variable oder Wert klassifiziert.IfK
is zero and the simple_name appears within a block and if the block's (or an enclosing block's) local variable declaration space (Declarations) contains a local variable, parameter or constant with nameI
, then the simple_name refers to that local variable, parameter or constant and is classified as a variable or value.Wenn
K
0 (null) ist und die Simple_name im Text einer generischen Methoden Deklaration angezeigt wird und diese Deklaration einen Typparameter mit dem Namen enthältI
, verweist der Simple_name auf diesen Typparameter.IfK
is zero and the simple_name appears within the body of a generic method declaration and if that declaration includes a type parameter with nameI
, then the simple_name refers to that type parameter.Andernfalls für jeden Instanztyp
T
(Instanztyp), beginnend mit dem Instanztyp der unmittelbar einschließenden Typdeklaration und fortsetzen mit dem Instanztyp jeder einschließenden Klasse oder Struktur Deklaration (sofern vorhanden):Otherwise, for each instance typeT
(The instance type), starting with the instance type of the immediately enclosing type declaration and continuing with the instance type of each enclosing class or struct declaration (if any):- Wenn
K
0 (null) ist und die Deklaration vonT
einen Typparameter mit dem Namen enthältI
, verweist der Simple_name auf diesen Typparameter.IfK
is zero and the declaration ofT
includes a type parameter with nameI
, then the simple_name refers to that type parameter. - Andernfalls, wenn eine Member-Suche (Member-Suche) von
I
inT
mitK
Typargumenten eine Entsprechung erzeugt:Otherwise, if a member lookup (Member lookup) ofI
inT
withK
type arguments produces a match:- Wenn
T
der Instanztyp der unmittelbar einschließenden Klasse oder des Struktur Typs ist und die Suche eine oder mehrere Methoden identifiziert, ist das Ergebnis eine Methoden Gruppe mit einem zugeordneten Instanzausdruck vonthis
.IfT
is the instance type of the immediately enclosing class or struct type and the lookup identifies one or more methods, the result is a method group with an associated instance expression ofthis
. Wenn eine Typargument Liste angegeben wurde, wird Sie beim Aufrufen einer generischen Methode (Methodenaufrufe) verwendet.If a type argument list was specified, it is used in calling a generic method (Method invocations). - Andernfalls, wenn der
T
Instanztyp der unmittelbar einschließenden Klasse oder des Struktur Typs ist, wenn die Suche einen Instanzmember identifiziert und der Verweis innerhalb des Texts eines Instanzkonstruktors, einer Instanzmethode oder eines Instanzaccessors auftritt, ist das Ergebnis das gleiche wie ein Element Zugriff (Member Access) des Formularsthis.I
.Otherwise, ifT
is the instance type of the immediately enclosing class or struct type, if the lookup identifies an instance member, and if the reference occurs within the body of an instance constructor, an instance method, or an instance accessor, the result is the same as a member access (Member access) of the formthis.I
. Dies kann nur vorkommen, wennK
0 (null) ist.This can only happen whenK
is zero. - Andernfalls ist das Ergebnis das gleiche wie ein Element Zugriff (Member Access) des Formulars
T.I
oderT.I<A1,...,Ak>
.Otherwise, the result is the same as a member access (Member access) of the formT.I
orT.I<A1,...,Ak>
. In diesem Fall handelt es sich um einen Bindungs Zeit Fehler, damit der Simple_name auf einen Instanzmember verweist.In this case, it is a binding-time error for the simple_name to refer to an instance member.
- Wenn
- Wenn
Andernfalls
N
werden die folgenden Schritte für jeden Namespace, beginnend mit dem Namespace, in dem der Simple_name auftritt, mit jedem einschließenden Namespace (sofern vorhanden) und mit dem globalen Namespace fortgesetzt, bis eine Entität gefunden wird:Otherwise, for each namespaceN
, starting with the namespace in which the simple_name occurs, continuing with each enclosing namespace (if any), and ending with the global namespace, the following steps are evaluated until an entity is located:- Wenn
K
0 (null) ist undI
der Name eines Namespace in istN
, dann gilt Folgendes:IfK
is zero andI
is the name of a namespace inN
, then:- Wenn der Speicherort, an dem der Simple_name auftritt, von einer Namespace Deklaration für eingeschlossen ist
N
und die Namespace Deklaration eine extern_alias_directive oder using_alias_directive enthält, die den NamenI
einem Namespace oder Typ zuordnet, ist die Simple_name mehrdeutig, und es tritt ein Kompilierungsfehler auf.If the location where the simple_name occurs is enclosed by a namespace declaration forN
and the namespace declaration contains an extern_alias_directive or using_alias_directive that associates the nameI
with a namespace or type, then the simple_name is ambiguous and a compile-time error occurs. - Andernfalls verweist der Simple_name auf den Namespace mit dem Namen
I
inN
.Otherwise, the simple_name refers to the namespace namedI
inN
.
- Wenn der Speicherort, an dem der Simple_name auftritt, von einer Namespace Deklaration für eingeschlossen ist
- Wenn andernfalls einen zugreif baren
N
Typ mit den Parametern "Name" und "Type" enthältI
K
, dann:Otherwise, ifN
contains an accessible type having nameI
andK
type parameters, then:- Wenn
K
0 (null) ist und die Position, an der die Simple_name auftritt, von einer Namespace Deklaration für eingeschlossen wirdN
und die Namespace Deklaration eine extern_alias_directive oder using_alias_directive enthält, die den NamenI
einem Namespace oder Typ zuordnet, ist die Simple_name mehrdeutig und ein Kompilierzeitfehler aufgetreten.IfK
is zero and the location where the simple_name occurs is enclosed by a namespace declaration forN
and the namespace declaration contains an extern_alias_directive or using_alias_directive that associates the nameI
with a namespace or type, then the simple_name is ambiguous and a compile-time error occurs. - Andernfalls verweist der namespace_or_type_name auf den Typ, der mit den angegebenen Typargumenten erstellt wurde.Otherwise, the namespace_or_type_name refers to the type constructed with the given type arguments.
- Wenn
- Andernfalls ist der Speicherort, an dem der Simple_name auftritt, von einer Namespace Deklaration für Folgendes eingeschlossen
N
:Otherwise, if the location where the simple_name occurs is enclosed by a namespace declaration forN
:- Wenn
K
0 (null) ist und die-Namespace Deklaration eine extern_alias_directive oder using_alias_directive enthält, die den NamenI
einem importierten Namespace oder Typ zuordnet, verweist der Simple_name auf diesen Namespace oder Typ.IfK
is zero and the namespace declaration contains an extern_alias_directive or using_alias_directive that associates the nameI
with an imported namespace or type, then the simple_name refers to that namespace or type. - Wenn die Namespaces und Typdeklarationen, die von den using_namespace_directive s und using_static_directive s der Namespace Deklaration importiert werden, genau einen zugreif baren Typ oder einen statischen Member ohne Erweiterung haben, der über die Parameter "Name" und "Type" verfügt
I
K
, verweist der Simple_name auf diesen Typ oder Member, der mit den angegebenen TypargumentenOtherwise, if the namespaces and type declarations imported by the using_namespace_directive s and using_static_directive s of the namespace declaration contain exactly one accessible type or non-extension static member having nameI
andK
type parameters, then the simple_name refers to that type or member constructed with the given type arguments. - Wenn die Namespaces und Typen, die durch die using_namespace_directive s der Namespace Deklaration importiert werden, mehr als einen zugreif baren Typ oder einen statischen Member ohne Erweiterungsmethode haben, der über die Parameter "Name" und "Type" verfügt
I
K
, ist die Simple_name mehrdeutig und ein Fehler.Otherwise, if the namespaces and types imported by the using_namespace_directive s of the namespace declaration contain more than one accessible type or non-extension-method static member having nameI
andK
type parameters, then the simple_name is ambiguous and an error occurs.
- Wenn
Beachten Sie, dass der gesamte Schritt genau mit dem entsprechenden Schritt bei der Verarbeitung eines namespace_or_type_name (Namespace-und Typnamen) identisch ist.Note that this entire step is exactly parallel to the corresponding step in the processing of a namespace_or_type_name (Namespace and type names).
- Wenn
Andernfalls ist der Simple_name nicht definiert, und es tritt ein Kompilierzeitfehler auf.Otherwise, the simple_name is undefined and a compile-time error occurs.
Ausdrücke in KlammernParenthesized expressions
Ein parenthesized_expression besteht aus einem Ausdruck , der in Klammern eingeschlossen ist.A parenthesized_expression consists of an expression enclosed in parentheses.
parenthesized_expression
: '(' expression ')'
;
Eine parenthesized_expression wird ausgewertet, indem der Ausdruck innerhalb der Klammern ausgewertet wird.A parenthesized_expression is evaluated by evaluating the expression within the parentheses. Wenn der Ausdruck innerhalb der Klammern einen Namespace oder Typ angibt, tritt ein Kompilierzeitfehler auf.If the expression within the parentheses denotes a namespace or type, a compile-time error occurs. Andernfalls ist das Ergebnis der parenthesized_expression das Ergebnis der Auswertung des enthaltenen Ausdrucks.Otherwise, the result of the parenthesized_expression is the result of the evaluation of the contained expression.
MemberzugriffMember access
Eine member_access besteht aus einem primary_expression, einem predefined_type oder einem qualified_alias_member, gefolgt von einem " .
"-Token, gefolgt von einem Bezeichner, optional gefolgt von einem type_argument_list.A member_access consists of a primary_expression, a predefined_type, or a qualified_alias_member, followed by a ".
" token, followed by an identifier, optionally followed by a type_argument_list.
member_access
: primary_expression '.' identifier type_argument_list?
| predefined_type '.' identifier type_argument_list?
| qualified_alias_member '.' identifier
;
predefined_type
: 'bool' | 'byte' | 'char' | 'decimal' | 'double' | 'float' | 'int' | 'long'
| 'object' | 'sbyte' | 'short' | 'string' | 'uint' | 'ulong' | 'ushort'
;
Die qualified_alias_member Produktion wird in Namespacealias-Qualifiziererndefiniert.The qualified_alias_member production is defined in Namespace alias qualifiers.
Ein member_access weist entweder das Formular E.I
oder das Format auf E.I<A1, ..., Ak>
, wobei E
ein primärer Ausdruck ist, I
ein einzelner Bezeichner ist und <A1, ..., Ak>
ein optionaler type_argument_list ist.A member_access is either of the form E.I
or of the form E.I<A1, ..., Ak>
, where E
is a primary-expression, I
is a single identifier and <A1, ..., Ak>
is an optional type_argument_list. Wenn keine type_argument_list angegeben ist, sollten K
Sie den Wert 0 (null) angeben.When no type_argument_list is specified, consider K
to be zero.
Eine member_access mit einer primary_expression vom Typ dynamic
ist dynamisch gebunden (dynamische Bindung).A member_access with a primary_expression of type dynamic
is dynamically bound (Dynamic binding). In diesem Fall klassifiziert der Compiler den Member Access als Eigenschaften Zugriff vom Typ dynamic
.In this case the compiler classifies the member access as a property access of type dynamic
. Die nachstehenden Regeln zum Bestimmen der Bedeutung der member_access werden dann zur Laufzeit angewendet und verwenden den Lauf Zeittyp anstelle des Kompilierzeit Typs der primary_expression.The rules below to determine the meaning of the member_access are then applied at run-time, using the run-time type instead of the compile-time type of the primary_expression. Wenn diese Lauf Zeit Klassifizierung zu einer Methoden Gruppe führt, muss der Element Zugriff die primary_expression eines invocation_expression sein.If this run-time classification leads to a method group, then the member access must be the primary_expression of an invocation_expression.
Die member_access wird wie folgt ausgewertet und klassifiziert:The member_access is evaluated and classified as follows:
- Wenn
K
0 (null) ist undE
ein Namespace ist undE
einen schsted Namespace mit dem Namen enthältI
, ist das Ergebnis dieser Namespace.IfK
is zero andE
is a namespace andE
contains a nested namespace with nameI
, then the result is that namespace. - Wenn
E
ein Namespace ist undE
einen zugänglichen TypI
mit den Parametern "Name" und "Type" enthältK
, ist das Ergebnis der Typ, der mit den angegebenen Typargumenten erstellt wurde.Otherwise, ifE
is a namespace andE
contains an accessible type having nameI
andK
type parameters, then the result is that type constructed with the given type arguments. - Wenn
E
ein predefined_type oder ein primary_expression als Typ klassifiziert ist, wennE
kein Typparameter ist, und wenn eine Member-Suche (Member-Suche) vonI
inE
mitK
Typparametern eine Entsprechung erzeugt,E.I
wird wie folgt ausgewertet und klassifiziert:IfE
is a predefined_type or a primary_expression classified as a type, ifE
is not a type parameter, and if a member lookup (Member lookup) ofI
inE
withK
type parameters produces a match, thenE.I
is evaluated and classified as follows:- Wenn
I
einen Typ identifiziert, ist das Ergebnis der Typ, der mit den angegebenen Typargumenten erstellt wurde.IfI
identifies a type, then the result is that type constructed with the given type arguments. - Wenn
I
eine oder mehrere Methoden identifiziert, ist das Ergebnis eine Methoden Gruppe ohne zugeordneten Instanzausdruck.IfI
identifies one or more methods, then the result is a method group with no associated instance expression. Wenn eine Typargument Liste angegeben wurde, wird Sie beim Aufrufen einer generischen Methode (Methodenaufrufe) verwendet.If a type argument list was specified, it is used in calling a generic method (Method invocations). - Wenn
I
einestatic
Eigenschaft identifiziert, ist das Ergebnis ein Eigenschaften Zugriff ohne zugeordneten Instanzausdruck.IfI
identifies astatic
property, then the result is a property access with no associated instance expression. - Wenn
I
einstatic
Feld angibt:IfI
identifies astatic
field:- Wenn das Feld den
readonly
Wert hat und der Verweis außerhalb des statischen Konstruktors der Klasse oder Struktur auftritt, in der das Feld deklariert ist, dann ist das Ergebnis ein Wert, nämlich der Wert des statischen FeldsI
inE
.If the field isreadonly
and the reference occurs outside the static constructor of the class or struct in which the field is declared, then the result is a value, namely the value of the static fieldI
inE
. - Andernfalls ist das Ergebnis eine Variable, nämlich das statische Feld
I
inE
.Otherwise, the result is a variable, namely the static fieldI
inE
.
- Wenn das Feld den
- Wenn
I
ein-static
Ereignis identifiziert:IfI
identifies astatic
event:- Wenn der Verweis innerhalb der Klasse oder Struktur auftritt, in der das Ereignis deklariert ist, und das Ereignis ohne event_accessor_declarations (Ereignisse) deklariert wurde,
E.I
wird genau so verarbeitet, als wäre esI
ein statisches Feld.If the reference occurs within the class or struct in which the event is declared, and the event was declared without event_accessor_declarations (Events), thenE.I
is processed exactly as ifI
were a static field. - Andernfalls ist das Ergebnis ein Ereignis Zugriff ohne zugeordneten Instanzausdruck.Otherwise, the result is an event access with no associated instance expression.
- Wenn der Verweis innerhalb der Klasse oder Struktur auftritt, in der das Ereignis deklariert ist, und das Ereignis ohne event_accessor_declarations (Ereignisse) deklariert wurde,
- Wenn
I
eine Konstante identifiziert, ist das Ergebnis ein Wert, nämlich der Wert dieser Konstante.IfI
identifies a constant, then the result is a value, namely the value of that constant. - Wenn
I
einen Enumerationsmember identifiziert, ist das Ergebnis ein Wert, nämlich der Wert dieses Enumerationsmembers.IfI
identifies an enumeration member, then the result is a value, namely the value of that enumeration member. - Andernfalls
E.I
ist ein ungültiger Member-Verweis, und ein Kompilierzeitfehler tritt auf.Otherwise,E.I
is an invalid member reference, and a compile-time error occurs.
- Wenn
- Wenn
E
ein Eigenschaften Zugriff, Indexer-Zugriff, Variable oder Wert ist, der Typ istT
, und eine Member-Suche (Member-Suche) vonI
inT
mitK
Typargumenten eine Entsprechung erzeugt,E.I
wird wie folgt ausgewertet und klassifiziert:IfE
is a property access, indexer access, variable, or value, the type of which isT
, and a member lookup (Member lookup) ofI
inT
withK
type arguments produces a match, thenE.I
is evaluated and classified as follows:- Zuerst wird
E
der Wert der Eigenschaft oder des Indexerzugriffs abgerufen (Werte von Ausdrücken) undE
als Wert neu klassifiziert, wenn ein Eigenschafts-oder Indexer-Zugriff ist.First, ifE
is a property or indexer access, then the value of the property or indexer access is obtained (Values of expressions) andE
is reclassified as a value. - Wenn
I
eine oder mehrere Methoden identifiziert, ist das Ergebnis eine Methoden Gruppe mit einem zugeordneten Instanzausdruck vonE
.IfI
identifies one or more methods, then the result is a method group with an associated instance expression ofE
. Wenn eine Typargument Liste angegeben wurde, wird Sie beim Aufrufen einer generischen Methode (Methodenaufrufe) verwendet.If a type argument list was specified, it is used in calling a generic method (Method invocations). - Wenn
I
eine Instanzeigenschaft identifiziert,IfI
identifies an instance property,- Wenn
E
istthis
,I
eine automatisch implementierte Eigenschaft (automatisch implementierte Eigenschaften) ohne Setter identifiziert, und der Verweis innerhalb eines Instanzkonstruktors für einen Klassen-oder Strukturtyp istT
, dann ist das Ergebnis eine Variable, d. h. das verborgene dahinter liegende Feld für die Auto-Eigenschaft, dieI
in der Instanz von angegeben ist, dieT
von angegeben wirdthis
.IfE
isthis
,I
identifies an automatically implemented property (Automatically implemented properties) without a setter, and the reference occurs within an instance constructor for a class or struct typeT
, then the result is a variable, namely the hidden backing field for the auto-property given byI
in the instance ofT
given bythis
. - Andernfalls ist das Ergebnis ein Eigenschaften Zugriff mit einem zugeordneten Instanzausdruck von
E
.Otherwise, the result is a property access with an associated instance expression ofE
.
- Wenn
- Wenn
T
ein class_type ist undI
ein Instanzfeld dieses class_type angibt:IfT
is a class_type andI
identifies an instance field of that class_type:- Wenn der Wert von
E
istnull
, wird eine ausgelöstSystem.NullReferenceException
.If the value ofE
isnull
, then aSystem.NullReferenceException
is thrown. - Andernfalls
readonly
ist das Ergebnis ein Wert, d. h. der Wert des Felds in dem Objekt, auf das verwiesen wird, wenn das Feld den Wert hat und der Verweis außerhalb eines Instanzkonstruktors der Klasse auftritt, in der das Feld deklariert istI
E
.Otherwise, if the field isreadonly
and the reference occurs outside an instance constructor of the class in which the field is declared, then the result is a value, namely the value of the fieldI
in the object referenced byE
. - Andernfalls ist das Ergebnis eine Variable, nämlich das Feld
I
in dem Objekt, auf das von verwiesen wirdE
.Otherwise, the result is a variable, namely the fieldI
in the object referenced byE
.
- Wenn der Wert von
- Wenn
T
ein struct_type ist undI
ein Instanzfeld dieses struct_type angibt:IfT
is a struct_type andI
identifies an instance field of that struct_type:- Wenn
E
ein Wert ist oder wenn das Feld istreadonly
und der Verweis außerhalb eines Instanzkonstruktors der Struktur auftritt, in der das Feld deklariert ist, dann ist das Ergebnis ein Wert, d. h. der Wert des FeldsI
in der Struktur Instanz, die von angegeben wirdE
.IfE
is a value, or if the field isreadonly
and the reference occurs outside an instance constructor of the struct in which the field is declared, then the result is a value, namely the value of the fieldI
in the struct instance given byE
. - Andernfalls ist das Ergebnis eine Variable, nämlich das Feld
I
in der Struktur Instanz, das von angegeben wirdE
.Otherwise, the result is a variable, namely the fieldI
in the struct instance given byE
.
- Wenn
- Wenn
I
ein Instanzereignis angibt:IfI
identifies an instance event:- Wenn der Verweis innerhalb der Klasse oder Struktur auftritt, in der das Ereignis deklariert ist, und das Ereignis ohne event_accessor_declarations (Ereignisse) deklariert wurde, und der Verweis nicht als linke Seite eines or-
+=
Operators auftritt-=
,E.I
wird genau so verarbeitet, als wäreI
ein Instanzfeld.If the reference occurs within the class or struct in which the event is declared, and the event was declared without event_accessor_declarations (Events), and the reference does not occur as the left-hand side of a+=
or-=
operator, thenE.I
is processed exactly as ifI
was an instance field. - Andernfalls ist das Ergebnis ein Ereignis Zugriff mit einem zugeordneten Instanzausdruck von
E
.Otherwise, the result is an event access with an associated instance expression ofE
.
- Wenn der Verweis innerhalb der Klasse oder Struktur auftritt, in der das Ereignis deklariert ist, und das Ereignis ohne event_accessor_declarations (Ereignisse) deklariert wurde, und der Verweis nicht als linke Seite eines or-
- Zuerst wird
- Andernfalls wird versucht,
E.I
als Erweiterungs Methodenaufruf (Erweiterungs Methodenaufrufe) zu verarbeiten.Otherwise, an attempt is made to processE.I
as an extension method invocation (Extension method invocations). Wenn dies nicht möglichE.I
ist, ist ein ungültiger Element Verweis, und ein Bindungs Fehler tritt auf.If this fails,E.I
is an invalid member reference, and a binding-time error occurs.
Identische einfache Namen und TypnamenIdentical simple names and type names
Wenn ein Element Zugriff auf das Formular E.I
ist, wenn E
ein einzelner Bezeichner ist und die Bedeutung von E
als Simple_name (einfache Namen) eine Konstante, ein Feld, eine Eigenschaft, eine lokale Variable oder ein Parameter mit demselben Typ wie die Bedeutung von E
als TYPE_NAME (Namespace-und Typnamen) ist, sind beide möglichen Bedeutungen von E
zulässig.In a member access of the form E.I
, if E
is a single identifier, and if the meaning of E
as a simple_name (Simple names) is a constant, field, property, local variable, or parameter with the same type as the meaning of E
as a type_name (Namespace and type names), then both possible meanings of E
are permitted. Die beiden möglichen Bedeutungen von E.I
sind nie mehrdeutig, da I
E
in beiden Fällen notwendigerweise ein Member des-Typs sein muss.The two possible meanings of E.I
are never ambiguous, since I
must necessarily be a member of the type E
in both cases. Anders ausgedrückt: die Regel gestattet einfach den Zugriff auf die statischen Member und die schsted Typen, E
bei denen andernfalls ein Kompilierzeitfehler aufgetreten ist.In other words, the rule simply permits access to the static members and nested types of E
where a compile-time error would otherwise have occurred. Beispiel:For example:
struct Color
{
public static readonly Color White = new Color(...);
public static readonly Color Black = new Color(...);
public Color Complement() {...}
}
class A
{
public Color Color; // Field Color of type Color
void F() {
Color = Color.Black; // References Color.Black static member
Color = Color.Complement(); // Invokes Complement() on Color field
}
static void G() {
Color c = Color.White; // References Color.White static member
}
}
Grammatik MehrdeutigkeitenGrammar ambiguities
Die Produktion für Simple_name (einfache Namen) und member_access (Member Access) kann zu Mehrdeutigkeiten in der Grammatik für Ausdrücke führen.The productions for simple_name (Simple names) and member_access (Member access) can give rise to ambiguities in the grammar for expressions. Beispielsweise ist die-Anweisung:For example, the statement:
F(G<A,B>(7));
kann als ein F
-Befehl mit zwei Argumenten (und) interpretiert werden G < A
B > (7)
.could be interpreted as a call to F
with two arguments, G < A
and B > (7)
. Alternativ könnte Sie auch als ein-Rückruf F
mit einem Argument interpretiert werden, bei dem es sich um einen aufgerufenen Vorgang einer generischen Methode G
mit zwei Typargumenten und einem regulären Argument handelt.Alternatively, it could be interpreted as a call to F
with one argument, which is a call to a generic method G
with two type arguments and one regular argument.
Wenn eine Sequenz von Token (im Kontext) als Simple_name (einfache Namen), member_access (Member Access) oder pointer_member_access (Zeiger Element Zugriff) mit einer type_argument_list (Typargumente) analysiert werden kann, wird das Token, das unmittelbar auf das schließende Token folgt, >
untersucht.If a sequence of tokens can be parsed (in context) as a simple_name (Simple names), member_access (Member access), or pointer_member_access (Pointer member access) ending with a type_argument_list (Type arguments), the token immediately following the closing >
token is examined. Wenn eine vonIf it is one of
( ) ] } : ; , . ? == != | ^
Anschließend wird der type_argument_list als Teil der Simple_name, member_access oder pointer_member_access aufbewahrt, und jede andere mögliche Analyse der Sequenz von Token wird verworfen.then the type_argument_list is retained as part of the simple_name, member_access or pointer_member_access and any other possible parse of the sequence of tokens is discarded. Andernfalls wird der type_argument_list nicht als Teil der Simple_name, member_access oder pointer_member_access betrachtet, auch wenn es keine andere Möglichkeit gibt, die Sequenz von Token zu analysieren.Otherwise, the type_argument_list is not considered to be part of the simple_name, member_access or pointer_member_access, even if there is no other possible parse of the sequence of tokens. Beachten Sie, dass diese Regeln beim Durchlaufen einer type_argument_list in einer namespace_or_type_name (Namespace-und Typnamen) nicht angewendet werden.Note that these rules are not applied when parsing a type_argument_list in a namespace_or_type_name (Namespace and type names). Die AnweisungThe statement
F(G<A,B>(7));
wird gemäß dieser Regel als ein-Rückruf F
mit einem Argument interpretiert, bei dem es sich um einen Aufrufe einer generischen Methode G
mit zwei Typargumenten und einem regulären Argument handelt.will, according to this rule, be interpreted as a call to F
with one argument, which is a call to a generic method G
with two type arguments and one regular argument. Die AnweisungenThe statements
F(G < A, B > 7);
F(G < A, B >> 7);
wird jeweils als ein-Rückruf F
mit zwei Argumenten interpretiert.will each be interpreted as a call to F
with two arguments. Die AnweisungThe statement
x = F < A > +y;
wird als ein kleiner-als-Operator, größer als-Operator und Unärer Plus-Operator interpretiert, als ob die-Anweisung geschrieben worden wäre x = (F < A) > (+y)
, anstatt als Simple_name mit einem type_argument_list gefolgt von einem binären Plus-Operator.will be interpreted as a less than operator, greater than operator, and unary plus operator, as if the statement had been written x = (F < A) > (+y)
, instead of as a simple_name with a type_argument_list followed by a binary plus operator. In der-AnweisungIn the statement
x = y is C<T> + z;
die Token C<T>
werden als namespace_or_type_name mit einem type_argument_list interpretiert.the tokens C<T>
are interpreted as a namespace_or_type_name with a type_argument_list.
AufrufausdrückeInvocation expressions
Ein invocation_expression wird verwendet, um eine Methode aufzurufen.An invocation_expression is used to invoke a method.
invocation_expression
: primary_expression '(' argument_list? ')'
;
Ein- invocation_expression ist dynamisch gebunden (dynamische Bindung), wenn mindestens einer der folgenden Punkte enthält:An invocation_expression is dynamically bound (Dynamic binding) if at least one of the following holds:
- Der primary_expression weist den Kompilier Zeittyp auf
dynamic
.The primary_expression has compile-time typedynamic
. - Mindestens ein Argument der optionalen argument_list hat einen Kompilier Zeittyp,
dynamic
und die primary_expression weist keinen Delegattyp auf.At least one argument of the optional argument_list has compile-time typedynamic
and the primary_expression does not have a delegate type.
In diesem Fall klassifiziert der Compiler die invocation_expression als Wert des Typs dynamic
.In this case the compiler classifies the invocation_expression as a value of type dynamic
. Die nachstehenden Regeln zum Bestimmen der Bedeutung der invocation_expression werden dann zur Laufzeit angewendet. dabei wird der Lauf Zeittyp anstelle des Kompilier Zeittyps der primary_expression und Argumente verwendet, die den Kompilier Zeittyp aufweisen dynamic
.The rules below to determine the meaning of the invocation_expression are then applied at run-time, using the run-time type instead of the compile-time type of those of the primary_expression and arguments which have the compile-time type dynamic
. Wenn das primary_expression keinen Kompilier Zeittyp hat dynamic
, wird der Methodenaufruf einer begrenzten Kompilierungszeit Überprüfung unterzogen, wie in der Kompilierzeit Überprüfung der dynamischen Überladungs Auflösungbeschrieben.If the primary_expression does not have compile-time type dynamic
, then the method invocation undergoes a limited compile time check as described in Compile-time checking of dynamic overload resolution.
Der primary_expression eines invocation_expression muss eine Methoden Gruppe oder ein Wert eines delegate_type sein.The primary_expression of an invocation_expression must be a method group or a value of a delegate_type. Wenn die primary_expression eine Methoden Gruppe ist, ist die invocation_expression ein Methodenaufruf (Methodenaufrufe).If the primary_expression is a method group, the invocation_expression is a method invocation (Method invocations). Wenn die primary_expression ein Wert eines delegate_type ist, ist der invocation_expression ein Delegataufruf (Delegataufrufe).If the primary_expression is a value of a delegate_type, the invocation_expression is a delegate invocation (Delegate invocations). Wenn die primary_expression weder eine Methoden Gruppe noch der Wert eines delegate_type ist, tritt ein Bindungs Fehler auf.If the primary_expression is neither a method group nor a value of a delegate_type, a binding-time error occurs.
Die optionalen argument_list (Argumentlisten) stellen Werte oder Variablen Verweise für die Parameter der Methode bereit.The optional argument_list (Argument lists) provides values or variable references for the parameters of the method.
Das Ergebnis der Auswertung eines invocation_expression wird wie folgt klassifiziert:The result of evaluating an invocation_expression is classified as follows:
- Wenn die invocation_expression eine Methode oder einen Delegaten aufruft, die zurückgibt
void
, ist das Ergebnis "Nothing".If the invocation_expression invokes a method or delegate that returnsvoid
, the result is nothing. Ein Ausdruck, der als "Nothing" klassifiziert wird, ist nur im Kontext einer statement_expression (Ausdrucks Anweisungen) oder als Text eines lambda_expression (Anonyme Funktions Ausdrücke) zulässig.An expression that is classified as nothing is permitted only in the context of a statement_expression (Expression statements) or as the body of a lambda_expression (Anonymous function expressions). Andernfalls tritt ein Bindungs Zeitfehler auf.Otherwise a binding-time error occurs. - Andernfalls ist das Ergebnis ein Wert des Typs, der von der-Methode oder dem-Delegaten zurückgegeben wird.Otherwise, the result is a value of the type returned by the method or delegate.
MethodenaufrufeMethod invocations
Bei einem Methodenaufruf muss die primary_expression der invocation_expression eine Methoden Gruppe sein.For a method invocation, the primary_expression of the invocation_expression must be a method group. Die Methoden Gruppe identifiziert die eine Methode, die aufgerufen werden soll, oder den Satz überladener Methoden, von denen eine bestimmte aufzurufende Methode ausgewählt werden soll.The method group identifies the one method to invoke or the set of overloaded methods from which to choose a specific method to invoke. Im letzteren Fall basiert die Bestimmung der aufzurufenden Methode auf dem Kontext, der von den Typen der Argumente im argument_list bereitgestellt wird.In the latter case, determination of the specific method to invoke is based on the context provided by the types of the arguments in the argument_list.
Die Bindungs Zeit Verarbeitung eines Methoden M(A)
aufruens im Formular, wobei M
eine Methoden Gruppe (möglicherweise ein type_argument_list) und A
ein optionaler argument_list ist, besteht aus den folgenden Schritten:The binding-time processing of a method invocation of the form M(A)
, where M
is a method group (possibly including a type_argument_list), and A
is an optional argument_list, consists of the following steps:
- Der Satz von Kandidaten Methoden für den Methodenaufruf wird erstellt.The set of candidate methods for the method invocation is constructed. Für jede Methode,
F
die der Methoden Gruppe zugeordnet istM
:For each methodF
associated with the method groupM
:- Wenn
F
nicht generisch ist,F
ist ein Kandidat, wenn:IfF
is non-generic,F
is a candidate when:M
hat keine Typargument Liste, undM
has no type argument list, andF
ist in Bezug aufA
(anwendbares Funktionsmember) anwendbar.F
is applicable with respect toA
(Applicable function member).
- Wenn
F
generisch ist undM
keine Typargument Liste aufweist,F
ist ein Kandidat für Folgendes:IfF
is generic andM
has no type argument list,F
is a candidate when:- Der Typrückschluss (Typrückschluss) ist erfolgreich, wobei eine Liste der Typargumente für den-Befehl abgeleitet wird.Type inference (Type inference) succeeds, inferring a list of type arguments for the call, and
- Nachdem die abzurufenden Typargumente die entsprechenden Methodentypparameter ersetzt haben, erfüllen alle konstruierten Typen in der Parameterliste von F ihre Einschränkungen (die dieEinschränkungenerfüllen), und die Parameterliste von
F
ist in Bezug aufA
(anwendbares Funktionsmember) anwendbar.Once the inferred type arguments are substituted for the corresponding method type parameters, all constructed types in the parameter list of F satisfy their constraints (Satisfying constraints), and the parameter list ofF
is applicable with respect toA
(Applicable function member).
- Wenn
F
generisch ist undM
eine Typargument Liste enthält,F
ist ein Kandidat, wenn Folgendes gilt:IfF
is generic andM
includes a type argument list,F
is a candidate when:F
verfügt über die gleiche Anzahl von Methodentypparametern, die in der Typargument Liste angegeben wurden, undF
has the same number of method type parameters as were supplied in the type argument list, and- Nachdem die Typargumente die entsprechenden Methodentypparameter ersetzt haben, erfüllen alle konstruierten Typen in der Parameterliste von F ihre Einschränkungen (die dieEinschränkungenerfüllen), und die Parameterliste von
F
ist in Bezug aufA
(anwendbares Funktionsmember) anwendbar.Once the type arguments are substituted for the corresponding method type parameters, all constructed types in the parameter list of F satisfy their constraints (Satisfying constraints), and the parameter list ofF
is applicable with respect toA
(Applicable function member).
- Wenn
- Der Satz von Kandidaten Methoden wird so reduziert, dass er nur Methoden der am weitesten abgeleiteten Typen enthält: für jede Methode
C.F
in der Menge, wobeiC
der Typ ist, in dem die MethodeF
deklariert ist, werden alle Methoden, die in einem Basistyp von deklariertC
sind, aus dem Satz entfernt.The set of candidate methods is reduced to contain only methods from the most derived types: For each methodC.F
in the set, whereC
is the type in which the methodF
is declared, all methods declared in a base type ofC
are removed from the set. Wenn außerdemC
ein anderer Klassentyp als istobject
, werden alle in einem Schnittstellentyp deklarierten Methoden aus dem Satz entfernt.Furthermore, ifC
is a class type other thanobject
, all methods declared in an interface type are removed from the set. (Diese letztere Regel hat nur Auswirkungen, wenn die Methoden Gruppe das Ergebnis einer Member-Suche nach einem Typparameter ist, der eine effektive Basisklasse als Object und eine nicht leere effektive Schnittstellen Menge aufweist.)(This latter rule only has affect when the method group was the result of a member lookup on a type parameter having an effective base class other than object and a non-empty effective interface set.) - Wenn der resultierende Satz von Kandidaten Methoden leer ist, wird die weitere Verarbeitung der folgenden Schritte abgebrochen, und stattdessen wird versucht, den Aufruf als Erweiterungs Methodenaufruf (Erweiterungs Methodenaufrufe) zu verarbeiten.If the resulting set of candidate methods is empty, then further processing along the following steps are abandoned, and instead an attempt is made to process the invocation as an extension method invocation (Extension method invocations). Wenn dies fehlschlägt, gibt es keine anwendbaren Methoden, und ein Bindungs Fehler tritt auf.If this fails, then no applicable methods exist, and a binding-time error occurs.
- Die beste Methode des Satzes von Kandidaten Methoden wird mithilfe der Regeln zur Überladungs Auflösung der Überladungs Auflösungidentifiziert.The best method of the set of candidate methods is identified using the overload resolution rules of Overload resolution. Wenn eine einzige optimale Methode nicht identifiziert werden kann, ist der Methodenaufruf mehrdeutig, und es tritt ein Fehler bei der Bindung auf.If a single best method cannot be identified, the method invocation is ambiguous, and a binding-time error occurs. Beim Durchführen der Überladungs Auflösung werden die Parameter einer generischen Methode berücksichtigt, nachdem die Typargumente (bereitgestellt oder abgeleitet) für die entsprechenden Methodentyp Parameter ersetzt wurden.When performing overload resolution, the parameters of a generic method are considered after substituting the type arguments (supplied or inferred) for the corresponding method type parameters.
- Die endgültige Überprüfung der ausgewählten optimalen Methode wird ausgeführt:Final validation of the chosen best method is performed:
- Die-Methode wird im Kontext der-Methoden Gruppe überprüft: Wenn es sich bei der besten Methode um eine statische Methode handelt, muss die Methoden Gruppe aus einer Simple_name oder einer member_access durch einen Typ resultieren.The method is validated in the context of the method group: If the best method is a static method, the method group must have resulted from a simple_name or a member_access through a type. Wenn die beste Methode eine Instanzmethode ist, muss die Methoden Gruppe durch eine Simple_name, eine member_access durch eine Variable oder einen Wert oder eine base_access resultieren.If the best method is an instance method, the method group must have resulted from a simple_name, a member_access through a variable or value, or a base_access. Wenn keine dieser Anforderungen erfüllt ist, tritt ein Fehler bei der Bindung auf.If neither of these requirements is true, a binding-time error occurs.
- Wenn es sich bei der besten Methode um eine generische Methode handelt, werden die Typargumente (bereitgestellt oder abgeleitet) mit den Einschränkungen (die sich durch dieErfüllung der Einschränkungenin der generischen Methode) überprüfenIf the best method is a generic method, the type arguments (supplied or inferred) are checked against the constraints (Satisfying constraints) declared on the generic method. Wenn ein Typargument die entsprechenden Einschränkungen für den Typparameter nicht erfüllt, tritt ein Bindungs Zeitfehler auf.If any type argument does not satisfy the corresponding constraint(s) on the type parameter, a binding-time error occurs.
Nachdem eine Methode mithilfe der obigen Schritte zur Bindungs Zeit ausgewählt und überprüft wurde, wird der tatsächliche Lauf Zeit Aufruf gemäß den Regeln für den Funktionselement Aufruf verarbeitet, der unter Kompilierzeit Überprüfung der dynamischen Überladungs Auflösungbeschrieben wird.Once a method has been selected and validated at binding-time by the above steps, the actual run-time invocation is processed according to the rules of function member invocation described in Compile-time checking of dynamic overload resolution.
Die intuitiver Auswirkung der oben beschriebenen Auflösungs Regeln lautet wie folgt: um die von einem Methodenaufruf aufgerufene Methode zu suchen, beginnen Sie mit dem Typ, der durch den Methodenaufruf angegeben wird, und setzen Sie die Vererbungs Kette fort, bis mindestens eine anwendbare, barrierefreie, nicht über schreibende Methoden Deklaration gefunden wurde.The intuitive effect of the resolution rules described above is as follows: To locate the particular method invoked by a method invocation, start with the type indicated by the method invocation and proceed up the inheritance chain until at least one applicable, accessible, non-override method declaration is found. Führen Sie dann den Typrückschluss und die Überladungs Auflösung für den Satz der anwendbaren, zugänglichen, nicht überschreibenden Methoden aus, die in diesem Typ deklariert sind, und rufen Sie die Methode aufThen perform type inference and overload resolution on the set of applicable, accessible, non-override methods declared in that type and invoke the method thus selected. Wenn keine Methode gefunden wurde, versuchen Sie stattdessen, den Aufruf als Erweiterungs Methodenaufruf zu verarbeiten.If no method was found, try instead to process the invocation as an extension method invocation.
Erweiterungs MethodenaufrufeExtension method invocations
In einem Methodenaufruf (Aufrufe für geboxte Instanzen) eines der FormulareIn a method invocation (Invocations on boxed instances) of one of the forms
expr . identifier ( )
expr . identifier ( args )
expr . identifier < typeargs > ( )
expr . identifier < typeargs > ( args )
Wenn bei der normalen Verarbeitung des aufzurufenden-aufzurufenden keine anwendbaren Methoden gefunden werden, wird versucht, das Konstrukt als Erweiterungs Methodenaufruf zu verarbeiten.if the normal processing of the invocation finds no applicable methods, an attempt is made to process the construct as an extension method invocation. Wenn expr oder eines der args den Kompilier Zeittyp aufweist dynamic
, werden keine Erweiterungs Methoden angewendet.If expr or any of the args has compile-time type dynamic
, extension methods will not apply.
Ziel ist es, die beste TYPE_NAME zu finden C
, damit der entsprechende Aufruf der statischen Methode stattfinden kann:The objective is to find the best type_name C
, so that the corresponding static method invocation can take place:
C . identifier ( expr )
C . identifier ( expr , args )
C . identifier < typeargs > ( expr )
C . identifier < typeargs > ( expr , args )
Eine Erweiterungsmethode Ci.Mj
ist berechtigt , wenn Folgendes gilt:An extension method Ci.Mj
is eligible if:
Ci
ist eine nicht generische, nicht-Klassen-Klasse.Ci
is a non-generic, non-nested class- Der Name von
Mj
ist ein Bezeichner .The name ofMj
is identifier Mj
ist verfügbar und anwendbar, wenn Sie auf die Argumente als statische Methode angewendet wird, wie oben gezeigt.Mj
is accessible and applicable when applied to the arguments as a static method as shown above- Eine implizite Identitäts-, Verweis-oder Boxingkonvertierung ist von expr zum Typ des ersten Parameters von vorhanden
Mj
.An implicit identity, reference or boxing conversion exists from expr to the type of the first parameter ofMj
.
Die Suche nach C
verläuft wie folgt:The search for C
proceeds as follows:
- Beginnend mit der nächstgelegenen, einschließenden Namespace Deklaration, der Fortsetzung der einschließenden Namespace Deklaration und dem Ende der enthaltenden Kompilierungseinheit werden nachfolgende Versuche unternommen, um einen Kandidaten Satz von Erweiterungs Methoden zu finden:Starting with the closest enclosing namespace declaration, continuing with each enclosing namespace declaration, and ending with the containing compilation unit, successive attempts are made to find a candidate set of extension methods:
- Wenn der angegebene Namespace oder die Kompilierungseinheit direkt nicht generische Typdeklarationen
Ci
mit berechtigten Erweiterungs Methoden enthältMj
, ist der Satz dieser Erweiterungs Methoden der Kandidaten Satz.If the given namespace or compilation unit directly contains non-generic type declarationsCi
with eligible extension methodsMj
, then the set of those extension methods is the candidate set. - Wenn Typen, die
Ci
von using_static_declarations importiert und direkt in Namespaces deklariert werden, die von using_namespace_directive s in den angegebenen Namespace oder in der Kompilierungseinheit importiert wurden, die geeigneten Erweiterungs Methoden direkt enthaltenMj
, ist der Satz dieser Erweiterungs Methoden der Kandidaten Satz.If typesCi
imported by using_static_declarations and directly declared in namespaces imported by using_namespace_directive s in the given namespace or compilation unit directly contain eligible extension methodsMj
, then the set of those extension methods is the candidate set.
- Wenn der angegebene Namespace oder die Kompilierungseinheit direkt nicht generische Typdeklarationen
- Wenn kein Kandidaten Satz in einer einschließenden Namespace Deklaration oder Kompilierungseinheit gefunden wird, tritt ein Kompilierzeitfehler auf.If no candidate set is found in any enclosing namespace declaration or compilation unit, a compile-time error occurs.
- Andernfalls wird die Überladungs Auflösung auf den Kandidaten Satz angewendet, wie in (Überladungs Auflösung) beschrieben.Otherwise, overload resolution is applied to the candidate set as described in (Overload resolution). Wenn keine einzige optimale Methode gefunden wird, tritt ein Kompilierzeitfehler auf.If no single best method is found, a compile-time error occurs.
C
der Typ, in dem die beste Methode als Erweiterungsmethode deklariert wird.C
is the type within which the best method is declared as an extension method.
C
Wenn als Ziel verwendet wird, wird der Methodenaufruf als statischer Methodenaufruf verarbeitet (Kompilierzeit Überprüfung der dynamischen Überladungs Auflösung).Using C
as a target, the method call is then processed as a static method invocation (Compile-time checking of dynamic overload resolution).
Die vorstehenden Regeln bedeuten, dass Instanzmethoden Vorrang vor Erweiterungs Methoden haben, dass die in inneren Namespace Deklarationen verfügbaren Erweiterungs Methoden Vorrang vor Erweiterungs Methoden haben, die in äußeren Namespace Deklarationen verfügbar sind, und dass Erweiterungs Methoden, die direkt in einem Namespace deklariert werden, Vorrang vor Erweiterungs Methoden haben, die mit einer using-namespace Direktive in denselben NamespaceThe preceding rules mean that instance methods take precedence over extension methods, that extension methods available in inner namespace declarations take precedence over extension methods available in outer namespace declarations, and that extension methods declared directly in a namespace take precedence over extension methods imported into that same namespace with a using namespace directive. Beispiel:For example:
public static class E
{
public static void F(this object obj, int i) { }
public static void F(this object obj, string s) { }
}
class A { }
class B
{
public void F(int i) { }
}
class C
{
public void F(object obj) { }
}
class X
{
static void Test(A a, B b, C c) {
a.F(1); // E.F(object, int)
a.F("hello"); // E.F(object, string)
b.F(1); // B.F(int)
b.F("hello"); // E.F(object, string)
c.F(1); // C.F(object)
c.F("hello"); // C.F(object)
}
}
In diesem Beispiel hat die B
-Methode Vorrang vor der ersten Erweiterungsmethode, und C
die-Methode hat Vorrang vor beiden Erweiterungs Methoden.In the example, B
's method takes precedence over the first extension method, and C
's method takes precedence over both extension methods.
public static class C
{
public static void F(this int i) { Console.WriteLine("C.F({0})", i); }
public static void G(this int i) { Console.WriteLine("C.G({0})", i); }
public static void H(this int i) { Console.WriteLine("C.H({0})", i); }
}
namespace N1
{
public static class D
{
public static void F(this int i) { Console.WriteLine("D.F({0})", i); }
public static void G(this int i) { Console.WriteLine("D.G({0})", i); }
}
}
namespace N2
{
using N1;
public static class E
{
public static void F(this int i) { Console.WriteLine("E.F({0})", i); }
}
class Test
{
static void Main(string[] args)
{
1.F();
2.G();
3.H();
}
}
}
Die Ausgabe dieses Beispiels lautet wie folgt:The output of this example is:
E.F(1)
D.G(2)
C.H(3)
D.G``C.G
hat Vorrang vor und hat Vorrang vor E.F
D.F
und C.F
.D.G
takes precedence over C.G
, and E.F
takes precedence over both D.F
and C.F
.
DelegataufrufeDelegate invocations
Bei einem Delegataufruf muss die primary_expression der invocation_expression ein Wert eines delegate_type sein.For a delegate invocation, the primary_expression of the invocation_expression must be a value of a delegate_type. Außerdem muss der delegate_type in Bezug auf den argument_list der invocation_expression anwendbar sein, wenn der delegate_type ein Funktionsmember mit derselben Parameterliste wie der delegate_type ist.Furthermore, considering the delegate_type to be a function member with the same parameter list as the delegate_type, the delegate_type must be applicable (Applicable function member) with respect to the argument_list of the invocation_expression.
Die Lauf Zeit Verarbeitung eines delegataufruens im Formular D(A)
, wobei D
eine primary_expression eines delegate_type und A
ein optionaler argument_list ist, besteht aus den folgenden Schritten:The run-time processing of a delegate invocation of the form D(A)
, where D
is a primary_expression of a delegate_type and A
is an optional argument_list, consists of the following steps:
D
wird ausgewertet.D
is evaluated. Wenn diese Auswertung eine Ausnahme verursacht, werden keine weiteren Schritte ausgeführt.If this evaluation causes an exception, no further steps are executed.- Der Wert von
D
wird als gültig geprüft.The value ofD
is checked to be valid. Wenn der Wert vonD
istnull
, wird eine ausgelöst,System.NullReferenceException
und es werden keine weiteren Schritte ausgeführt.If the value ofD
isnull
, aSystem.NullReferenceException
is thrown and no further steps are executed. - Andernfalls
D
ist ein Verweis auf eine Delegatinstanz.Otherwise,D
is a reference to a delegate instance. Funktionsmember-Aufrufe (Kompilierungszeit Überprüfung der dynamischen Überladungs Auflösung) werden für jede der Aufruf baren Entitäten in der Aufruf Liste des Delegaten ausgeführt.Function member invocations (Compile-time checking of dynamic overload resolution) are performed on each of the callable entities in the invocation list of the delegate. Bei Aufruf baren Entitäten, die aus einer Instanz-und Instanzmethode bestehen, ist die Instanz für den Aufruf die Instanz, die in der Aufruf baren Entität enthalten ist.For callable entities consisting of an instance and instance method, the instance for the invocation is the instance contained in the callable entity.
ElementzugriffElement access
Eine element_access besteht aus einem primary_no_array_creation_expression, gefolgt von einem " [
"-Token, gefolgt von einem argument_list, gefolgt von einem " ]
"-Token.An element_access consists of a primary_no_array_creation_expression, followed by a "[
" token, followed by an argument_list, followed by a "]
" token. Der argument_list besteht aus mindestens einem Argument s, getrennt durch Kommas.The argument_list consists of one or more argument s, separated by commas.
element_access
: primary_no_array_creation_expression '[' expression_list ']'
;
Der argument_list eines element_access darf keine- ref
oder-Argumente enthalten out
.The argument_list of an element_access is not allowed to contain ref
or out
arguments.
Ein- element_access ist dynamisch gebunden (dynamische Bindung), wenn mindestens einer der folgenden Punkte enthält:An element_access is dynamically bound (Dynamic binding) if at least one of the following holds:
- Der primary_no_array_creation_expression weist den Kompilier Zeittyp auf
dynamic
.The primary_no_array_creation_expression has compile-time typedynamic
. - Mindestens ein Ausdruck des argument_list hat einen Kompilier Zeittyp,
dynamic
und die primary_no_array_creation_expression weist keinen Arraytyp auf.At least one expression of the argument_list has compile-time typedynamic
and the primary_no_array_creation_expression does not have an array type.
In diesem Fall klassifiziert der Compiler die element_access als Wert des Typs dynamic
.In this case the compiler classifies the element_access as a value of type dynamic
. Die nachstehenden Regeln zum Bestimmen der Bedeutung der element_access werden dann zur Laufzeit angewendet. dabei wird der Lauf Zeittyp anstelle des Kompilier Zeittyps der primary_no_array_creation_expression und argument_list Ausdrücke verwendet, die den Kompilier Zeittyp aufweisen dynamic
.The rules below to determine the meaning of the element_access are then applied at run-time, using the run-time type instead of the compile-time type of those of the primary_no_array_creation_expression and argument_list expressions which have the compile-time type dynamic
. Wenn das primary_no_array_creation_expression keinen Kompilier Zeittyp hat dynamic
, wird der Zugriff auf die Kompilierzeit durch den Element Zugriff eingeschränkt, wie in der Kompilierzeit Überprüfung der dynamischen Überladungs Auflösungbeschrieben.If the primary_no_array_creation_expression does not have compile-time type dynamic
, then the element access undergoes a limited compile time check as described in Compile-time checking of dynamic overload resolution.
Wenn die primary_no_array_creation_expression eines element_access ein Wert eines array_type ist, ist der element_access ein Array Zugriff (Array Zugriff).If the primary_no_array_creation_expression of an element_access is a value of an array_type, the element_access is an array access (Array access). Andernfalls muss es sich bei der primary_no_array_creation_expression um eine Variable oder einen Wert einer Klasse, Struktur oder eines Schnittstellen Typs handeln, die mindestens ein Indexer-Element aufweist. in diesem Fall ist der element_access ein Indexer-Zugriff (Indexer-Zugriff).Otherwise, the primary_no_array_creation_expression must be a variable or value of a class, struct, or interface type that has one or more indexer members, in which case the element_access is an indexer access (Indexer access).
ArrayzugriffArray access
Bei einem Array Zugriff muss die primary_no_array_creation_expression der element_access ein Wert eines array_type sein.For an array access, the primary_no_array_creation_expression of the element_access must be a value of an array_type. Außerdem darf die argument_list eines Array Zugriffs keine benannten Argumente enthalten. Die Anzahl der Ausdrücke in der argument_list muss mit dem Rang des array_type identisch sein, und jeder Ausdruck muss den Typ int
, uint
,, oder aufweisen, der long
ulong
implizit in einen oder mehrere dieser Typen konvertiert werden muss.Furthermore, the argument_list of an array access is not allowed to contain named arguments.The number of expressions in the argument_list must be the same as the rank of the array_type, and each expression must be of type int
, uint
, long
, ulong
, or must be implicitly convertible to one or more of these types.
Das Ergebnis der Auswertung eines Array Zugriffs ist eine Variable des Elementtyps des Arrays, d. h. das Array Element, das von den Werten der Ausdrücke im argument_list ausgewählt wird.The result of evaluating an array access is a variable of the element type of the array, namely the array element selected by the value(s) of the expression(s) in the argument_list.
Die Lauf Zeit Verarbeitung eines Array Zugriffs auf das Formular P[A]
, wobei P
eine primary_no_array_creation_expression eines array_type und A
eine argument_list ist, besteht aus den folgenden Schritten:The run-time processing of an array access of the form P[A]
, where P
is a primary_no_array_creation_expression of an array_type and A
is an argument_list, consists of the following steps:
P
wird ausgewertet.P
is evaluated. Wenn diese Auswertung eine Ausnahme verursacht, werden keine weiteren Schritte ausgeführt.If this evaluation causes an exception, no further steps are executed.- Die Index Ausdrücke der argument_list werden in der Reihenfolge von links nach rechts ausgewertet.The index expressions of the argument_list are evaluated in order, from left to right. Nach der Auswertung der einzelnen Index Ausdrücke wird eine implizite Konvertierung (implizite Konvertierungen) in einen der folgenden Typen ausgeführt:
int
,uint
,long
,ulong
.Following evaluation of each index expression, an implicit conversion (Implicit conversions) to one of the following types is performed:int
,uint
,long
,ulong
. Der erste Typ in dieser Liste, für den eine implizite Konvertierung vorhanden ist, wird ausgewählt.The first type in this list for which an implicit conversion exists is chosen. Wenn der Index Ausdruck beispielsweise vom Typ ist,short
wird eine implizite Konvertierung inint
durchgeführt, da implizite Konvertierungen vonshort
inint
und vonshort
inlong
möglich sind.For instance, if the index expression is of typeshort
then an implicit conversion toint
is performed, since implicit conversions fromshort
toint
and fromshort
tolong
are possible. Wenn die Auswertung eines Index Ausdrucks oder der nachfolgenden impliziten Konvertierung eine Ausnahme verursacht, werden keine weiteren Index Ausdrücke ausgewertet, und es werden keine weiteren Schritte ausgeführt.If evaluation of an index expression or the subsequent implicit conversion causes an exception, then no further index expressions are evaluated and no further steps are executed. - Der Wert von
P
wird als gültig geprüft.The value ofP
is checked to be valid. Wenn der Wert vonP
istnull
, wird eine ausgelöst,System.NullReferenceException
und es werden keine weiteren Schritte ausgeführt.If the value ofP
isnull
, aSystem.NullReferenceException
is thrown and no further steps are executed. - Der Wert jedes Ausdrucks im argument_list wird anhand der tatsächlichen Begrenzungen der einzelnen Dimensionen der Array Instanz überprüft, auf die von verwiesen wird
P
.The value of each expression in the argument_list is checked against the actual bounds of each dimension of the array instance referenced byP
. Wenn mindestens ein Wert außerhalb des gültigen Bereichs liegt, wird eine ausgelöst,System.IndexOutOfRangeException
und es werden keine weiteren Schritte ausgeführt.If one or more values are out of range, aSystem.IndexOutOfRangeException
is thrown and no further steps are executed. - Der Speicherort des Array Elements, das durch den Index Ausdruck (n) angegeben wird, wird berechnet, und dieser Speicherort wird zum Ergebnis des Array Zugriffs.The location of the array element given by the index expression(s) is computed, and this location becomes the result of the array access.
IndexerzugriffIndexer access
Für einen Indexer-Zugriff muss die primary_no_array_creation_expression der element_access eine Variable oder ein Wert einer Klasse, Struktur oder eines Schnittstellen Typs sein, und dieser Typ muss einen oder mehrere Indexer implementieren, die in Bezug auf die argument_list der element_access anwendbar sind.For an indexer access, the primary_no_array_creation_expression of the element_access must be a variable or value of a class, struct, or interface type, and this type must implement one or more indexers that are applicable with respect to the argument_list of the element_access.
Die Bindungs Zeit Verarbeitung eines Indexer-Zugriffs auf das Formular P[A]
, wobei P
eine primary_no_array_creation_expression einer Klasse, einer Struktur oder eines Schnittstellen Typs ist T
und A
eine argument_list ist, besteht aus den folgenden Schritten:The binding-time processing of an indexer access of the form P[A]
, where P
is a primary_no_array_creation_expression of a class, struct, or interface type T
, and A
is an argument_list, consists of the following steps:
- Der von bereitgestellte Indexer-Satz
T
wird erstellt.The set of indexers provided byT
is constructed. Der Satz besteht aus allen indexermembern, die in deklariertT
werden, oder einem Basistyp vonT
, die keineoverride
Deklarationen sind und auf die im aktuellen Kontext zugegriffen werden kann (Member Access).The set consists of all indexers declared inT
or a base type ofT
that are notoverride
declarations and are accessible in the current context (Member access). - Der Satz wird auf die Indexer reduziert, die anwendbar sind und von anderen Indexer nicht ausgeblendet werden.The set is reduced to those indexers that are applicable and not hidden by other indexers. Die folgenden Regeln werden auf jeden Indexer
S.I
im Satz angewendet, wobeiS
der Typ ist, in dem der IndexerI
deklariert ist:The following rules are applied to each indexerS.I
in the set, whereS
is the type in which the indexerI
is declared:- Wenn
I
nicht in Bezug aufA
(anwendbares Funktionsmember) anwendbar ist,I
wird aus dem Satz entfernt.IfI
is not applicable with respect toA
(Applicable function member), thenI
is removed from the set. - Wenn in
I
Bezug aufA
(anwendbares Funktionsmember) anwendbar ist, werden alle in einem Basistyp von deklarierten IndexerS
aus dem Satz entfernt.IfI
is applicable with respect toA
(Applicable function member), then all indexers declared in a base type ofS
are removed from the set. - Wenn in
I
Bezug aufA
(anwendbares Funktionsmember) anwendbar ist undS
ein anderer Klassentyp als istobject
, werden alle in einer Schnittstelle deklarierten Indexer aus dem Satz entfernt.IfI
is applicable with respect toA
(Applicable function member) andS
is a class type other thanobject
, all indexers declared in an interface are removed from the set.
- Wenn
- Wenn der resultierende Satz von Kandidaten Indexer leer ist, sind keine anwendbaren Indexer vorhanden, und es tritt ein Bindungs Zeitfehler auf.If the resulting set of candidate indexers is empty, then no applicable indexers exist, and a binding-time error occurs.
- Der beste Indexer der Gruppe von Kandidaten Indexern wird mithilfe der Regeln zur Überladungs Auflösung der Überladungs Auflösungidentifiziert.The best indexer of the set of candidate indexers is identified using the overload resolution rules of Overload resolution. Wenn ein einzelner optimaler Indexer nicht identifiziert werden kann, ist der Indexerzugriff mehrdeutig, und es tritt ein Fehler bei der Bindung auf.If a single best indexer cannot be identified, the indexer access is ambiguous, and a binding-time error occurs.
- Die Index Ausdrücke der argument_list werden in der Reihenfolge von links nach rechts ausgewertet.The index expressions of the argument_list are evaluated in order, from left to right. Das Ergebnis der Verarbeitung des Indexer-Zugriffs ist ein Ausdruck, der als Indexer-Zugriff klassifiziert ist.The result of processing the indexer access is an expression classified as an indexer access. Der indexerzugriffsausdruck verweist auf den Indexer, der im obigen Schritt festgelegt wurde, und verfügt über einen zugeordneten Instanzausdruck
P
und eine zugeordnete Argumentliste vonA
.The indexer access expression references the indexer determined in the step above, and has an associated instance expression ofP
and an associated argument list ofA
.
Abhängig vom Kontext, in dem Sie verwendet werden, bewirkt ein Indexer-Zugriff, dass entweder der Get-Accessor oder der Set-Accessor des Indexers aufgerufen wird.Depending on the context in which it is used, an indexer access causes invocation of either the get accessor or the set accessor of the indexer. Wenn der Indexer-Zugriff das Ziel einer Zuweisung ist, wird der Set-Accessor aufgerufen, um einen neuen Wert zuzuweisen (einfache Zuweisung).If the indexer access is the target of an assignment, the set accessor is invoked to assign a new value (Simple assignment). In allen anderen Fällen wird der Get-Accessor aufgerufen, um den aktuellen Wert zu erhalten (Werte von Ausdrücken).In all other cases, the get accessor is invoked to obtain the current value (Values of expressions).
Dieser ZugriffThis access
Ein this_access besteht aus dem reservierten Wort this
.A this_access consists of the reserved word this
.
this_access
: 'this'
;
Eine this_access ist nur im- Block eines Instanzkonstruktors, einer Instanzmethode oder eines Instanzaccessors zulässig.A this_access is permitted only in the block of an instance constructor, an instance method, or an instance accessor. Dies hat eine der folgenden Bedeutungen:It has one of the following meanings:
- Wenn
this
in einer primary_expression in einem Instanzkonstruktor einer Klasse verwendet wird, wird Sie als Wert klassifiziert.Whenthis
is used in a primary_expression within an instance constructor of a class, it is classified as a value. Der Typ des Werts ist der Instanztyp (der Instanztyp) der Klasse, in der die Verwendung erfolgt, und der Wert ist ein Verweis auf das Objekt, das erstellt wird.The type of the value is the instance type (The instance type) of the class within which the usage occurs, and the value is a reference to the object being constructed. - Wenn
this
in einer primary_expression in einer Instanzmethode oder einem Instanzaccessor einer Klasse verwendet wird, wird Sie als Wert klassifiziert.Whenthis
is used in a primary_expression within an instance method or instance accessor of a class, it is classified as a value. Der Typ des Werts ist der Instanztyp (der Instanztyp) der Klasse, in der die Verwendung erfolgt, und der Wert ist ein Verweis auf das Objekt, für das die Methode oder der Accessor aufgerufen wurde.The type of the value is the instance type (The instance type) of the class within which the usage occurs, and the value is a reference to the object for which the method or accessor was invoked. - Wenn
this
in einem primary_expression innerhalb eines Instanzkonstruktors einer Struktur verwendet wird, wird es als Variable klassifiziert.Whenthis
is used in a primary_expression within an instance constructor of a struct, it is classified as a variable. Der Typ der Variablen ist der Instanztyp (der Instanztyp) der Struktur, in der die Verwendung erfolgt, und die Variable stellt die Struktur dar, die erstellt wird.The type of the variable is the instance type (The instance type) of the struct within which the usage occurs, and the variable represents the struct being constructed. Diethis
Variable eines Instanzkonstruktors einer Struktur verhält sich genau wie einout
Parameter des Struktur Typs – Dies bedeutet insbesondere, dass die Variable definitiv in jedem Ausführungs Pfad des Instanzkonstruktors zugewiesen werden muss.Thethis
variable of an instance constructor of a struct behaves exactly the same as anout
parameter of the struct type—in particular, this means that the variable must be definitely assigned in every execution path of the instance constructor. - Wenn
this
in einer primary_expression in einer Instanzmethode oder einem Instanzaccessor einer Struktur verwendet wird, wird Sie als Variable klassifiziert.Whenthis
is used in a primary_expression within an instance method or instance accessor of a struct, it is classified as a variable. Der Typ der Variablen ist der Instanztyp (der Instanztyp) der Struktur, in der die Verwendung erfolgt.The type of the variable is the instance type (The instance type) of the struct within which the usage occurs.- Wenn die Methode oder der Accessor kein Iterator (Iteratoren) ist,
this
stellt die Variable die Struktur dar, für die die Methode oder der Accessor aufgerufen wurde, und verhält sich genau wie einref
Parameter des Struktur Typs.If the method or accessor is not an iterator (Iterators), thethis
variable represents the struct for which the method or accessor was invoked, and behaves exactly the same as aref
parameter of the struct type. - Wenn es sich bei der Methode oder dem Accessor um einen Iterator handelt,
this
stellt die Variable eine Kopie der Struktur dar, für die die Methode oder der Accessor aufgerufen wurde, und verhält sich genau wie ein Wert Parameter des Struktur Typs.If the method or accessor is an iterator, thethis
variable represents a copy of the struct for which the method or accessor was invoked, and behaves exactly the same as a value parameter of the struct type.
- Wenn die Methode oder der Accessor kein Iterator (Iteratoren) ist,
Die Verwendung von this
in einem primary_expression in einem anderen als dem oben aufgeführten Kontext ist ein Kompilierzeitfehler.Use of this
in a primary_expression in a context other than the ones listed above is a compile-time error. Insbesondere ist es nicht möglich, auf this
eine statische Methode, einen statischen Eigenschafts Accessor oder eine variable_initializer einer Feld Deklaration zu verweisen.In particular, it is not possible to refer to this
in a static method, a static property accessor, or in a variable_initializer of a field declaration.
Basis ZugriffBase access
Ein base_access besteht aus dem reservierten Wort, base
gefolgt von einem " .
"-Token und einem-Bezeichner oder einem in eckige Klammern eingeschlossenen argument_list :A base_access consists of the reserved word base
followed by either a ".
" token and an identifier or an argument_list enclosed in square brackets:
base_access
: 'base' '.' identifier
| 'base' '[' expression_list ']'
;
Ein base_access wird für den Zugriff auf Basisklassenmember verwendet, die durch ähnlich benannte Member in der aktuellen Klasse oder Struktur ausgeblendet werden.A base_access is used to access base class members that are hidden by similarly named members in the current class or struct. Eine base_access ist nur im- Block eines Instanzkonstruktors, einer Instanzmethode oder eines Instanzaccessors zulässig.A base_access is permitted only in the block of an instance constructor, an instance method, or an instance accessor. Wenn base.I
in einer Klasse oder Struktur vorkommt, I
muss einen Member der Basisklasse dieser Klasse oder Struktur bezeichnen.When base.I
occurs in a class or struct, I
must denote a member of the base class of that class or struct. Ebenso muss bei base[E]
Auftreten von in einer Klasse ein anwendbarer Indexer in der Basisklasse vorhanden sein.Likewise, when base[E]
occurs in a class, an applicable indexer must exist in the base class.
Bei der Bindungs Zeit werden base_access Ausdrücke des Formulars base.I
und genauso base[E]
ausgewertet, als wären Sie geschrieben worden ((B)this).I
((B)this)[E]
, wobei B
die Basisklasse der Klasse oder Struktur ist, in der das Konstrukt auftritt.At binding-time, base_access expressions of the form base.I
and base[E]
are evaluated exactly as if they were written ((B)this).I
and ((B)this)[E]
, where B
is the base class of the class or struct in which the construct occurs. Folglich base.I
entsprechen und und base[E]
this.I
this[E]
, außer this
als Instanz der Basisklasse.Thus, base.I
and base[E]
correspond to this.I
and this[E]
, except this
is viewed as an instance of the base class.
Wenn eine base_access auf einen virtuellen Funktionsmember (eine Methode, eine Eigenschaft oder einen Indexer) verweist, wird bestimmt, welcher Funktionsmember zur Laufzeit aufgerufen werden soll (über Prüfung der Auflösung der dynamischen Überlastung).When a base_access references a virtual function member (a method, property, or indexer), the determination of which function member to invoke at run-time (Compile-time checking of dynamic overload resolution) is changed. Der aufgerufene Funktionsmember wird ermittelt, indem die am meisten abgeleitete Implementierung (virtuelle Methoden) des Funktionsmembers in Bezug auf B
(anstelle des Lauf Zeit Typs this
, wie bei einem nicht-Basis-Zugriff üblich) gefunden wird.The function member that is invoked is determined by finding the most derived implementation (Virtual methods) of the function member with respect to B
(instead of with respect to the run-time type of this
, as would be usual in a non-base access). Daher override
virtual
kann ein base_access in einem eines Funktionsmembers verwendet werden, um die geerbte Implementierung des Funktionsmembers aufzurufen.Thus, within an override
of a virtual
function member, a base_access can be used to invoke the inherited implementation of the function member. Wenn das von einem base_access referenzierte Funktionsmember abstrakt ist, tritt ein Fehler bei der Bindung auf.If the function member referenced by a base_access is abstract, a binding-time error occurs.
Postfix-Inkrementoperator und Postfix-DekrementoperatorPostfix increment and decrement operators
post_increment_expression
: primary_expression '++'
;
post_decrement_expression
: primary_expression '--'
;
Der Operand eines Postfix-Inkrement-oder dekrementvorgangs muss ein Ausdruck sein, der als Variable, Eigenschafts Zugriff oder Indexerzugriff klassifiziert ist.The operand of a postfix increment or decrement operation must be an expression classified as a variable, a property access, or an indexer access. Das Ergebnis des Vorgangs ist ein Wert desselben Typs wie der Operand.The result of the operation is a value of the same type as the operand.
Wenn das primary_expression den Kompilier Zeittyp aufweist dynamic
, wird der Operator dynamisch gebunden (dynamische Bindung), die post_increment_expression oder post_decrement_expression den Kompilier Zeittyp, dynamic
und die folgenden Regeln werden zur Laufzeit mithilfe des Lauf Zeit Typs der primary_expression angewendet.If the primary_expression has the compile-time type dynamic
then the operator is dynamically bound (Dynamic binding), the post_increment_expression or post_decrement_expression has the compile-time type dynamic
and the following rules are applied at run-time using the run-time type of the primary_expression.
Wenn der Operand einer Postfix-Inkrement-oder Dekrementoperation eine Eigenschaft oder ein Indexer-Zugriff ist, muss die Eigenschaft oder der Indexer sowohl einen get
-als auch einen- set
Accessor aufweisen.If the operand of a postfix increment or decrement operation is a property or indexer access, the property or indexer must have both a get
and a set
accessor. Wenn dies nicht der Fall ist, tritt ein Bindungs Zeitfehler auf.If this is not the case, a binding-time error occurs.
Unäre Operator Überladungs Auflösung (unäre Operator Überladungs Auflösung) wird angewendet, um eine bestimmte Operator Implementierung auszuwählen.Unary operator overload resolution (Unary operator overload resolution) is applied to select a specific operator implementation. ++
--
Für die folgenden Typen sind vordefinierte-und-Operatoren vorhanden: sbyte
, byte
, short
, ushort
, int
, uint
, long
, ulong
, char
, float
, double
, decimal
und ein beliebiger Enumerationstyp.Predefined ++
and --
operators exist for the following types: sbyte
, byte
, short
, ushort
, int
, uint
, long
, ulong
, char
, float
, double
, decimal
, and any enum type. Die vordefinierten ++
Operatoren geben den Wert zurück, der beim Hinzufügen von 1 zum Operanden erzeugt wurde, und die vordefinierten --
Operatoren geben den Wert zurück, der durch die Subtraktion von 1 vom Operanden erzeugt wird.The predefined ++
operators return the value produced by adding 1 to the operand, and the predefined --
operators return the value produced by subtracting 1 from the operand. Wenn in einem checked
Kontext das Ergebnis dieser Addition oder Subtraktion außerhalb des Bereichs des Ergebnis Typs liegt und der Ergebnistyp ein ganzzahliger Typ oder Enumeration-Typ ist, System.OverflowException
wird eine ausgelöst.In a checked
context, if the result of this addition or subtraction is outside the range of the result type and the result type is an integral type or enum type, a System.OverflowException
is thrown.
Die Lauf Zeit Verarbeitung einer Postfix-Inkrement-oder Dekrementoperation des Formulars x++
oder x--
besteht aus den folgenden Schritten:The run-time processing of a postfix increment or decrement operation of the form x++
or x--
consists of the following steps:
- Wenn
x
als Variable klassifiziert ist:Ifx
is classified as a variable:x
wird ausgewertet, um die Variable zu entwickeln.x
is evaluated to produce the variable.- Der Wert von
x
wird gespeichert.The value ofx
is saved. - Der ausgewählte Operator wird mit dem gespeicherten Wert von
x
als sein Argument aufgerufen.The selected operator is invoked with the saved value ofx
as its argument. - Der vom-Operator zurückgegebene Wert wird an dem Speicherort gespeichert, der durch die Auswertung von angegeben wird
x
.The value returned by the operator is stored in the location given by the evaluation ofx
. - Der gespeicherte Wert von
x
wird das Ergebnis des Vorgangs.The saved value ofx
becomes the result of the operation.
- Wenn
x
als Eigenschaft oder Indexer-Zugriff klassifiziert ist:Ifx
is classified as a property or indexer access:- Der Instanzausdruck (wenn
x
nicht iststatic
), und die Argumentliste (wennx
ein Indexer-Zugriff ist), die zugeordnet istx
, wird ausgewertet, und die Ergebnisse werden in den nachfolgendenget
-und-Accessoraufrufen verwendetset
.The instance expression (ifx
is notstatic
) and the argument list (ifx
is an indexer access) associated withx
are evaluated, and the results are used in the subsequentget
andset
accessor invocations. - Der
get
-Accessor vonx
wird aufgerufen, und der zurückgegebene Wert wird gespeichert.Theget
accessor ofx
is invoked and the returned value is saved. - Der ausgewählte Operator wird mit dem gespeicherten Wert von
x
als sein Argument aufgerufen.The selected operator is invoked with the saved value ofx
as its argument. - Der-
set
Accessor vonx
wird mit dem Wert aufgerufen, der vom Operator als sein Argument zurückgegeben wurdevalue
.Theset
accessor ofx
is invoked with the value returned by the operator as itsvalue
argument. - Der gespeicherte Wert von
x
wird das Ergebnis des Vorgangs.The saved value ofx
becomes the result of the operation.
- Der Instanzausdruck (wenn
Die ++
--
Operatoren und unterstützen auch Präfix Notation (Präfix Inkrement-und Dekrementoperatoren).The ++
and --
operators also support prefix notation (Prefix increment and decrement operators). In der Regel ist das Ergebnis von x++
oder x--
der Wert von x
vor dem Vorgang, wohingegen das Ergebnis von ++x
oder --x
der Wert von x
nach dem Vorgang ist.Typically, the result of x++
or x--
is the value of x
before the operation, whereas the result of ++x
or --x
is the value of x
after the operation. In jedem Fall x
hat nach dem Vorgang denselben Wert.In either case, x
itself has the same value after the operation.
Eine- operator ++
oder- operator --
Implementierung kann entweder mithilfe der Postfix-oder Präfix Notation aufgerufen werden.An operator ++
or operator --
implementation can be invoked using either postfix or prefix notation. Es ist nicht möglich, separate Operator Implementierungen für die beiden Notationen zu haben.It is not possible to have separate operator implementations for the two notations.
Der new-OperatorThe new operator
Der- new
Operator wird verwendet, um neue Instanzen von-Typen zu erstellen.The new
operator is used to create new instances of types.
Es gibt drei Formen von new
Ausdrücken:There are three forms of new
expressions:
- Objekt Erstellungs Ausdrücke werden verwendet, um neue Instanzen von Klassentypen und Werttypen zu erstellen.Object creation expressions are used to create new instances of class types and value types.
- Array Erstellungs Ausdrücke werden verwendet, um neue Instanzen von Array Typen zu erstellen.Array creation expressions are used to create new instances of array types.
- Delegaterstellungs-Ausdrücke werden verwendet, um neue Instanzen von Delegattypen zu erstellen.Delegate creation expressions are used to create new instances of delegate types.
Der new
Operator impliziert die Erstellung einer Instanz eines Typs, impliziert jedoch nicht notwendigerweise die dynamische Speicher Belegung.The new
operator implies creation of an instance of a type, but does not necessarily imply dynamic allocation of memory. Vor allem sind für Instanzen von Werttypen außerhalb der Variablen, in denen Sie sich befinden, kein zusätzlicher Arbeitsspeicher erforderlich. es treten keine dynamischen Zuordnungen auf, wenn new
zum Erstellen von Instanzen von Werttypen verwendet wird.In particular, instances of value types require no additional memory beyond the variables in which they reside, and no dynamic allocations occur when new
is used to create instances of value types.
Objekt Erstellungs AusdrückeObject creation expressions
Eine object_creation_expression wird zum Erstellen einer neuen Instanz einer class_type oder einer value_type verwendet.An object_creation_expression is used to create a new instance of a class_type or a value_type.
object_creation_expression
: 'new' type '(' argument_list? ')' object_or_collection_initializer?
| 'new' type object_or_collection_initializer
;
object_or_collection_initializer
: object_initializer
| collection_initializer
;
Der Typ eines object_creation_expression muss ein class_type, ein value_type oder ein type_parameter sein.The type of an object_creation_expression must be a class_type, a value_type or a type_parameter. Der Typ darf keine abstract
class_type sein.The type cannot be an abstract
class_type.
Die optionalen argument_list (Argumentlisten) sind nur zulässig, wenn es sich bei dem Typ um einen class_type oder eine struct_type handelt.The optional argument_list (Argument lists) is permitted only if the type is a class_type or a struct_type.
Ein Objekt Erstellungs Ausdruck kann die Liste der Konstruktorargumente weglassen und einschließende Klammern einschließen, wenn er einen Objektinitialisierer oder einen Auflistungsinitialisierer enthält.An object creation expression can omit the constructor argument list and enclosing parentheses provided it includes an object initializer or collection initializer. Das Weglassen der Konstruktorargumentliste und das Einschließen von Klammern entspricht der Angabe einer leeren Argumentliste.Omitting the constructor argument list and enclosing parentheses is equivalent to specifying an empty argument list.
Die Verarbeitung eines Ausdrucks zur Objekt Erstellung, der einen Objektinitialisierer oder Auflistungsinitialisierer enthält, besteht aus der ersten Verarbeitung des Instanzkonstruktors und der anschließenden Verarbeitung der Element-oder Element Initialisierungen, die vom Objektinitialisierer (Objektinitialisierer) oder sammlungsinitialisierer (sammlungsinitialisiererProcessing of an object creation expression that includes an object initializer or collection initializer consists of first processing the instance constructor and then processing the member or element initializations specified by the object initializer (Object initializers) or collection initializer (Collection initializers).
Wenn eines der Argumente im optionalen argument_list den Kompilier Zeittyp aufweist dynamic
, wird der object_creation_expression dynamisch gebunden (dynamische Bindung), und die folgenden Regeln werden zur Laufzeit verwendet, wobei der Lauf Zeittyp der Argumente der argument_list , die den Kompilier Zeittyp aufweisen, verwendet wird dynamic
.If any of the arguments in the optional argument_list has the compile-time type dynamic
then the object_creation_expression is dynamically bound (Dynamic binding) and the following rules are applied at run-time using the run-time type of those arguments of the argument_list that have the compile time type dynamic
. Allerdings wird bei der Objekt Erstellung eine beschränkte Kompilierungszeit Überprüfung durchgeführt, wie in der Kompilierzeit Überprüfung der dynamischen Überladungs Auflösungbeschrieben.However, the object creation undergoes a limited compile time check as described in Compile-time checking of dynamic overload resolution.
Die Bindungs Zeit Verarbeitung einer object_creation_expression der Form new T(A)
, wobei T
ein class_type oder ein value_type ist und A
ein optionaler argument_list ist, besteht aus den folgenden Schritten:The binding-time processing of an object_creation_expression of the form new T(A)
, where T
is a class_type or a value_type and A
is an optional argument_list, consists of the following steps:
- Wenn
T
ein value_type ist undA
nicht vorhanden ist:IfT
is a value_type andA
is not present:- Der object_creation_expression ist ein standardkonstruktoraufruf.The object_creation_expression is a default constructor invocation. Das Ergebnis der object_creation_expression ist ein Wert vom Typ
T
, d. h. der Standardwert für,T
wie im System. ValueType-Typdefiniert.The result of the object_creation_expression is a value of typeT
, namely the default value forT
as defined in The System.ValueType type.
- Der object_creation_expression ist ein standardkonstruktoraufruf.The object_creation_expression is a default constructor invocation. Das Ergebnis der object_creation_expression ist ein Wert vom Typ
- Andernfalls, wenn
T
ein type_parameter ist undA
nicht vorhanden ist:Otherwise, ifT
is a type_parameter andA
is not present:- Wenn keine Werttyp Einschränkung oder Konstruktoreinschränkung (Typparameter Einschränkungen) für angegeben wurde
T
, tritt ein Bindungs Zeitfehler auf.If no value type constraint or constructor constraint (Type parameter constraints) has been specified forT
, a binding-time error occurs. - Das Ergebnis der object_creation_expression ist ein Wert des Lauf Zeittyps, an den der Typparameter gebunden wurde, nämlich das Ergebnis des Aufrufs des Standardkonstruktors dieses Typs.The result of the object_creation_expression is a value of the run-time type that the type parameter has been bound to, namely the result of invoking the default constructor of that type. Der Lauf Zeittyp kann ein Referenztyp oder ein Werttyp sein.The run-time type may be a reference type or a value type.
- Wenn keine Werttyp Einschränkung oder Konstruktoreinschränkung (Typparameter Einschränkungen) für angegeben wurde
- Andernfalls, wenn
T
ein class_type oder ein struct_type ist:Otherwise, ifT
is a class_type or a struct_type:- Wenn
T
einabstract
class_type ist, tritt ein Kompilierzeitfehler auf.IfT
is anabstract
class_type, a compile-time error occurs. - Der aufzurufende Instanzkonstruktor wird mithilfe der Regeln zur Überladungs Auflösung der Überladungs Auflösungbestimmt.The instance constructor to invoke is determined using the overload resolution rules of Overload resolution. Der Satz von Kandidaten Instanzkonstruktoren besteht aus allen zugänglichen Instanzkonstruktoren
T
, die in deklariert sind und in Bezug aufA
(anwendbares Funktionsmember) anwendbar sind.The set of candidate instance constructors consists of all accessible instance constructors declared inT
which are applicable with respect toA
(Applicable function member). Wenn der Satz von standardinstanzkonstruktoren leer ist, oder wenn ein einzelner Konstruktor mit der besten Instanz nicht identifiziert werden kann, tritt ein Bindungs Zeitfehler auf.If the set of candidate instance constructors is empty, or if a single best instance constructor cannot be identified, a binding-time error occurs. - Das Ergebnis der object_creation_expression ist ein Wert vom Typ
T
, d. h. der Wert, der durch Aufrufen des Instanzkonstruktors erzeugt wird, der im obigen Schritt festgelegt wurde.The result of the object_creation_expression is a value of typeT
, namely the value produced by invoking the instance constructor determined in the step above.
- Wenn
- Andernfalls ist der object_creation_expression ungültig, und ein Bindungs Fehler tritt auf.Otherwise, the object_creation_expression is invalid, and a binding-time error occurs.
Auch wenn die object_creation_expression dynamisch gebunden ist, ist der Kompilier Zeittyp immer noch T
.Even if the object_creation_expression is dynamically bound, the compile-time type is still T
.
Die Lauf Zeit Verarbeitung einer object_creation_expression der Form new T(A)
, wobei T
class_type oder ein struct_type ist und A
eine optionale argument_list ist, besteht aus den folgenden Schritten:The run-time processing of an object_creation_expression of the form new T(A)
, where T
is class_type or a struct_type and A
is an optional argument_list, consists of the following steps:
- Wenn
T
ein class_type ist:IfT
is a class_type:- Es wird eine neue Instanz der-Klasse
T
zugeordnet.A new instance of classT
is allocated. Wenn nicht genügend Arbeitsspeicher zur Verfügung steht, um die neue Instanz zuzuordnen, wird eine ausgelöst,System.OutOfMemoryException
und es werden keine weiteren Schritte ausgeführt.If there is not enough memory available to allocate the new instance, aSystem.OutOfMemoryException
is thrown and no further steps are executed. - Alle Felder der neuen Instanz werden mit ihren Standardwerten initialisiert (Standardwerte).All fields of the new instance are initialized to their default values (Default values).
- Der Instanzkonstruktor wird entsprechend den Regeln für den Funktionselement Aufruf (Kompilierzeit Überprüfung der dynamischen Überladungs Auflösung) aufgerufen.The instance constructor is invoked according to the rules of function member invocation (Compile-time checking of dynamic overload resolution). Ein Verweis auf die neu zugeordnete-Instanz wird automatisch an den Instanzkonstruktor übergeben, und der Zugriff auf die-Instanz kann innerhalb dieses Konstruktors als erfolgen
this
.A reference to the newly allocated instance is automatically passed to the instance constructor and the instance can be accessed from within that constructor asthis
.
- Es wird eine neue Instanz der-Klasse
- Wenn
T
ein struct_type ist:IfT
is a struct_type:- Eine Instanz vom Typ
T
wird erstellt, indem eine temporäre lokale Variable zugewiesen wird.An instance of typeT
is created by allocating a temporary local variable. Da ein Instanzkonstruktor einer struct_type erforderlich ist, um jedem Feld der erstellten Instanz einen Wert definitiv zuzuweisen, ist keine Initialisierung der temporären Variablen erforderlich.Since an instance constructor of a struct_type is required to definitely assign a value to each field of the instance being created, no initialization of the temporary variable is necessary. - Der Instanzkonstruktor wird entsprechend den Regeln für den Funktionselement Aufruf (Kompilierzeit Überprüfung der dynamischen Überladungs Auflösung) aufgerufen.The instance constructor is invoked according to the rules of function member invocation (Compile-time checking of dynamic overload resolution). Ein Verweis auf die neu zugeordnete-Instanz wird automatisch an den Instanzkonstruktor übergeben, und der Zugriff auf die-Instanz kann innerhalb dieses Konstruktors als erfolgen
this
.A reference to the newly allocated instance is automatically passed to the instance constructor and the instance can be accessed from within that constructor asthis
.
- Eine Instanz vom Typ
ObjektinitialisiererObject initializers
Ein Objektinitialisierer gibt Werte für NULL oder mehr Felder, Eigenschaften oder indizierte Elemente eines Objekts an.An object initializer specifies values for zero or more fields, properties or indexed elements of an object.
object_initializer
: '{' member_initializer_list? '}'
| '{' member_initializer_list ',' '}'
;
member_initializer_list
: member_initializer (',' member_initializer)*
;
member_initializer
: initializer_target '=' initializer_value
;
initializer_target
: identifier
| '[' argument_list ']'
;
initializer_value
: expression
| object_or_collection_initializer
;
Ein Objektinitialisierer besteht aus einer Sequenz von Elementinitialisierern, die von {
-und- }
Token eingeschlossen und durch Kommas getrennt sind.An object initializer consists of a sequence of member initializers, enclosed by {
and }
tokens and separated by commas. Jede member_initializer bestimmt ein Ziel für die Initialisierung.Each member_initializer designates a target for the initialization. Ein Bezeichner muss ein barrierefreies Feld oder eine Eigenschaft des Objekts benennen, das initialisiert wird, wohingegen eine in eckige Klammern eingeschlossene argument_list Argumente für einen zugreif baren Indexer für das Objekt angeben muss, das initialisiert wird.An identifier must name an accessible field or property of the object being initialized, whereas an argument_list enclosed in square brackets must specify arguments for an accessible indexer on the object being initialized. Es ist ein Fehler, wenn ein Objektinitialisierer mehr als einen Elementinitialisierer für das gleiche Feld oder die gleiche Eigenschaft einschließt.It is an error for an object initializer to include more than one member initializer for the same field or property.
Auf jede initializer_target folgt ein Gleichheitszeichen und entweder ein Ausdruck, ein Objektinitialisierer oder ein Auflistungsinitialisierer.Each initializer_target is followed by an equals sign and either an expression, an object initializer or a collection initializer. Es ist nicht möglich, dass Ausdrücke im Objektinitialisierer auf das neu erstellte Objekt verweisen, das initialisiert wird.It is not possible for expressions within the object initializer to refer to the newly created object it is initializing.
Ein Member-Initialisierer, der einen Ausdruck angibt, nachdem das Gleichheitszeichen auf die gleiche Weise wie eine Zuweisung (einfache Zuweisung) zum Ziel verarbeitet wird.A member initializer that specifies an expression after the equals sign is processed in the same way as an assignment (Simple assignment) to the target.
Ein Member-Initialisierer, der einen Objektinitialisierer angibt, nachdem das Gleichheitszeichen ein instanzinitialisierer ist, d. h. eine Initialisierung eines eingebetteten Objekts.A member initializer that specifies an object initializer after the equals sign is a nested object initializer, i.e. an initialization of an embedded object. Anstatt dem Feld oder der Eigenschaft einen neuen Wert zuzuweisen, werden die Zuweisungen im Initialisierer für den initialisierten Objektinitialisierer als Zuweisungen zu Membern des Felds oder der Eigenschaft behandelt.Instead of assigning a new value to the field or property, the assignments in the nested object initializer are treated as assignments to members of the field or property. Initialisierer für ein Objekt können nicht auf Eigenschaften mit einem Werttyp oder auf schreibgeschützte Felder mit einem Werttyp angewendet werden.Nested object initializers cannot be applied to properties with a value type, or to read-only fields with a value type.
Ein Member-Initialisierer, der einen Auflistungsinitialisierer angibt, nachdem das Gleichheitszeichen eine Initialisierung einer eingebetteten Auflistung ist.A member initializer that specifies a collection initializer after the equals sign is an initialization of an embedded collection. Anstatt dem Zielfeld, der Eigenschaft oder dem Indexer eine neue Auflistung zuzuweisen, werden die im Initialisierer angegebenen Elemente der Auflistung hinzugefügt, auf die das Ziel verweist.Instead of assigning a new collection to the target field, property or indexer, the elements given in the initializer are added to the collection referenced by the target. Das Ziel muss einen Sammlungstyp aufweisen, der die in Auflistungsinitialisierer angegebenen Anforderungen erfüllt. The target must be of a collection type that satisfies the requirements specified in Collection initializers.
Die Argumente für einen indexinitialisierer werden immer genau einmal ausgewertet.The arguments to an index initializer will always be evaluated exactly once. Folglich werden Sie, selbst wenn die Argumente am Ende nie verwendet werden (z. b. aufgrund eines leeren Initialisierers), auf Ihre Nebeneffekte ausgewertet.Thus, even if the arguments end up never getting used (e.g. because of an empty nested initializer), they will be evaluated for their side effects.
Die folgende Klasse stellt einen Punkt mit zwei Koordinaten dar:The following class represents a point with two coordinates:
public class Point
{
int x, y;
public int X { get { return x; } set { x = value; } }
public int Y { get { return y; } set { y = value; } }
}
Eine Instanz von Point
kann wie folgt erstellt und initialisiert werden:An instance of Point
can be created and initialized as follows:
Point a = new Point { X = 0, Y = 1 };
Dies hat die gleiche Wirkung wiewhich has the same effect as
Point __a = new Point();
__a.X = 0;
__a.Y = 1;
Point a = __a;
dabei __a
ist eine anderweitig unsichtbare und nicht zugängliche temporäre Variable.where __a
is an otherwise invisible and inaccessible temporary variable. Die folgende Klasse stellt ein Rechteck dar, das aus zwei Punkten erstellt wurde:The following class represents a rectangle created from two points:
public class Rectangle
{
Point p1, p2;
public Point P1 { get { return p1; } set { p1 = value; } }
public Point P2 { get { return p2; } set { p2 = value; } }
}
Eine Instanz von Rectangle
kann wie folgt erstellt und initialisiert werden:An instance of Rectangle
can be created and initialized as follows:
Rectangle r = new Rectangle {
P1 = new Point { X = 0, Y = 1 },
P2 = new Point { X = 2, Y = 3 }
};
Dies hat die gleiche Wirkung wiewhich has the same effect as
Rectangle __r = new Rectangle();
Point __p1 = new Point();
__p1.X = 0;
__p1.Y = 1;
__r.P1 = __p1;
Point __p2 = new Point();
__p2.X = 2;
__p2.Y = 3;
__r.P2 = __p2;
Rectangle r = __r;
dabei __r
__p1
handelt es sich bei und __p2
um temporäre Variablen, die andernfalls unsichtbar und nicht zugänglich sind.where __r
, __p1
and __p2
are temporary variables that are otherwise invisible and inaccessible.
, Wenn Rectangle
der Konstruktor die beiden eingebetteten Instanzen ordnet. Point
If Rectangle
's constructor allocates the two embedded Point
instances
public class Rectangle
{
Point p1 = new Point();
Point p2 = new Point();
public Point P1 { get { return p1; } }
public Point P2 { get { return p2; } }
}
Das folgende Konstrukt kann verwendet werden, um die eingebetteten Instanzen zu initialisieren, Point
anstatt neue Instanzen zuzuweisen:the following construct can be used to initialize the embedded Point
instances instead of assigning new instances:
Rectangle r = new Rectangle {
P1 = { X = 0, Y = 1 },
P2 = { X = 2, Y = 3 }
};
Dies hat die gleiche Wirkung wiewhich has the same effect as
Rectangle __r = new Rectangle();
__r.P1.X = 0;
__r.P1.Y = 1;
__r.P2.X = 2;
__r.P2.Y = 3;
Rectangle r = __r;
Im folgenden Beispiel wird eine entsprechende Definition von C angegeben:Given an appropriate definition of C, the following example:
var c = new C {
x = true,
y = { a = "Hello" },
z = { 1, 2, 3 },
["x"] = 5,
[0,0] = { "a", "b" },
[1,2] = {}
};
entspricht dieser Reihe von Zuweisungen:is equivalent to this series of assignments:
C __c = new C();
__c.x = true;
__c.y.a = "Hello";
__c.z.Add(1);
__c.z.Add(2);
__c.z.Add(3);
string __i1 = "x";
__c[__i1] = 5;
int __i2 = 0, __i3 = 0;
__c[__i2,__i3].Add("a");
__c[__i2,__i3].Add("b");
int __i4 = 1, __i5 = 2;
var c = __c;
Where __c
, usw., sind generierte Variablen, die unsichtbar sind und für den Quellcode nicht zugänglich sind.where __c
, etc., are generated variables that are invisible and inaccessible to the source code. Beachten Sie, dass die Argumente für [0,0]
nur einmal ausgewertet werden und die Argumente für [1,2]
einmal ausgewertet werden, auch wenn Sie nie verwendet werden.Note that the arguments for [0,0]
are evaluated only once, and the arguments for [1,2]
are evaluated once even though they are never used.
AuflistungsinitialisiererCollection initializers
Ein Auflistungsinitialisierer gibt die Elemente einer Auflistung an.A collection initializer specifies the elements of a collection.
collection_initializer
: '{' element_initializer_list '}'
| '{' element_initializer_list ',' '}'
;
element_initializer_list
: element_initializer (',' element_initializer)*
;
element_initializer
: non_assignment_expression
| '{' expression_list '}'
;
expression_list
: expression (',' expression)*
;
Ein Auflistungsinitialisierer besteht aus einer Sequenz von Elementinitialisierern, die von {
-und- }
Token eingeschlossen und durch Kommas getrennt sind.A collection initializer consists of a sequence of element initializers, enclosed by {
and }
tokens and separated by commas. Jeder Elementinitialisierer gibt ein Element an, das dem aufzurufenden Auflistungs Objekt hinzugefügt werden soll, und besteht aus einer Liste von Ausdrücken, die von {
-und- }
Token eingeschlossen und durch Kommas getrennt sind.Each element initializer specifies an element to be added to the collection object being initialized, and consists of a list of expressions enclosed by {
and }
tokens and separated by commas. Ein Elementinitialisierer mit einem Ausdruck kann ohne geschweifte Klammern geschrieben werden, kann jedoch kein Zuweisungs Ausdruck sein, um Mehrdeutigkeit mit Member-Initialisierern zu vermeiden.A single-expression element initializer can be written without braces, but cannot then be an assignment expression, to avoid ambiguity with member initializers. Die non_assignment_expression Produktion ist in Expressiondefiniert.The non_assignment_expression production is defined in Expression.
Im folgenden finden Sie ein Beispiel für einen Objekt Erstellungs Ausdruck, der einen Auflistungsinitialisierer umfasst:The following is an example of an object creation expression that includes a collection initializer:
List<int> digits = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Das Auflistungs Objekt, auf das ein Auflistungsinitialisierer angewendet wird, muss einen Typ aufweisen, der implementiert, System.Collections.IEnumerable
oder ein Kompilierzeitfehler tritt auf.The collection object to which a collection initializer is applied must be of a type that implements System.Collections.IEnumerable
or a compile-time error occurs. Für jedes angegebene Element in der Reihenfolge ruft der sammlungsinitialisierer eine Add
Methode für das Zielobjekt mit der Ausdrucks Liste des elementinitialisierers als Argumentliste auf und wendet die normale Member-Suche-und Überladungs Auflösung für jeden Aufruf an.For each specified element in order, the collection initializer invokes an Add
method on the target object with the expression list of the element initializer as argument list, applying normal member lookup and overload resolution for each invocation. Folglich muss das Auflistungs Objekt über eine gültige Instanz-oder Erweiterungsmethode mit dem Namen Add
für jeden Elementinitialisierer verfügen.Thus, the collection object must have an applicable instance or extension method with the name Add
for each element initializer.
Die folgende Klasse stellt einen Kontakt mit einem Namen und einer Liste von Telefonnummern dar:The following class represents a contact with a name and a list of phone numbers:
public class Contact
{
string name;
List<string> phoneNumbers = new List<string>();
public string Name { get { return name; } set { name = value; } }
public List<string> PhoneNumbers { get { return phoneNumbers; } }
}
Eine List<Contact>
kann wie folgt erstellt und initialisiert werden:A List<Contact>
can be created and initialized as follows:
var contacts = new List<Contact> {
new Contact {
Name = "Chris Smith",
PhoneNumbers = { "206-555-0101", "425-882-8080" }
},
new Contact {
Name = "Bob Harris",
PhoneNumbers = { "650-555-0199" }
}
};
Dies hat die gleiche Wirkung wiewhich has the same effect as
var __clist = new List<Contact>();
Contact __c1 = new Contact();
__c1.Name = "Chris Smith";
__c1.PhoneNumbers.Add("206-555-0101");
__c1.PhoneNumbers.Add("425-882-8080");
__clist.Add(__c1);
Contact __c2 = new Contact();
__c2.Name = "Bob Harris";
__c2.PhoneNumbers.Add("650-555-0199");
__clist.Add(__c2);
var contacts = __clist;
dabei __clist
__c1
handelt es sich bei und __c2
um temporäre Variablen, die andernfalls unsichtbar und nicht zugänglich sind.where __clist
, __c1
and __c2
are temporary variables that are otherwise invisible and inaccessible.
Ausdrücke zum Erstellen von ArraysArray creation expressions
Eine array_creation_expression wird zum Erstellen einer neuen Instanz eines- array_type verwendet.An array_creation_expression is used to create a new instance of an array_type.
array_creation_expression
: 'new' non_array_type '[' expression_list ']' rank_specifier* array_initializer?
| 'new' array_type array_initializer
| 'new' rank_specifier array_initializer
;
Ein Array Erstellungs Ausdruck des ersten Formulars ordnet eine Array Instanz des Typs zu, der sich aus dem Löschen der einzelnen Ausdrücke aus der Ausdrucks Liste ergibt.An array creation expression of the first form allocates an array instance of the type that results from deleting each of the individual expressions from the expression list. Beispielsweise erzeugt der Ausdruck für die Array Erstellung new int[10,20]
eine Array Instanz vom Typ int[,]
, und der Ausdruck für die Array Erstellung new int[10][,]
erzeugt ein Array vom Typ int[][,]
.For example, the array creation expression new int[10,20]
produces an array instance of type int[,]
, and the array creation expression new int[10][,]
produces an array of type int[][,]
. Jeder Ausdruck in der Ausdrucks Liste muss vom Typ int
, uint
, oder sein long
ulong
oder implizit in einen oder mehrere dieser Typen konvertiert werden können.Each expression in the expression list must be of type int
, uint
, long
, or ulong
, or implicitly convertible to one or more of these types. Der Wert jedes Ausdrucks bestimmt die Länge der entsprechenden Dimension in der neu zugeordneten Array Instanz.The value of each expression determines the length of the corresponding dimension in the newly allocated array instance. Da die Länge einer Array Dimension nicht negativ sein muss, ist dies ein Kompilierzeitfehler, bei dem ein constant_expression mit einem negativen Wert in der Ausdrucks Liste vorliegt.Since the length of an array dimension must be nonnegative, it is a compile-time error to have a constant_expression with a negative value in the expression list.
Das Layout von Arrays ist nicht festgelegt, es sei denn, es ist ein unsicherer Kontext (unsichere Kontexte).Except in an unsafe context (Unsafe contexts), the layout of arrays is unspecified.
Wenn ein Array Erstellungs Ausdruck des ersten Formulars einen Arrayinitialisierer enthält, muss jeder Ausdruck in der Ausdrucks Liste eine Konstante sein, und die von der Ausdrucks Liste angegebenen Rang-und Dimensions Längen müssen mit denen des Arrayinitialisierers identisch sein.If an array creation expression of the first form includes an array initializer, each expression in the expression list must be a constant and the rank and dimension lengths specified by the expression list must match those of the array initializer.
In einem Array Erstellungs Ausdruck des zweiten oder dritten Formulars muss der Rang des angegebenen Arraytyps oder rangspezifizierers mit dem des Arrayinitialisierers identisch sein.In an array creation expression of the second or third form, the rank of the specified array type or rank specifier must match that of the array initializer. Die einzelnen Dimensions Längen werden von der Anzahl von Elementen in jeder der entsprechenden Schachtelungs Ebenen des Arrayinitialisierers abgeleitet.The individual dimension lengths are inferred from the number of elements in each of the corresponding nesting levels of the array initializer. Folglich ist der AusdruckThus, the expression
new int[,] {{0, 1}, {2, 3}, {4, 5}}
entspricht genauexactly corresponds to
new int[3, 2] {{0, 1}, {2, 3}, {4, 5}}
Ein Array Erstellungs Ausdruck des dritten Formulars wird als *implizit typisierter Array Erstellungs Ausdruck _ bezeichnet.An array creation expression of the third form is referred to as an *implicitly typed array creation expression _. Sie ähnelt dem zweiten Formular, mit dem Unterschied, dass der Elementtyp des Arrays nicht explizit angegeben wird, sondern als der am besten geeignete Typ (suchendes besten allgemeinen Typs eines Satzes von Ausdrücken) des Satzes von Ausdrücken im Arrayinitialisierer festgelegt ist.It is similar to the second form, except that the element type of the array is not explicitly given, but determined as the best common type (Finding the best common type of a set of expressions) of the set of expressions in the array initializer. Bei einem mehrdimensionalen Array, d. h. einer, bei dem der _rank_specifier * mindestens ein Komma enthält, besteht dieser Satz aus allen Ausdrücken, die in den array_initializer s gefunden wurden.For a multidimensional array, i.e., one where the _rank_specifier* contains at least one comma, this set comprises all expression s found in nested array_initializer s.
Arrayinitialisierer werden in arrayinitialisierernausführlicher beschrieben.Array initializers are described further in Array initializers.
Das Ergebnis der Auswertung eines Array Erstellungs Ausdrucks wird als Wert klassifiziert, nämlich als Verweis auf die neu zugeordnete Array Instanz.The result of evaluating an array creation expression is classified as a value, namely a reference to the newly allocated array instance. Die Lauf Zeit Verarbeitung eines Ausdrucks zur Array Erstellung besteht aus den folgenden Schritten:The run-time processing of an array creation expression consists of the following steps:
- Die Dimensions Längen Ausdrücke der expression_list werden in der Reihenfolge von links nach rechts ausgewertet.The dimension length expressions of the expression_list are evaluated in order, from left to right. Nach der Auswertung der einzelnen Ausdrücke wird eine implizite Konvertierung (implizite Konvertierungen) in einen der folgenden Typen ausgeführt:
int
,uint
,long
,ulong
.Following evaluation of each expression, an implicit conversion (Implicit conversions) to one of the following types is performed:int
,uint
,long
,ulong
. Der erste Typ in dieser Liste, für den eine implizite Konvertierung vorhanden ist, wird ausgewählt.The first type in this list for which an implicit conversion exists is chosen. Wenn die Auswertung eines Ausdrucks oder der nachfolgenden impliziten Konvertierung eine Ausnahme verursacht, werden keine weiteren Ausdrücke ausgewertet, und es werden keine weiteren Schritte ausgeführt.If evaluation of an expression or the subsequent implicit conversion causes an exception, then no further expressions are evaluated and no further steps are executed. - Die berechneten Werte für die Dimensions Längen werden wie folgt überprüft.The computed values for the dimension lengths are validated as follows. Wenn mindestens einer der-Werte kleiner als 0 (null) ist, wird eine ausgelöst,
System.OverflowException
und es werden keine weiteren Schritte ausgeführt.If one or more of the values are less than zero, aSystem.OverflowException
is thrown and no further steps are executed. - Eine Array Instanz mit den angegebenen Dimensions Längen ist zugeordnet.An array instance with the given dimension lengths is allocated. Wenn nicht genügend Arbeitsspeicher zur Verfügung steht, um die neue Instanz zuzuordnen, wird eine ausgelöst,
System.OutOfMemoryException
und es werden keine weiteren Schritte ausgeführt.If there is not enough memory available to allocate the new instance, aSystem.OutOfMemoryException
is thrown and no further steps are executed. - Alle Elemente der neuen Array Instanz werden mit ihren Standardwerten initialisiert (Standardwerte).All elements of the new array instance are initialized to their default values (Default values).
- Wenn der Ausdruck für die Array Erstellung einen Arrayinitialisierer enthält, wird jeder Ausdruck im Arrayinitialisierer ausgewertet und dem entsprechenden Array Element zugewiesen.If the array creation expression contains an array initializer, then each expression in the array initializer is evaluated and assigned to its corresponding array element. Die Auswertungen und Zuweisungen werden in der Reihenfolge ausgeführt, in der die Ausdrücke in den Arrayinitialisierer geschrieben werden – mit anderen Worten, Elemente werden in steigender Index Reihenfolge initialisiert, wobei die äußerste Rechte Dimension zuerst zunimmt.The evaluations and assignments are performed in the order the expressions are written in the array initializer—in other words, elements are initialized in increasing index order, with the rightmost dimension increasing first. Wenn die Auswertung eines angegebenen Ausdrucks oder der nachfolgenden Zuweisung zum entsprechenden Array Element eine Ausnahme auslöst, werden keine weiteren Elemente initialisiert (und die restlichen Elemente haben daher ihre Standardwerte).If evaluation of a given expression or the subsequent assignment to the corresponding array element causes an exception, then no further elements are initialized (and the remaining elements will thus have their default values).
Ein Array Erstellungs Ausdruck ermöglicht die Instanziierung eines Arrays mit Elementen eines Arraytyps, aber die Elemente eines solchen Arrays müssen manuell initialisiert werden.An array creation expression permits instantiation of an array with elements of an array type, but the elements of such an array must be manually initialized. Beispielsweise ist die-AnweisungFor example, the statement
int[][] a = new int[100][];
erstellt ein eindimensionales Array mit 100 Elementen vom Typ int[]
.creates a single-dimensional array with 100 elements of type int[]
. Der Anfangswert jedes Elements ist null
.The initial value of each element is null
. Es ist nicht möglich, dass derselbe Array Erstellungs Ausdruck auch die Unterarrays und die-Anweisung instanziiert.It is not possible for the same array creation expression to also instantiate the sub-arrays, and the statement
int[][] a = new int[100][5]; // Error
führt zu einem Kompilierzeitfehler.results in a compile-time error. Die Instanziierung der Unterarrays muss stattdessen manuell ausgeführt werden, wie inInstantiation of the sub-arrays must instead be performed manually, as in
int[][] a = new int[100][];
for (int i = 0; i < 100; i++) a[i] = new int[5];
Wenn ein Array von Arrays eine "rechteckige" Form hat, d. h., wenn die Teil Arrays die gleiche Länge haben, ist es effizienter, ein mehrdimensionales Array zu verwenden.When an array of arrays has a "rectangular" shape, that is when the sub-arrays are all of the same length, it is more efficient to use a multi-dimensional array. Im obigen Beispiel erstellt die Instanziierung des Arrays von Arrays 101 Objekte – ein äußeres Array und 100 Teil Arrays.In the example above, instantiation of the array of arrays creates 101 objects—one outer array and 100 sub-arrays. Im Gegensatz dazuIn contrast,
int[,] = new int[100, 5];
erstellt nur ein einzelnes-Objekt, ein zweidimensionales Array und erreicht die Zuordnung in einer einzelnen Anweisung.creates only a single object, a two-dimensional array, and accomplishes the allocation in a single statement.
Im folgenden finden Sie Beispiele für implizit typisierte Array Erstellungs Ausdrücke:The following are examples of implicitly typed array creation expressions:
var a = new[] { 1, 10, 100, 1000 }; // int[]
var b = new[] { 1, 1.5, 2, 2.5 }; // double[]
var c = new[,] { { "hello", null }, { "world", "!" } }; // string[,]
var d = new[] { 1, "one", 2, "two" }; // Error
Der letzte Ausdruck verursacht einen Kompilierzeitfehler, weil weder int
noch string
implizit in den anderen konvertiert werden kann, sodass es keinen optimalen allgemeinen Typ gibt.The last expression causes a compile-time error because neither int
nor string
is implicitly convertible to the other, and so there is no best common type. In diesem Fall muss ein explizit typisierter Array Erstellungs Ausdruck verwendet werden, z. b. die Angabe des Typs object[]
.An explicitly typed array creation expression must be used in this case, for example specifying the type to be object[]
. Alternativ kann eines der Elemente in einen allgemeinen Basistyp umgewandelt werden, der dann zum abzurufenden Elementtyp wird.Alternatively, one of the elements can be cast to a common base type, which would then become the inferred element type.
Implizit typisierte Array Erstellungs Ausdrücke können mit anonymen Objektinitialisierern (anonymen Objekt Erstellungs Ausdrücken) kombiniert werden, um anonym typisierte Datenstrukturen zu erstellen.Implicitly typed array creation expressions can be combined with anonymous object initializers (Anonymous object creation expressions) to create anonymously typed data structures. Beispiel:For example:
var contacts = new[] {
new {
Name = "Chris Smith",
PhoneNumbers = new[] { "206-555-0101", "425-882-8080" }
},
new {
Name = "Bob Harris",
PhoneNumbers = new[] { "650-555-0199" }
}
};
Delegatenerstellungs AusdrückeDelegate creation expressions
Eine delegate_creation_expression wird zum Erstellen einer neuen Instanz einer delegate_type verwendet.A delegate_creation_expression is used to create a new instance of a delegate_type.
delegate_creation_expression
: 'new' delegate_type '(' expression ')'
;
Das Argument eines delegaterstellungs-Ausdrucks muss eine Methoden Gruppe, eine anonyme Funktion oder ein Wert entweder der Kompilier Zeittyp dynamic
oder ein delegate_type sein.The argument of a delegate creation expression must be a method group, an anonymous function or a value of either the compile time type dynamic
or a delegate_type. Wenn das Argument eine Methoden Gruppe ist, identifiziert es die-Methode und für eine Instanzmethode das-Objekt, für das ein Delegat erstellt werden soll.If the argument is a method group, it identifies the method and, for an instance method, the object for which to create a delegate. Wenn das Argument eine anonyme Funktion ist, werden die Parameter und der Methoden Text des delegatziels direkt definiert.If the argument is an anonymous function it directly defines the parameters and method body of the delegate target. Wenn das-Argument ein Wert ist, wird eine Delegatinstanz identifiziert, von der eine Kopie erstellt werden soll.If the argument is a value it identifies a delegate instance of which to create a copy.
Wenn der Ausdruck den Kompilier Zeittyp aufweist dynamic
, wird der delegate_creation_expression dynamisch gebunden (dynamische Bindung), und die unten aufgeführten Regeln werden zur Laufzeit mit dem Lauf Zeittyp des Ausdrucks angewendet.If the expression has the compile-time type dynamic
, the delegate_creation_expression is dynamically bound (Dynamic binding), and the rules below are applied at run-time using the run-time type of the expression. Andernfalls werden die Regeln zur Kompilierzeit angewendet.Otherwise the rules are applied at compile-time.
Die Bindungs Zeit Verarbeitung einer delegate_creation_expression der Form new D(E)
, wobei D
ein delegate_type und E
ein Ausdruck ist, besteht aus den folgenden Schritten:The binding-time processing of a delegate_creation_expression of the form new D(E)
, where D
is a delegate_type and E
is an expression, consists of the following steps:
- Wenn
E
eine Methoden Gruppe ist, wird der delegaterstellungs-Ausdruck auf die gleiche Weise wie eine Methoden Gruppen Konvertierung (Methoden Gruppen Konvertierungen) vonE
in verarbeitetD
.IfE
is a method group, the delegate creation expression is processed in the same way as a method group conversion (Method group conversions) fromE
toD
. - Wenn
E
eine anonyme Funktion ist, wird der delegaterstellungs-Ausdruck auf die gleiche Weise wie eine anonyme Funktions Konvertierung (Anonyme Funktions Konvertierungen) vonE
in verarbeitetD
.IfE
is an anonymous function, the delegate creation expression is processed in the same way as an anonymous function conversion (Anonymous function conversions) fromE
toD
. - Wenn
E
ein-Wert ist,E
muss kompatibel (Delegatdeklarationen) mit seinD
, und das Ergebnis ist ein Verweis auf einen neu erstellten Delegaten vom Typ, derD
auf dieselbe Aufruf Liste wie verweistE
.IfE
is a value,E
must be compatible (Delegate declarations) withD
, and the result is a reference to a newly created delegate of typeD
that refers to the same invocation list asE
. WennE
nicht mit kompatibel istD
, tritt ein Kompilierzeitfehler auf.IfE
is not compatible withD
, a compile-time error occurs.
Die Lauf Zeit Verarbeitung einer delegate_creation_expression der Form new D(E)
, wobei D
ein delegate_type und E
ein Ausdruck ist, besteht aus den folgenden Schritten:The run-time processing of a delegate_creation_expression of the form new D(E)
, where D
is a delegate_type and E
is an expression, consists of the following steps:
- Wenn
E
eine Methoden Gruppe ist, wird der delegaterstellungs-Ausdruck als Methoden Gruppen Konvertierung (Methoden Gruppen Konvertierungen) vonE
in ausgewertetD
.IfE
is a method group, the delegate creation expression is evaluated as a method group conversion (Method group conversions) fromE
toD
. - Wenn
E
eine anonyme Funktion ist, wird die Delegaterstellung als anonyme Funktions Konvertierung vonE
in ausgewertetD
(Anonyme Funktions Konvertierungen).IfE
is an anonymous function, the delegate creation is evaluated as an anonymous function conversion fromE
toD
(Anonymous function conversions). - Wenn
E
ein Wert eines delegate_type ist:IfE
is a value of a delegate_type:E
wird ausgewertet.E
is evaluated. Wenn diese Auswertung eine Ausnahme verursacht, werden keine weiteren Schritte ausgeführt.If this evaluation causes an exception, no further steps are executed.- Wenn der Wert von
E
istnull
, wird eine ausgelöst,System.NullReferenceException
und es werden keine weiteren Schritte ausgeführt.If the value ofE
isnull
, aSystem.NullReferenceException
is thrown and no further steps are executed. - Eine neue Instanz des Delegattyps
D
wird zugewiesen.A new instance of the delegate typeD
is allocated. Wenn nicht genügend Arbeitsspeicher zur Verfügung steht, um die neue Instanz zuzuordnen, wird eine ausgelöst,System.OutOfMemoryException
und es werden keine weiteren Schritte ausgeführt.If there is not enough memory available to allocate the new instance, aSystem.OutOfMemoryException
is thrown and no further steps are executed. - Die neue Delegatinstanz wird mit der gleichen Aufruf Liste initialisiert wie die Delegatinstanz, die von angegeben wird
E
.The new delegate instance is initialized with the same invocation list as the delegate instance given byE
.
Die Aufruf Liste eines Delegaten wird bestimmt, wenn der Delegat instanziiert wird, und wird dann für die gesamte Lebensdauer des Delegaten konstant bleiben.The invocation list of a delegate is determined when the delegate is instantiated and then remains constant for the entire lifetime of the delegate. Anders ausgedrückt: Es ist nicht möglich, die Ziel Aufruf baren Entitäten eines Delegaten zu ändern, nachdem er erstellt wurde.In other words, it is not possible to change the target callable entities of a delegate once it has been created. Wenn zwei Delegaten kombiniert werden oder eine aus einer anderen entfernt wird (Delegatdeklarationen), ergibt sich ein neuer Delegat. der Inhalt eines vorhandenen Delegaten wurde nicht geändert.When two delegates are combined or one is removed from another (Delegate declarations), a new delegate results; no existing delegate has its contents changed.
Es ist nicht möglich, einen Delegaten zu erstellen, der auf eine Eigenschaft, einen Indexer, einen benutzerdefinierten Operator, einen Instanzkonstruktor, einen Dekonstruktor oder einen statischen Konstruktor verweist.It is not possible to create a delegate that refers to a property, indexer, user-defined operator, instance constructor, destructor, or static constructor.
Wie oben beschrieben, wird beim Erstellen eines Delegaten aus einer Methoden Gruppe die Liste der formalen Parameter und der Rückgabetyp des Delegaten bestimmt, welche der überladenen Methoden ausgewählt werden sollen.As described above, when a delegate is created from a method group, the formal parameter list and return type of the delegate determine which of the overloaded methods to select. Im BeispielIn the example
delegate double DoubleFunc(double x);
class A
{
DoubleFunc f = new DoubleFunc(Square);
static float Square(float x) {
return x * x;
}
static double Square(double x) {
return x * x;
}
}
Das- A.f
Feld wird mit einem Delegaten initialisiert, der sich auf die zweite Methode bezieht, Square
da diese Methode exakt mit der formalen Parameterliste und dem Rückgabetyp von übereinstimmt DoubleFunc
.the A.f
field is initialized with a delegate that refers to the second Square
method because that method exactly matches the formal parameter list and return type of DoubleFunc
. Wenn die zweite Square
Methode nicht vorhanden wäre, wäre ein Kompilierzeitfehler aufgetreten.Had the second Square
method not been present, a compile-time error would have occurred.
Ausdrücke zum Erstellen anonymer ObjekteAnonymous object creation expressions
Ein anonymous_object_creation_expression wird zum Erstellen eines Objekts eines anonymen Typs verwendet.An anonymous_object_creation_expression is used to create an object of an anonymous type.
anonymous_object_creation_expression
: 'new' anonymous_object_initializer
;
anonymous_object_initializer
: '{' member_declarator_list? '}'
| '{' member_declarator_list ',' '}'
;
member_declarator_list
: member_declarator (',' member_declarator)*
;
member_declarator
: simple_name
| member_access
| base_access
| null_conditional_member_access
| identifier '=' expression
;
Ein Anonymer Objektinitialisierer deklariert einen anonymen Typ und gibt eine Instanz dieses Typs zurück.An anonymous object initializer declares an anonymous type and returns an instance of that type. Ein anonymer Typ ist ein namenloser Klassentyp, der direkt von erbt object
.An anonymous type is a nameless class type that inherits directly from object
. Die Member eines anonymen Typs sind eine Sequenz von schreibgeschützten Eigenschaften, die vom anonymen Objektinitialisierer abgeleitet werden, um eine Instanz des Typs zu erstellen.The members of an anonymous type are a sequence of read-only properties inferred from the anonymous object initializer used to create an instance of the type. Genauer gesagt: ein Anonymer Objektinitialisierer des FormularsSpecifically, an anonymous object initializer of the form
new { p1 = e1, p2 = e2, ..., pn = en }
deklariert einen anonymen Typ des Formulars.declares an anonymous type of the form
class __Anonymous1
{
private readonly T1 f1;
private readonly T2 f2;
...
private readonly Tn fn;
public __Anonymous1(T1 a1, T2 a2, ..., Tn an) {
f1 = a1;
f2 = a2;
...
fn = an;
}
public T1 p1 { get { return f1; } }
public T2 p2 { get { return f2; } }
...
public Tn pn { get { return fn; } }
public override bool Equals(object __o) { ... }
public override int GetHashCode() { ... }
}
wobei jede Tx
der Typen des entsprechenden Ausdrucks ist ex
.where each Tx
is the type of the corresponding expression ex
. Der Ausdruck, der in einem member_declarator verwendet wird, muss einen Typ aufweisen.The expression used in a member_declarator must have a type. Daher ist es ein Kompilierzeitfehler für einen Ausdruck in einer member_declarator NULL oder eine anonyme Funktion zu sein.Thus, it is a compile-time error for an expression in a member_declarator to be null or an anonymous function. Es ist auch ein Kompilierzeitfehler, wenn der Ausdruck einen unsicheren Typ hat.It is also a compile-time error for the expression to have an unsafe type.
Die Namen eines anonymen Typs und des-Parameters für die zugehörige- Equals
Methode werden vom Compiler automatisch generiert, und im Programmtext kann nicht auf Sie verwiesen werden.The names of an anonymous type and of the parameter to its Equals
method are automatically generated by the compiler and cannot be referenced in program text.
Innerhalb desselben Programms werden zwei anonyme Objektinitialisierer, die eine Sequenz von Eigenschaften mit denselben Namen und Kompilierzeit Typen in derselben Reihenfolge angeben, Instanzen desselben anonymen Typs erstellen.Within the same program, two anonymous object initializers that specify a sequence of properties of the same names and compile-time types in the same order will produce instances of the same anonymous type.
Im BeispielIn the example
var p1 = new { Name = "Lawnmower", Price = 495.00 };
var p2 = new { Name = "Shovel", Price = 26.95 };
p1 = p2;
die Zuweisung in der letzten Zeile ist zulässig, da p1
und p2
denselben anonymen Typ haben.the assignment on the last line is permitted because p1
and p2
are of the same anonymous type.
Die Equals
-Methode und die- GetHashcode
Methode für anonyme Typen überschreiben die von geerbten Methoden object
und werden im Hinblick auf die Equals
und GetHashcode
der Eigenschaften definiert, sodass zwei Instanzen desselben anonymen Typs nur dann gleich sind, wenn alle Eigenschaften gleich sind.The Equals
and GetHashcode
methods on anonymous types override the methods inherited from object
, and are defined in terms of the Equals
and GetHashcode
of the properties, so that two instances of the same anonymous type are equal if and only if all their properties are equal.
Ein Element Deklarator kann mit einem einfachen Namen (Typrückschluss), einem Element Zugriff (Kompilierzeit Überprüfung der dynamischen Überladungs Auflösung), einem Basis Zugriff (Basis Zugriff) oder einem NULL bedingten Member-Zugriff (null bedingte Ausdrücke als Projektions Initialisierer) abgekürzt werden.A member declarator can be abbreviated to a simple name (Type inference), a member access (Compile-time checking of dynamic overload resolution), a base access (Base access) or a null-conditional member access (Null-conditional expressions as projection initializers). Dies wird als Projektions Initialisierer bezeichnet und ist eine Abkürzung für eine Deklaration von und die Zuweisung zu einer Eigenschaft mit demselben Namen.This is called a projection initializer and is shorthand for a declaration of and assignment to a property with the same name. Insbesondere Member-Deklaratoren der FormulareSpecifically, member declarators of the forms
identifier
expr.identifier
entsprechen genau den folgenden:are precisely equivalent to the following, respectively:
identifier = identifier
identifier = expr.identifier
Folglich wählt der Bezeichner in einem Projektions Initialisierer sowohl den Wert als auch das Feld oder die Eigenschaft aus, dem der Wert zugewiesen wird.Thus, in a projection initializer the identifier selects both the value and the field or property to which the value is assigned. Intuitiv projiziert ein Projektions Initialisierer nicht nur einen Wert, sondern auch den Namen des Werts.Intuitively, a projection initializer projects not just a value, but also the name of the value.
Der typeof-OperatorThe typeof operator
Der- typeof
Operator wird zum Abrufen des- System.Type
Objekts für einen Typ verwendet.The typeof
operator is used to obtain the System.Type
object for a type.
typeof_expression
: 'typeof' '(' type ')'
| 'typeof' '(' unbound_type_name ')'
| 'typeof' '(' 'void' ')'
;
unbound_type_name
: identifier generic_dimension_specifier?
| identifier '::' identifier generic_dimension_specifier?
| unbound_type_name '.' identifier generic_dimension_specifier?
;
generic_dimension_specifier
: '<' comma* '>'
;
comma
: ','
;
Die erste Form typeof_expression besteht aus einem typeof
Schlüsselwort, gefolgt von einem Typ in Klammern.The first form of typeof_expression consists of a typeof
keyword followed by a parenthesized type. Das Ergebnis eines Ausdrucks dieses Formulars ist das- System.Type
Objekt für den jeweiligen Typ.The result of an expression of this form is the System.Type
object for the indicated type. Es ist nur ein- System.Type
Objekt für einen bestimmten Typ vorhanden.There is only one System.Type
object for any given type. Dies bedeutet, dass für einen T
Typ typeof(T) == typeof(T)
immer true ist.This means that for a type T
, typeof(T) == typeof(T)
is always true. Der Typ darf nicht sein dynamic
.The type cannot be dynamic
.
Die zweite Form von typeof_expression besteht aus einem typeof
Schlüsselwort, gefolgt von einer unbound_type_name in Klammern.The second form of typeof_expression consists of a typeof
keyword followed by a parenthesized unbound_type_name. Ein- unbound_type_name ähnelt einem TYPE_NAME (Namespace und Typnamen), mit dem Unterschied, dass ein unbound_type_name generic_dimension_specifier s enthält, in denen eine TYPE_NAME type_argument_list s enthält.An unbound_type_name is very similar to a type_name (Namespace and type names) except that an unbound_type_name contains generic_dimension_specifier s where a type_name contains type_argument_list s. Wenn der Operand einer typeof_expression eine Sequenz von Token ist, die die Grammatiken von unbound_type_name und TYPE_NAME erfüllt, d. h., wenn weder ein generic_dimension_specifier noch ein type_argument_list enthalten ist, wird die Sequenz der Token als TYPE_NAME betrachtet.When the operand of a typeof_expression is a sequence of tokens that satisfies the grammars of both unbound_type_name and type_name, namely when it contains neither a generic_dimension_specifier nor a type_argument_list, the sequence of tokens is considered to be a type_name. Die Bedeutung eines unbound_type_name wird wie folgt bestimmt:The meaning of an unbound_type_name is determined as follows:
- Konvertieren Sie die Sequenz von Token in eine TYPE_NAME , indem Sie alle generic_dimension_specifier durch eine type_argument_list ersetzen, die dieselbe Anzahl von Kommas und das Schlüsselwort
object
wie jedes type_argument hat.Convert the sequence of tokens to a type_name by replacing each generic_dimension_specifier with a type_argument_list having the same number of commas and the keywordobject
as each type_argument. - Werten Sie die resultierende TYPE_NAME aus, während alle Typparameter Einschränkungen ignoriert werden.Evaluate the resulting type_name, while ignoring all type parameter constraints.
- Der unbound_type_name wird in den ungebundenen generischen Typ aufgelöst, der dem resultierenden konstruierten Typ zugeordnet ist (gebundene und ungebundene Typen).The unbound_type_name resolves to the unbound generic type associated with the resulting constructed type (Bound and unbound types).
Das Ergebnis des typeof_expression ist das- System.Type
Objekt für den resultierenden ungebundenen generischen Typ.The result of the typeof_expression is the System.Type
object for the resulting unbound generic type.
Die dritte Form von typeof_expression besteht aus einem typeof
Schlüsselwort, gefolgt von einem void
Schlüsselwort in Klammern.The third form of typeof_expression consists of a typeof
keyword followed by a parenthesized void
keyword. Das Ergebnis eines Ausdrucks dieses Formulars ist das System.Type
Objekt, das das Fehlen eines Typs darstellt.The result of an expression of this form is the System.Type
object that represents the absence of a type. Das von zurückgegebene Typobjekt unter typeof(void)
scheidet sich vom Typobjekt, das für einen beliebigen Typ zurückgegeben wurde.The type object returned by typeof(void)
is distinct from the type object returned for any type. Dieses besondere Typobjekt ist nützlich in Klassenbibliotheken, die die Reflektion auf Methoden in der Sprache zulassen, wobei diese Methoden eine Möglichkeit haben möchten, den Rückgabetyp jeder Methode, einschließlich void-Methoden, mit einer Instanz von darzustellen System.Type
.This special type object is useful in class libraries that allow reflection onto methods in the language, where those methods wish to have a way to represent the return type of any method, including void methods, with an instance of System.Type
.
Der- typeof
Operator kann für einen Typparameter verwendet werden.The typeof
operator can be used on a type parameter. Das Ergebnis ist das- System.Type
Objekt für den Lauf Zeittyp, der an den Typparameter gebunden wurde.The result is the System.Type
object for the run-time type that was bound to the type parameter. Der typeof
Operator kann auch für einen konstruierten Typ oder einen ungebundenen generischen Typ (gebundene und ungebundene Typen) verwendet werden.The typeof
operator can also be used on a constructed type or an unbound generic type (Bound and unbound types). Das- System.Type
Objekt für einen ungebundenen generischen Typ ist nicht mit dem- System.Type
Objekt des Instanztyps identisch.The System.Type
object for an unbound generic type is not the same as the System.Type
object of the instance type. Der Instanztyp ist zur Laufzeit immer ein geschlossener konstruierter Typ, sodass System.Type
das Objekt von den verwendeten Lauf Zeittyp Argumenten abhängt, während der ungebundene generische Typ keine Typargumente aufweist.The instance type is always a closed constructed type at run-time so its System.Type
object depends on the run-time type arguments in use, while the unbound generic type has no type arguments.
Das BeispielThe example
using System;
class X<T>
{
public static void PrintTypes() {
Type[] t = {
typeof(int),
typeof(System.Int32),
typeof(string),
typeof(double[]),
typeof(void),
typeof(T),
typeof(X<T>),
typeof(X<X<T>>),
typeof(X<>)
};
for (int i = 0; i < t.Length; i++) {
Console.WriteLine(t[i]);
}
}
}
class Test
{
static void Main() {
X<int>.PrintTypes();
}
}
erzeugt die folgende Ausgabe:produces the following output:
System.Int32
System.Int32
System.String
System.Double[]
System.Void
System.Int32
X`1[System.Int32]
X`1[X`1[System.Int32]]
X`1[T]
Beachten Sie, dass int
und System.Int32
denselben Typ haben.Note that int
and System.Int32
are the same type.
Beachten Sie auch, dass das Ergebnis von typeof(X<>)
nicht vom Typargument abhängt, sondern vom Ergebnis von typeof(X<T>)
.Also note that the result of typeof(X<>)
does not depend on the type argument but the result of typeof(X<T>)
does.
Checked- und Unchecked-OperatorenThe checked and unchecked operators
Die checked
unchecked
Operatoren und werden verwendet, um den Überlauf Überprüfungs Kontext für arithmetische Operationen und Konvertierungen im ganzzahligen Typ zu steuern.The checked
and unchecked
operators are used to control the overflow checking context for integral-type arithmetic operations and conversions.
checked_expression
: 'checked' '(' expression ')'
;
unchecked_expression
: 'unchecked' '(' expression ')'
;
Der checked
Operator wertet den enthaltenen Ausdruck in einem überprüften Kontext aus, und der unchecked
Operator wertet den enthaltenen Ausdruck in einem nicht überprüften Kontext aus.The checked
operator evaluates the contained expression in a checked context, and the unchecked
operator evaluates the contained expression in an unchecked context. Ein checked_expression oder unchecked_expression entspricht genau einem parenthesized_expression (in Klammern Klammern), mit dem Unterschied, dass der enthaltene Ausdruck im angegebenen Überlauf Prüfungs Kontext ausgewertet wird.A checked_expression or unchecked_expression corresponds exactly to a parenthesized_expression (Parenthesized expressions), except that the contained expression is evaluated in the given overflow checking context.
Der Überlauf Überprüfungs Kontext kann auch durch die checked
-und- unchecked
Anweisungen (dieaktivierten und deaktivierten Anweisungen) gesteuert werden.The overflow checking context can also be controlled through the checked
and unchecked
statements (The checked and unchecked statements).
Die folgenden Vorgänge wirken sich auf den Überlauf Prüfungs Kontext aus, der von den checked
unchecked
Operatoren und und-Anweisungen festgelegt wird:The following operations are affected by the overflow checking context established by the checked
and unchecked
operators and statements:
- Der vordefinierte
++
und--
unäre Operator (postfix-Inkrement-und Dekrementoperatoren und Präfix Inkrement-und Dekrementoperatoren), wenn der Operand ein ganzzahliger Typ ist.The predefined++
and--
unary operators (Postfix increment and decrement operators and Prefix increment and decrement operators), when the operand is of an integral type. - Der vordefinierte
-
unäre Operator (unärer Minus Operator), wenn der Operand ein ganzzahliger Typ ist.The predefined-
unary operator (Unary minus operator), when the operand is of an integral type. - Die vordefinierten
+
-
*
Operatoren,, und/
(arithmetische Operatoren), wenn beide Operanden ganzzahlige Typen sind.The predefined+
,-
,*
, and/
binary operators (Arithmetic operators), when both operands are of integral types. - Explizite numerische Konvertierungen (explizite numerische Konvertierungen) von einem ganzzahligen Typ in einen anderen ganzzahligen Typ oder von
float
oder in einen ganzzahligendouble
Typ.Explicit numeric conversions (Explicit numeric conversions) from one integral type to another integral type, or fromfloat
ordouble
to an integral type.
Wenn eine der obigen Vorgänge ein Ergebnis erzeugt, das zu groß für die Darstellung im Zieltyp ist, steuert der Kontext, in dem der Vorgang ausgeführt wird, das resultierende Verhalten:When one of the above operations produce a result that is too large to represent in the destination type, the context in which the operation is performed controls the resulting behavior:
- In einem
checked
Kontext tritt ein Kompilierzeitfehler auf, wenn es sich bei dem Vorgang um einen konstanten Ausdruck (Konstante Ausdrücke) handelt.In achecked
context, if the operation is a constant expression (Constant expressions), a compile-time error occurs. Andernfalls wird eine ausgelöst, wenn der Vorgang zur Laufzeit ausgeführt wirdSystem.OverflowException
.Otherwise, when the operation is performed at run-time, aSystem.OverflowException
is thrown. - In einem
unchecked
Kontext wird das Ergebnis abgeschnitten, indem alle höherwertigen Bits verworfen werden, die nicht in den Zieltyp passen.In anunchecked
context, the result is truncated by discarding any high-order bits that do not fit in the destination type.
Für nicht konstante Ausdrücke (Ausdrücke, die zur Laufzeit ausgewertet werden), die nicht von einem checked
or- unchecked
Operator oder-Anweisungen eingeschlossen sind, ist der Standardkontext der Überlauf Überprüfung, unchecked
es sei denn, externe Faktoren (z. b. compilerswitches und Konfiguration der Ausführungsumgebung) werden zur checked
Auswertung aufgerufen.For non-constant expressions (expressions that are evaluated at run-time) that are not enclosed by any checked
or unchecked
operators or statements, the default overflow checking context is unchecked
unless external factors (such as compiler switches and execution environment configuration) call for checked
evaluation.
Für konstante Ausdrücke (Ausdrücke, die zur Kompilierzeit vollständig ausgewertet werden können) ist der Standardkontext der Überlauf Überprüfung immer checked
.For constant expressions (expressions that can be fully evaluated at compile-time), the default overflow checking context is always checked
. Wenn ein konstanter Ausdruck nicht explizit in einem Kontext abgelegt wird unchecked
, verursachen über Flüsse, die während der Kompilierzeit Auswertung des Ausdrucks auftreten, immer Kompilierzeitfehler.Unless a constant expression is explicitly placed in an unchecked
context, overflows that occur during the compile-time evaluation of the expression always cause compile-time errors.
Der Text einer anonymen Funktion ist nicht von- checked
oder- unchecked
Kontexten betroffen, in denen die anonyme Funktion auftritt.The body of an anonymous function is not affected by checked
or unchecked
contexts in which the anonymous function occurs.
Im BeispielIn the example
class Test
{
static readonly int x = 1000000;
static readonly int y = 1000000;
static int F() {
return checked(x * y); // Throws OverflowException
}
static int G() {
return unchecked(x * y); // Returns -727379968
}
static int H() {
return x * y; // Depends on default
}
}
Es werden keine Kompilierzeitfehler gemeldet, da keiner der Ausdrücke zur Kompilierzeit ausgewertet werden kann.no compile-time errors are reported since neither of the expressions can be evaluated at compile-time. Zur Laufzeit löst die F
Methode eine aus System.OverflowException
, und die G
Methode gibt-727379968 (die unteren 32 Bits des Ergebnisses außerhalb des gültigen Bereichs) zurück.At run-time, the F
method throws a System.OverflowException
, and the G
method returns -727379968 (the lower 32 bits of the out-of-range result). Das Verhalten der- H
Methode hängt vom Standardkontext der Überlauf Überprüfung für die Kompilierung ab, ist jedoch entweder identisch mit F
oder gleich G
.The behavior of the H
method depends on the default overflow checking context for the compilation, but it is either the same as F
or the same as G
.
Im BeispielIn the example
class Test
{
const int x = 1000000;
const int y = 1000000;
static int F() {
return checked(x * y); // Compile error, overflow
}
static int G() {
return unchecked(x * y); // Returns -727379968
}
static int H() {
return x * y; // Compile error, overflow
}
}
die Überläufe, die beim Auswerten der Konstanten Ausdrücke in auftreten F
und H
bewirken, dass Kompilierzeitfehler gemeldet werden, weil die Ausdrücke in einem Kontext ausgewertet werden checked
.the overflows that occur when evaluating the constant expressions in F
and H
cause compile-time errors to be reported because the expressions are evaluated in a checked
context. Ein Überlauf tritt auch auf, wenn der Konstante Ausdruck in ausgewertet wird G
, aber da die Auswertung in einem Kontext stattfindet unchecked
, wird der Überlauf nicht gemeldet.An overflow also occurs when evaluating the constant expression in G
, but since the evaluation takes place in an unchecked
context, the overflow is not reported.
Die checked
unchecked
Operatoren und wirken sich nur auf den Überlauf Überprüfungs Kontext für die Vorgänge aus, die in den (
Token "" und "" textuell enthalten sind )
.The checked
and unchecked
operators only affect the overflow checking context for those operations that are textually contained within the "(
" and ")
" tokens. Die Operatoren haben keine Auswirkung auf Funktionsmember, die als Ergebnis der Auswertung des enthaltenen Ausdrucks aufgerufen werden.The operators have no effect on function members that are invoked as a result of evaluating the contained expression. Im BeispielIn the example
class Test
{
static int Multiply(int x, int y) {
return x * y;
}
static int F() {
return checked(Multiply(1000000, 1000000));
}
}
die Verwendung von checked
in F
hat keine Auswirkung auf die Auswertung von x * y
in Multiply
, daher x * y
wird im Standardkontext der Überlauf Überprüfung ausgewertet.the use of checked
in F
does not affect the evaluation of x * y
in Multiply
, so x * y
is evaluated in the default overflow checking context.
Der- unchecked
Operator ist praktisch, wenn Konstanten der ganzzahligen Typen mit Vorzeichen in hexadezimal Notation geschrieben werden.The unchecked
operator is convenient when writing constants of the signed integral types in hexadecimal notation. Beispiel:For example:
class Test
{
public const int AllBits = unchecked((int)0xFFFFFFFF);
public const int HighBit = unchecked((int)0x80000000);
}
Beide hexadezimal Konstanten oben sind vom Typ uint
.Both of the hexadecimal constants above are of type uint
. Da die Konstanten int
ohne den-Operator außerhalb des Bereichs liegen unchecked
, würden die Umwandlungen in int
Kompilierzeitfehler verursachen.Because the constants are outside the int
range, without the unchecked
operator, the casts to int
would produce compile-time errors.
checked
Mit den unchecked
Operatoren und und Anweisungen können Programmierer bestimmte Aspekte einiger numerischer Berechnungen steuern.The checked
and unchecked
operators and statements allow programmers to control certain aspects of some numeric calculations. Das Verhalten einiger numerischer Operatoren hängt jedoch von den Datentypen ihrer Operanden ab.However, the behavior of some numeric operators depends on their operands' data types. Beispielsweise führt die Multiplikation von zwei Dezimalzahlen immer zu einer Ausnahme bei einem Überlauf, auch innerhalb eines expliziten unchecked
Konstrukts.For example, multiplying two decimals always results in an exception on overflow even within an explicitly unchecked
construct. Analog dazu führt das Multiplizieren von zwei Gleit Komma zahlen niemals zu einer Ausnahme bei einem Überlauf, auch innerhalb eines expliziten checked
AufbausSimilarly, multiplying two floats never results in an exception on overflow even within an explicitly checked
construct. Außerdem sind andere Operatoren nie von dem Überprüfungs Modus betroffen, ob Standard oder explizit.In addition, other operators are never affected by the mode of checking, whether default or explicit.
Standardwert AusdrückeDefault value expressions
Ein Standardwert Ausdruck wird zum Abrufen des Standardwerts (Standardwerte) eines Typs verwendet.A default value expression is used to obtain the default value (Default values) of a type. In der Regel wird ein Standardwert Ausdruck für Typparameter verwendet, da möglicherweise nicht bekannt ist, ob der Typparameter ein Werttyp oder ein Verweistyp ist.Typically a default value expression is used for type parameters, since it may not be known if the type parameter is a value type or a reference type. (Es ist keine Konvertierung vom null
Literaltyp zu einem Typparameter vorhanden, es sei denn, der Typparameter ist ein Referenztyp.)(No conversion exists from the null
literal to a type parameter unless the type parameter is known to be a reference type.)
default_value_expression
: 'default' '(' type ')'
;
Wenn der Typ in einem default_value_expression zur Laufzeit als Verweistyp ausgewertet wird, wird das Ergebnis null
in diesen Typ konvertiert.If the type in a default_value_expression evaluates at run-time to a reference type, the result is null
converted to that type. Wenn der Typ in einer default_value_expression zur Laufzeit auf einen Werttyp ausgewertet wird, ist das Ergebnis der Standardwert der value_type(Standardkonstruktoren).If the type in a default_value_expression evaluates at run-time to a value type, the result is the value_type's default value (Default constructors).
Ein default_value_expression ist ein konstanter Ausdruck (Konstante Ausdrücke), wenn der Typ ein Verweistyp oder ein Typparameter ist, der als Verweistyp bekannt ist (Typparameter Einschränkungen).A default_value_expression is a constant expression (Constant expressions) if the type is a reference type or a type parameter that is known to be a reference type (Type parameter constraints). Außerdem ist ein default_value_expression ein konstanter Ausdruck, wenn der Typ einem der folgenden Werttypen entspricht: sbyte
, byte
, short
, ushort
, int
, uint
, long
, ulong
, char
, float
, double
, decimal
, bool
oder ein beliebiger Enumerationstyp.In addition, a default_value_expression is a constant expression if the type is one of the following value types: sbyte
, byte
, short
, ushort
, int
, uint
, long
, ulong
, char
, float
, double
, decimal
, bool
, or any enumeration type.
Nameof-AusdrückeNameof expressions
Ein nameof_expression wird zum Abrufen des Namens einer Programm Entität als Konstante Zeichenfolge verwendet.A nameof_expression is used to obtain the name of a program entity as a constant string.
nameof_expression
: 'nameof' '(' named_entity ')'
;
named_entity
: simple_name
| named_entity_target '.' identifier type_argument_list?
;
named_entity_target
: 'this'
| 'base'
| named_entity
| predefined_type
| qualified_alias_member
;
Der named_entity Operand ist immer ein Ausdruck.Grammatically speaking, the named_entity operand is always an expression. Da nameof
kein reserviertes Schlüsselwort ist, ist ein nameof-Ausdruck immer syntaktisch mehrdeutig, wenn der einfache Name aufgerufen wird nameof
.Because nameof
is not a reserved keyword, a nameof expression is always syntactically ambiguous with an invocation of the simple name nameof
. Aus Kompatibilitätsgründen, wenn eine Namenssuche (simple names) des namens nameof
erfolgreich ist, wird der Ausdruck als invocation_expression behandelt, unabhängig davon, ob der Aufruf zulässig ist.For compatibility reasons, if a name lookup (Simple names) of the name nameof
succeeds, the expression is treated as an invocation_expression -- regardless of whether the invocation is legal. Andernfalls handelt es sich um einen nameof_expression.Otherwise it is a nameof_expression.
Die Bedeutung des named_entity eines nameof_expression ist die Bedeutung des Ausdrucks als Ausdruck. Das heißt, entweder als Simple_name, als base_access oder als member_access.The meaning of the named_entity of a nameof_expression is the meaning of it as an expression; that is, either as a simple_name, a base_access or a member_access. Wenn die in einfachen Namen und dem Element Zugriff beschriebene Suche jedoch zu einem Fehler führt, weil ein Instanzmember in einem statischen Kontext gefunden wurde, erzeugt eine nameof_expression keinen derartigen Fehler.However, where the lookup described in Simple names and Member access results in an error because an instance member was found in a static context, a nameof_expression produces no such error.
Es handelt sich um einen Kompilierzeitfehler für eine named_entity die eine Methoden Gruppe für eine type_argument_list festlegt.It is a compile-time error for a named_entity designating a method group to have a type_argument_list. Es handelt sich um einen Kompilierzeitfehler für eine named_entity_target , die über den-Typ verfügen dynamic
.It is a compile time error for a named_entity_target to have the type dynamic
.
Bei einem nameof_expression handelt es sich um einen konstanten Ausdruck vom Typ string
, der zur Laufzeit keine Auswirkung hat.A nameof_expression is a constant expression of type string
, and has no effect at runtime. Insbesondere wird der named_entity nicht ausgewertet, und wird für die konkrete Zuweisungs Analyse ignoriert (Allgemeine Regeln für einfache Ausdrücke).Specifically, its named_entity is not evaluated, and is ignored for the purposes of definite assignment analysis (General rules for simple expressions). Der Wert ist der letzte Bezeichner des named_entity vor der optionalen abschließenden type_argument_list, wie folgt transformiert:Its value is the last identifier of the named_entity before the optional final type_argument_list, transformed in the following way:
- Wenn Sie verwendet wird, wird das Präfix "
@
" entfernt.The prefix "@
", if used, is removed. - Jede unicode_escape_sequence wird in das entsprechende Unicode-Zeichen transformiert.Each unicode_escape_sequence is transformed into its corresponding Unicode character.
- Alle formatting_characters werden entfernt.Any formatting_characters are removed.
Dabei handelt es sich um dieselben Transformationen, die beim Testen der Gleichheit zwischen bezeichlern in Bezeichner angewendet werden.These are the same transformations applied in Identifiers when testing equality between identifiers.
TODO: BeispieleTODO: examples
Anonyme Methoden AusdrückeAnonymous method expressions
Eine anonymous_method_expression ist eine von zwei Möglichkeiten, eine anonyme Funktion zu definieren.An anonymous_method_expression is one of two ways of defining an anonymous function. Diese werden in Anonyme Funktions Ausdrückeweiter unten beschrieben.These are further described in Anonymous function expressions.
Unäre OperatorenUnary operators
Die ?
+
-
Operatoren,,, !
, ~
, ++
,, --
Cast und await
werden als unäre Operatoren bezeichnet.The ?
, +
, -
, !
, ~
, ++
, --
, cast, and await
operators are called the unary operators.
unary_expression
: primary_expression
| null_conditional_expression
| '+' unary_expression
| '-' unary_expression
| '!' unary_expression
| '~' unary_expression
| pre_increment_expression
| pre_decrement_expression
| cast_expression
| await_expression
| unary_expression_unsafe
;
Wenn der Operand einer unary_expression den Kompilier Zeittyp aufweist dynamic
, wird er dynamisch gebunden (dynamische Bindung).If the operand of a unary_expression has the compile-time type dynamic
, it is dynamically bound (Dynamic binding). In diesem Fall ist der Kompilier Zeittyp der unary_expression dynamic
, und die unten beschriebene Auflösung erfolgt zur Laufzeit mit dem Lauf Zeittyp des Operanden.In this case the compile-time type of the unary_expression is dynamic
, and the resolution described below will take place at run-time using the run-time type of the operand.
NULL-bedingter OperatorNull-conditional operator
Der NULL bedingte Operator wendet eine Liste von Vorgängen auf seinen Operanden nur an, wenn dieser Operand nicht NULL ist.The null-conditional operator applies a list of operations to its operand only if that operand is non-null. Andernfalls ist das Ergebnis der Anwendung des-Operators null
.Otherwise the result of applying the operator is null
.
null_conditional_expression
: primary_expression null_conditional_operations
;
null_conditional_operations
: null_conditional_operations? '?' '.' identifier type_argument_list?
| null_conditional_operations? '?' '[' argument_list ']'
| null_conditional_operations '.' identifier type_argument_list?
| null_conditional_operations '[' argument_list ']'
| null_conditional_operations '(' argument_list? ')'
;
Die Liste der Vorgänge kann Member-und Element Zugriffs Vorgänge (die selbst bedingt NULL sein können) sowie Aufrufe einschließen.The list of operations can include member access and element access operations (which may themselves be null-conditional), as well as invocation.
Der Ausdruck ist z. b. a.b?[0]?.c()
ein null_conditional_expression mit einem primary_expression a.b
und null_conditional_operations ?[0]
(null bedingter Element Zugriff), ?.c
(null bedingter Member-Zugriff) und ()
(Aufruf).For example, the expression a.b?[0]?.c()
is a null_conditional_expression with a primary_expression a.b
and null_conditional_operations ?[0]
(null-conditional element access), ?.c
(null-conditional member access) and ()
(invocation).
Bei einer null_conditional_expression E
mit einem primary_expression P
ist E0
der Ausdruck, der durch textuelles Entfernen der führenden ?
aus den einzelnen null_conditional_operations von abgerufen wird E
.For a null_conditional_expression E
with a primary_expression P
, let E0
be the expression obtained by textually removing the leading ?
from each of the null_conditional_operations of E
that have one. Konzeptionell E0
ist der Ausdruck, der ausgewertet wird, wenn keine der Null-Überprüfungen, die von den s dargestellt werden, ?
eine findet null
.Conceptually, E0
is the expression that will be evaluated if none of the null checks represented by the ?
s do find a null
.
Außerdem soll E1
der Ausdruck abgerufen werden, der durch textuelles Entfernen der führenden ?
aus nur der ersten des null_conditional_operations in abgerufen wird E
.Also, let E1
be the expression obtained by textually removing the leading ?
from just the first of the null_conditional_operations in E
. Dies kann zu einem primären Ausdruck (sofern es nur einen gibt ?
) oder zu einem anderen null_conditional_expression führen.This may lead to a primary-expression (if there was just one ?
) or to another null_conditional_expression.
Wenn z. b. E
der Ausdruck ist a.b?[0]?.c()
, dann E0
ist der Ausdruck, a.b[0].c()
und E1
ist der Ausdruck a.b[0]?.c()
.For example, if E
is the expression a.b?[0]?.c()
, then E0
is the expression a.b[0].c()
and E1
is the expression a.b[0]?.c()
.
Wenn E0
als "Nothing" klassifiziert wird, E
wird als "Nothing" klassifiziert.If E0
is classified as nothing, then E
is classified as nothing. Andernfalls wird E als Wert klassifiziert.Otherwise E is classified as a value.
E0
und E1
werden verwendet, um die Bedeutung von zu bestimmen E
:E0
and E1
are used to determine the meaning of E
:
Wenn
E
als statement_expression wird, ist die Bedeutung von mit der-E
Anweisung identisch.IfE
occurs as a statement_expression the meaning ofE
is the same as the statementif ((object)P != null) E1;
mit der Ausnahme, dass P nur einmal ausgewertet wird.except that P is evaluated only once.
Andernfalls, wenn
E0
als "Nothing" klassifiziert wird, tritt ein Kompilierzeitfehler auf.Otherwise, ifE0
is classified as nothing a compile-time error occurs.Andernfalls ist
T0
der Typ vonE0
.Otherwise, letT0
be the type ofE0
.Wenn ein
T0
Typparameter ist, der nicht bekannt ist, dass es sich um einen Verweistyp oder einen nicht auf NULL festleg baren Werttyp handelt, tritt ein Kompilierzeitfehler auf.IfT0
is a type parameter that is not known to be a reference type or a non-nullable value type, a compile-time error occurs.Wenn
T0
ein Werttyp ist, der keine NULL-Werte zulässt, ist der Typ vonE
T0?
, und die Bedeutung vonE
entspricht.IfT0
is a non-nullable value type, then the type ofE
isT0?
, and the meaning ofE
is the same as((object)P == null) ? (T0?)null : E1
mit der Ausnahme, dass
P
nur einmal ausgewertet wird.except thatP
is evaluated only once.Andernfalls ist der Typ von e t0, und die Bedeutung von e ist identisch mit.Otherwise the type of E is T0, and the meaning of E is the same as
((object)P == null) ? null : E1
mit der Ausnahme, dass
P
nur einmal ausgewertet wird.except thatP
is evaluated only once.
Wenn E1
selbst ein null_conditional_expression ist, werden diese Regeln erneut angewendet, und die Tests werden null
geschachtelt, bis keine weiteren vorhanden sind ?
, und der Ausdruck wurde bis zum primären Ausdruck reduziert E0
.If E1
is itself a null_conditional_expression, then these rules are applied again, nesting the tests for null
until there are no further ?
's, and the expression has been reduced all the way down to the primary-expression E0
.
Wenn der Ausdruck beispielsweise a.b?[0]?.c()
als Anweisungs Ausdruck auftritt, wie in der-Anweisung:For example, if the expression a.b?[0]?.c()
occurs as a statement-expression, as in the statement:
a.b?[0]?.c();
seine Bedeutung ist äquivalent zu:its meaning is equivalent to:
if (a.b != null) a.b[0]?.c();
Das wiederum entspricht:which again is equivalent to:
if (a.b != null) if (a.b[0] != null) a.b[0].c();
Mit Ausnahme von a.b
und a.b[0]
werden nur einmal ausgewertet.Except that a.b
and a.b[0]
are evaluated only once.
Wenn Sie in einem Kontext auftritt, in dem ihr Wert verwendet wird, wie in:If it occurs in a context where its value is used, as in:
var x = a.b?[0]?.c();
und vorausgesetzt, dass der Typ des letzten aufzurufenden aufzurufenden nicht auf NULL festleg baren Werttypen ist, entspricht seine Bedeutung folgenden Werten:and assuming that the type of the final invocation is not a non-nullable value type, its meaning is equivalent to:
var x = (a.b == null) ? null : (a.b[0] == null) ? null : a.b[0].c();
mit Ausnahme von a.b
und a.b[0]
werden nur einmal ausgewertet.except that a.b
and a.b[0]
are evaluated only once.
NULL bedingte Ausdrücke als Projektions InitialisiererNull-conditional expressions as projection initializers
Ein NULL bedingter Ausdruck ist nur als member_declarator in einer anonymous_object_creation_expression zulässig (Ausdrücke zum Erstellen anonymer Objekte), wenn er mit einem (optional NULL bedingten) Member-Zugriff endet.A null-conditional expression is only allowed as a member_declarator in an anonymous_object_creation_expression (Anonymous object creation expressions) if it ends with an (optionally null-conditional) member access. Diese Anforderung kann wie folgt ausgedrückt werden:Grammatically, this requirement can be expressed as:
null_conditional_member_access
: primary_expression null_conditional_operations? '?' '.' identifier type_argument_list?
| primary_expression null_conditional_operations '.' identifier type_argument_list?
;
Dies ist ein Sonderfall der Grammatik für null_conditional_expression oben.This is a special case of the grammar for null_conditional_expression above. Die Produktion für member_declarator in Ausdrücken der anonymen Objekt Erstellung enthält dann nur null_conditional_member_access.The production for member_declarator in Anonymous object creation expressions then includes only null_conditional_member_access.
NULL bedingte Ausdrücke als Anweisungs AusdrückeNull-conditional expressions as statement expressions
Ein NULL bedingter Ausdruck ist nur als statement_expression (Ausdrucks Anweisungen) zulässig, wenn er mit einem Aufruf endet.A null-conditional expression is only allowed as a statement_expression (Expression statements) if it ends with an invocation. Diese Anforderung kann wie folgt ausgedrückt werden:Grammatically, this requirement can be expressed as:
null_conditional_invocation_expression
: primary_expression null_conditional_operations '(' argument_list? ')'
;
Dies ist ein Sonderfall der Grammatik für null_conditional_expression oben.This is a special case of the grammar for null_conditional_expression above. Die Produktion für statement_expression in Ausdrucks Anweisungen enthält dann nur null_conditional_invocation_expression.The production for statement_expression in Expression statements then includes only null_conditional_invocation_expression.
Unärer Plus-OperatorUnary plus operator
Bei einem Vorgang des Formulars +x
wird die Überladungs Auflösung des unären Operators (unäre Operator Überladungs Auflösung) angewendet, um eine bestimmte Operator Implementierung auszuwählen.For an operation of the form +x
, unary operator overload resolution (Unary operator overload resolution) is applied to select a specific operator implementation. Der Operand wird in den Parametertyp des ausgewählten Operators konvertiert, und der Ergebnistyp ist der Rückgabetyp des Operators.The operand is converted to the parameter type of the selected operator, and the type of the result is the return type of the operator. Die vordefinierten unären plus Operatoren sind:The predefined unary plus operators are:
int operator +(int x);
uint operator +(uint x);
long operator +(long x);
ulong operator +(ulong x);
float operator +(float x);
double operator +(double x);
decimal operator +(decimal x);
Für jeden dieser Operatoren ist das Ergebnis einfach der Wert des Operanden.For each of these operators, the result is simply the value of the operand.
Unärer Minus-OperatorUnary minus operator
Bei einem Vorgang des Formulars -x
wird die Überladungs Auflösung des unären Operators (unäre Operator Überladungs Auflösung) angewendet, um eine bestimmte Operator Implementierung auszuwählen.For an operation of the form -x
, unary operator overload resolution (Unary operator overload resolution) is applied to select a specific operator implementation. Der Operand wird in den Parametertyp des ausgewählten Operators konvertiert, und der Ergebnistyp ist der Rückgabetyp des Operators.The operand is converted to the parameter type of the selected operator, and the type of the result is the return type of the operator. Die vordefinierten Negations Operatoren lauten wie folgt:The predefined negation operators are:
Ganzzahlige Negation:Integer negation:
int operator -(int x); long operator -(long x);
Das Ergebnis wird durch Subtrahieren
x
von 0 (null) berechnet.The result is computed by subtractingx
from zero. Wenn der Wert vonx
der kleinste darstellbare Wert des Operanden Typs (-2 ^ 31 fürint
oder-2 ^ 63 für) istlong
, kann die mathematische Negation vonx
nicht innerhalb des Operanden Typs darstellbar sein.If the value ofx
is the smallest representable value of the operand type (-2^31 forint
or -2^63 forlong
), then the mathematical negation ofx
is not representable within the operand type. Wenn dies innerhalb eineschecked
Kontexts auftritt, wird eine ausgelöstSystem.OverflowException
. Wenn Sie in einemunchecked
Kontext auftritt, ist das Ergebnis der Wert des Operanden, und der Überlauf wird nicht gemeldet.If this occurs within achecked
context, aSystem.OverflowException
is thrown; if it occurs within anunchecked
context, the result is the value of the operand and the overflow is not reported.Wenn der Operand des Negations Operators vom Typ ist
uint
, wird er in den Typ konvertiertlong
, und der Ergebnistyp istlong
.If the operand of the negation operator is of typeuint
, it is converted to typelong
, and the type of the result islong
. Eine Ausnahme ist die Regel, die zulässt, dass derint
Wert-2147483648 (-2 ^ 31) als dezimales Ganzzahlliteral (ganzzahlige Literale) geschrieben wird.An exception is the rule that permits theint
value -2147483648 (-2^31) to be written as a decimal integer literal (Integer literals).Wenn der Operand des Negations Operators vom Typ ist
ulong
, tritt ein Kompilierzeitfehler auf.If the operand of the negation operator is of typeulong
, a compile-time error occurs. Eine Ausnahme ist die Regel, die zulässt, dass derlong
Wert-9.223.372.036.854.775.808 (-2 ^ 63) als dezimales Ganzzahlliteral (ganzzahlige Literale) geschrieben wird.An exception is the rule that permits thelong
value -9223372036854775808 (-2^63) to be written as a decimal integer literal (Integer literals).Gleit Komma Negation:Floating-point negation:
float operator -(float x); double operator -(double x);
Das Ergebnis ist der Wert von
x
mit dem zugehörigen Vorzeichen.The result is the value ofx
with its sign inverted. Wennx
NaN ist, ist das Ergebnis ebenfalls NaN.Ifx
is NaN, the result is also NaN.Dezimale Negation:Decimal negation:
decimal operator -(decimal x);
Das Ergebnis wird durch Subtrahieren
x
von 0 (null) berechnet.The result is computed by subtractingx
from zero. Die Dezimale Negation entspricht der Verwendung des unären Minus Operators vom TypSystem.Decimal
.Decimal negation is equivalent to using the unary minus operator of typeSystem.Decimal
.
Logischer Negationsoperator:Logical negation operator
Bei einem Vorgang des Formulars !x
wird die Überladungs Auflösung des unären Operators (unäre Operator Überladungs Auflösung) angewendet, um eine bestimmte Operator Implementierung auszuwählen.For an operation of the form !x
, unary operator overload resolution (Unary operator overload resolution) is applied to select a specific operator implementation. Der Operand wird in den Parametertyp des ausgewählten Operators konvertiert, und der Ergebnistyp ist der Rückgabetyp des Operators.The operand is converted to the parameter type of the selected operator, and the type of the result is the return type of the operator. Es ist nur ein vordefinierter logischer Negations Operator vorhanden:Only one predefined logical negation operator exists:
bool operator !(bool x);
Dieser Operator berechnet die logische Negation des Operanden: Wenn der Operand ist true
, ist das Ergebnis false
.This operator computes the logical negation of the operand: If the operand is true
, the result is false
. Wenn der Operand false
ist, ist das Ergebnis true
.If the operand is false
, the result is true
.
Bitweiser KomplementoperatorBitwise complement operator
Bei einem Vorgang des Formulars ~x
wird die Überladungs Auflösung des unären Operators (unäre Operator Überladungs Auflösung) angewendet, um eine bestimmte Operator Implementierung auszuwählen.For an operation of the form ~x
, unary operator overload resolution (Unary operator overload resolution) is applied to select a specific operator implementation. Der Operand wird in den Parametertyp des ausgewählten Operators konvertiert, und der Ergebnistyp ist der Rückgabetyp des Operators.The operand is converted to the parameter type of the selected operator, and the type of the result is the return type of the operator. Die vordefinierten bitweisen Komplement Operatoren sind:The predefined bitwise complement operators are:
int operator ~(int x);
uint operator ~(uint x);
long operator ~(long x);
ulong operator ~(ulong x);
Für jeden dieser Operatoren ist das Ergebnis des Vorgangs das bitweise Komplement von x
.For each of these operators, the result of the operation is the bitwise complement of x
.
Jeder Enumerationstyp E
stellt implizit den folgenden bitweisen Komplement Operator bereit:Every enumeration type E
implicitly provides the following bitwise complement operator:
E operator ~(E x);
Das Ergebnis der Auswertung von ~x
, wobei x
ein Ausdruck eines Enumerationstyps E
mit einem zugrunde liegenden Typ ist U
, ist identisch mit dem Auswerten von (E)(~(U)x)
, mit der Ausnahme, dass die Konvertierung in E
immer als if in einem Kontext ausgeführt wird (die aktivierten und deaktivierten unchecked
Operatoren).The result of evaluating ~x
, where x
is an expression of an enumeration type E
with an underlying type U
, is exactly the same as evaluating (E)(~(U)x)
, except that the conversion to E
is always performed as if in an unchecked
context (The checked and unchecked operators).
Präfix-Inkrementoperator und Präfix-DekrementoperatorPrefix increment and decrement operators
pre_increment_expression
: '++' unary_expression
;
pre_decrement_expression
: '--' unary_expression
;
Der Operand eines Präfix Inkrement-oder dekrementvorgangs muss ein Ausdruck sein, der als Variable, Eigenschafts Zugriff oder Indexerzugriff klassifiziert ist.The operand of a prefix increment or decrement operation must be an expression classified as a variable, a property access, or an indexer access. Das Ergebnis des Vorgangs ist ein Wert desselben Typs wie der Operand.The result of the operation is a value of the same type as the operand.
Wenn der Operand einer Präfix Inkrement-oder Dekrementoperation eine Eigenschaft oder ein Indexer-Zugriff ist, muss die Eigenschaft oder der Indexer sowohl einen get
-als auch einen- set
Accessor aufweisen.If the operand of a prefix increment or decrement operation is a property or indexer access, the property or indexer must have both a get
and a set
accessor. Wenn dies nicht der Fall ist, tritt ein Bindungs Zeitfehler auf.If this is not the case, a binding-time error occurs.
Unäre Operator Überladungs Auflösung (unäre Operator Überladungs Auflösung) wird angewendet, um eine bestimmte Operator Implementierung auszuwählen.Unary operator overload resolution (Unary operator overload resolution) is applied to select a specific operator implementation. ++
--
Für die folgenden Typen sind vordefinierte-und-Operatoren vorhanden: sbyte
, byte
, short
, ushort
, int
, uint
, long
, ulong
, char
, float
, double
, decimal
und ein beliebiger Enumerationstyp.Predefined ++
and --
operators exist for the following types: sbyte
, byte
, short
, ushort
, int
, uint
, long
, ulong
, char
, float
, double
, decimal
, and any enum type. Die vordefinierten ++
Operatoren geben den Wert zurück, der beim Hinzufügen von 1 zum Operanden erzeugt wurde, und die vordefinierten --
Operatoren geben den Wert zurück, der durch die Subtraktion von 1 vom Operanden erzeugt wird.The predefined ++
operators return the value produced by adding 1 to the operand, and the predefined --
operators return the value produced by subtracting 1 from the operand. Wenn in einem checked
Kontext das Ergebnis dieser Addition oder Subtraktion außerhalb des Bereichs des Ergebnis Typs liegt und der Ergebnistyp ein ganzzahliger Typ oder Enumeration-Typ ist, System.OverflowException
wird eine ausgelöst.In a checked
context, if the result of this addition or subtraction is outside the range of the result type and the result type is an integral type or enum type, a System.OverflowException
is thrown.
Die Lauf Zeit Verarbeitung einer Präfix Inkrement-oder Dekrementoperation des Formulars ++x
oder --x
besteht aus den folgenden Schritten:The run-time processing of a prefix increment or decrement operation of the form ++x
or --x
consists of the following steps:
- Wenn
x
als Variable klassifiziert ist:Ifx
is classified as a variable:x
wird ausgewertet, um die Variable zu entwickeln.x
is evaluated to produce the variable.- Der ausgewählte Operator wird mit dem Wert von
x
als sein Argument aufgerufen.The selected operator is invoked with the value ofx
as its argument. - Der vom-Operator zurückgegebene Wert wird an dem Speicherort gespeichert, der durch die Auswertung von angegeben wird
x
.The value returned by the operator is stored in the location given by the evaluation ofx
. - Der vom Operator zurückgegebene Wert wird zum Ergebnis des Vorgangs.The value returned by the operator becomes the result of the operation.
- Wenn
x
als Eigenschaft oder Indexer-Zugriff klassifiziert ist:Ifx
is classified as a property or indexer access:- Der Instanzausdruck (wenn
x
nicht iststatic
), und die Argumentliste (wennx
ein Indexer-Zugriff ist), die zugeordnet istx
, wird ausgewertet, und die Ergebnisse werden in den nachfolgendenget
-und-Accessoraufrufen verwendetset
.The instance expression (ifx
is notstatic
) and the argument list (ifx
is an indexer access) associated withx
are evaluated, and the results are used in the subsequentget
andset
accessor invocations. - Der-
get
Accessor vonx
wird aufgerufen.Theget
accessor ofx
is invoked. - Der ausgewählte Operator wird mit dem Wert aufgerufen, der vom
get
Accessor als Argument zurückgegeben wurde.The selected operator is invoked with the value returned by theget
accessor as its argument. - Der-
set
Accessor vonx
wird mit dem Wert aufgerufen, der vom Operator als sein Argument zurückgegeben wurdevalue
.Theset
accessor ofx
is invoked with the value returned by the operator as itsvalue
argument. - Der vom Operator zurückgegebene Wert wird zum Ergebnis des Vorgangs.The value returned by the operator becomes the result of the operation.
- Der Instanzausdruck (wenn
Die ++
--
Operatoren und unterstützen auch postfix-Notation (postfix-Inkrement-und Dekrementoperatoren).The ++
and --
operators also support postfix notation (Postfix increment and decrement operators). In der Regel ist das Ergebnis von x++
oder x--
der Wert von x
vor dem Vorgang, wohingegen das Ergebnis von ++x
oder --x
der Wert von x
nach dem Vorgang ist.Typically, the result of x++
or x--
is the value of x
before the operation, whereas the result of ++x
or --x
is the value of x
after the operation. In jedem Fall x
hat nach dem Vorgang denselben Wert.In either case, x
itself has the same value after the operation.
Eine- operator++
oder- operator--
Implementierung kann entweder mithilfe der Postfix-oder Präfix Notation aufgerufen werden.An operator++
or operator--
implementation can be invoked using either postfix or prefix notation. Es ist nicht möglich, separate Operator Implementierungen für die beiden Notationen zu haben.It is not possible to have separate operator implementations for the two notations.
cast-AusdrückeCast expressions
Ein cast_expression wird verwendet, um einen Ausdruck explizit in einen bestimmten Typ zu konvertieren.A cast_expression is used to explicitly convert an expression to a given type.
cast_expression
: '(' type ')' unary_expression
;
Eine cast_expression des Formulars (T)E
, wobei T
ein- Typ und E
ein- unary_expression ist, führt eine explizite Konvertierung (explizite Konvertierungen) des Werts von E
in den Typ aus T
.A cast_expression of the form (T)E
, where T
is a type and E
is a unary_expression, performs an explicit conversion (Explicit conversions) of the value of E
to type T
. Wenn keine explizite Konvertierung von E
in vorhanden T
ist, tritt ein Bindungs Zeitfehler auf.If no explicit conversion exists from E
to T
, a binding-time error occurs. Andernfalls ist das Ergebnis der Wert, der von der expliziten Konvertierung erzeugt wird.Otherwise, the result is the value produced by the explicit conversion. Das Ergebnis wird immer als Wert klassifiziert, auch wenn E
eine Variable bezeichnet.The result is always classified as a value, even if E
denotes a variable.
Die Grammatik für eine cast_expression führt zu bestimmten syntaktischen Mehrdeutigkeiten.The grammar for a cast_expression leads to certain syntactic ambiguities. Der Ausdruck könnte z. b. (x)-y
entweder als cast_expression (eine -y
Umwandlung von in den-Typ x
) oder als additive_expression in Kombination mit einem parenthesized_expression (der den Wert berechnet) interpretiert werden x - y)
.For example, the expression (x)-y
could either be interpreted as a cast_expression (a cast of -y
to type x
) or as an additive_expression combined with a parenthesized_expression (which computes the value x - y)
.
Um cast_expression Mehrdeutigkeiten aufzulösen, ist die folgende Regel vorhanden: eine Sequenz von einem oder mehreren Token(Leerraum), die in Klammern eingeschlossen ist, wird nur als Anfang eines cast_expression betrachtet, wenn mindestens einer der folgenden Punkte zutrifft:To resolve cast_expression ambiguities, the following rule exists: A sequence of one or more token s (White space) enclosed in parentheses is considered the start of a cast_expression only if at least one of the following are true:
- Die Reihenfolge der Token ist die korrekte Grammatik für einen Typ, jedoch nicht für einen Ausdruck.The sequence of tokens is correct grammar for a type, but not for an expression.
- Die Reihenfolge der Token ist für einen Typ eine korrekte Grammatik, und das Token, das unmittelbar auf die schließenden Klammern folgt, ist das Token "
~
", das Token "!
", das Token "(
", ein Bezeichner (Escapesequenzen für Unicode-Zeichen), ein Literalzeichen (Literale) oder ein beliebiges Schlüsselwort (Schlüsselwörter) außeras
undis
.The sequence of tokens is correct grammar for a type, and the token immediately following the closing parentheses is the token "~
", the token "!
", the token "(
", an identifier (Unicode character escape sequences), a literal (Literals), or any keyword (Keywords) exceptas
andis
.
Der Begriff "korrekte Grammatik" oben bedeutet nur, dass die Abfolge der Token der jeweiligen grammatikerischen Produktion entsprechen muss.The term "correct grammar" above means only that the sequence of tokens must conform to the particular grammatical production. Dabei wird insbesondere nicht die tatsächliche Bedeutung von einzelnen Bezeichner berücksichtigt.It specifically does not consider the actual meaning of any constituent identifiers. Wenn z. b. x
-und-Bezeichner y
sind, dann x.y
ist die korrekte Grammatik für einen Typ, auch wenn x.y
nicht tatsächlich einen Typ bezeichnet.For example, if x
and y
are identifiers, then x.y
is correct grammar for a type, even if x.y
doesn't actually denote a type.
Aus der disambiguationrule folgt, dass, wenn und Bezeichner sind,, x
y
(x)y
(x)(y)
und (x)(-y)
cast_expression s sind, aber (x)-y
nicht, auch wenn x
einen Typ identifiziert.From the disambiguation rule it follows that, if x
and y
are identifiers, (x)y
, (x)(y)
, and (x)(-y)
are cast_expression s, but (x)-y
is not, even if x
identifies a type. Wenn jedoch x
ein Schlüsselwort ist, das einen vordefinierten Typ identifiziert (z. b. int
), werden alle vier Formulare cast_expression s (da ein solches Schlüsselwort nicht möglicherweise ein Ausdruck allein sein kann).However, if x
is a keyword that identifies a predefined type (such as int
), then all four forms are cast_expression s (because such a keyword could not possibly be an expression by itself).
Erwartungs AusdrückeAwait expressions
Der Erwartungs Operator wird verwendet, um die Auswertung der einschließenden Async-Funktion anzuhalten, bis der asynchrone Vorgang, der durch den Operanden dargestellt wird, abgeschlossen ist.The await operator is used to suspend evaluation of the enclosing async function until the asynchronous operation represented by the operand has completed.
await_expression
: 'await' unary_expression
;
Ein- await_expression ist nur im Text einer Async-Funktion (Async-Funktionen) zulässig.An await_expression is only allowed in the body of an async function (Async functions). In der nächsten einschließenden asynchronen Funktion tritt möglicherweise keine await_expression an folgenden Stellen auf:Within the nearest enclosing async function, an await_expression may not occur in these places:
- Innerhalb einer geschachtelten (nicht Async) anonymen FunktionInside a nested (non-async) anonymous function
- Innerhalb des Blocks einer lock_statementInside the block of a lock_statement
- In einem unsicheren KontextIn an unsafe context
Beachten Sie, dass ein await_expression an den meisten Stellen innerhalb eines query_expression nicht vorkommen kann, da diese syntaktisch transformiert werden, um nicht asynchrone Lambda-Ausdrücke zu verwenden.Note that an await_expression cannot occur in most places within a query_expression, because those are syntactically transformed to use non-async lambda expressions.
Innerhalb einer Async-Funktion await
kann nicht als Bezeichner verwendet werden.Inside of an async function, await
cannot be used as an identifier. Daher gibt es keine syntaktische Mehrdeutigkeit zwischen "Erwartung-Ausdrücke" und verschiedenen Ausdrücken mit bezeichmern.There is therefore no syntactic ambiguity between await-expressions and various expressions involving identifiers. Außerhalb der Async-Funktionen await
fungiert als normaler Bezeichner.Outside of async functions, await
acts as a normal identifier.
Der Operand eines await_expression wird als *Task _ bezeichnet.The operand of an await_expression is called the *task _. Sie stellt einen asynchronen Vorgang dar, der zum Zeitpunkt der Auswertung der _await_expression * möglicherweise nicht ausgeführt wird.It represents an asynchronous operation that may or may not be complete at the time the _await_expression* is evaluated. Der erwartete Operator besteht darin, die Ausführung der einschließenden Async-Funktion anzuhalten, bis die erwartete Aufgabe abgeschlossen ist, und dann das Ergebnis zu erhalten.The purpose of the await operator is to suspend execution of the enclosing async function until the awaited task is complete, and then obtain its outcome.
Awanutzbare AusdrückeAwaitable expressions
Die Aufgabe eines Erwartungs Ausdrucks muss erwartet werden.The task of an await expression is required to be awaitable. t
Wenn eine der folgenden Punkte enthält, kann ein Ausdruck ausgenutzt werden:An expression t
is awaitable if one of the following holds:
t
weist den Kompilier Zeittyp aufdynamic
t
is of compile time typedynamic
t
verfügt über eine barrierefreie Instanz-oder ErweiterungsmethodeGetAwaiter
, die ohne Parameter und ohne Typparameter aufgerufen wird, sowie über einen Rückgabetyp,A
für den die folgenden Werte gelten:t
has an accessible instance or extension method calledGetAwaiter
with no parameters and no type parameters, and a return typeA
for which all of the following hold:A
implementiert die-SchnittstelleSystem.Runtime.CompilerServices.INotifyCompletion
(im folgenden alsINotifyCompletion
aus Gründen der Kürze bekannt).A
implements the interfaceSystem.Runtime.CompilerServices.INotifyCompletion
(hereafter known asINotifyCompletion
for brevity)A
verfügt über eine barrierefreie, lesbareIsCompleted
Instanzeigenschaft vom Typ.bool
A
has an accessible, readable instance propertyIsCompleted
of typebool
A
verfügt über eine barrierefreie InstanzmethodeGetResult
ohne Parameter und ohne Typparameter.A
has an accessible instance methodGetResult
with no parameters and no type parameters
Der Zweck der- GetAwaiter
Methode ist das Abrufen eines *akellner _ für die Aufgabe.The purpose of the GetAwaiter
method is to obtain an *awaiter _ for the task. Der Typ A
wird als _ akellnertyp* für den Erwartungs Ausdruck bezeichnet.The type A
is called the _ awaiter type* for the await expression.
Mit der- IsCompleted
Eigenschaft wird bestimmt, ob die Aufgabe bereits beendet ist.The purpose of the IsCompleted
property is to determine if the task is already complete. Wenn dies der Fall ist, muss die Evaluierung nicht angehalten werden.If so, there is no need to suspend evaluation.
Der Zweck der- INotifyCompletion.OnCompleted
Methode besteht darin, eine "Fortsetzung" für die Aufgabe zu registrieren, d. h. einen Delegaten (vom Typ System.Action
), der nach Abschluss der Aufgabe aufgerufen wird.The purpose of the INotifyCompletion.OnCompleted
method is to sign up a "continuation" to the task; i.e. a delegate (of type System.Action
) that will be invoked once the task is complete.
Der Zweck der- GetResult
Methode besteht darin, das Ergebnis der Aufgabe zu erhalten, sobald Sie fertig ist.The purpose of the GetResult
method is to obtain the outcome of the task once it is complete. Dieses Ergebnis kann erfolgreich abgeschlossen werden, möglicherweise mit einem Ergebniswert, oder es handelt sich um eine Ausnahme, die von der-Methode ausgelöst wird GetResult
.This outcome may be successful completion, possibly with a result value, or it may be an exception which is thrown by the GetResult
method.
Klassifizierung von Erwartungs AusdrückenClassification of await expressions
Der Ausdruck await t
wird auf die gleiche Weise klassifiziert wie der Ausdruck (t).GetAwaiter().GetResult()
.The expression await t
is classified the same way as the expression (t).GetAwaiter().GetResult()
. Wenn der Rückgabetyp von den Wert GetResult
void
hat, wird der await_expression daher als "Nothing" klassifiziert.Thus, if the return type of GetResult
is void
, the await_expression is classified as nothing. Wenn Sie einen nicht leeren Rückgabetyp aufweist T
, wird die await_expression als Wert des Typs klassifiziert T
.If it has a non-void return type T
, the await_expression is classified as a value of type T
.
Lauf Zeit Auswertung von Erwartungs AusdrückenRuntime evaluation of await expressions
Zur Laufzeit wird der Ausdruck await t
wie folgt ausgewertet:At runtime, the expression await t
is evaluated as follows:
- Ein akellner
a
wird durch Auswerten des Ausdrucks abgerufen(t).GetAwaiter()
.An awaitera
is obtained by evaluating the expression(t).GetAwaiter()
. - Eine
bool
b
wird durch Auswerten des Ausdrucks abgerufen(a).IsCompleted
.Abool
b
is obtained by evaluating the expression(a).IsCompleted
. - Wenn
b
false
die Auswertung von ist, hängt davon ab, oba
die-Schnittstelle implementiertSystem.Runtime.CompilerServices.ICriticalNotifyCompletion
(im folgenden alsICriticalNotifyCompletion
aus Gründen der Kürze bekannt).Ifb
isfalse
then evaluation depends on whethera
implements the interfaceSystem.Runtime.CompilerServices.ICriticalNotifyCompletion
(hereafter known asICriticalNotifyCompletion
for brevity). Diese Überprüfung erfolgt zur Bindungs Zeit.a
, wenn beispielsweise zur Laufzeit, wenn den Kompilier Zeittypdynamic
und zur Kompilierzeit aufweist.This check is done at binding time; i.e. at runtime ifa
has the compile time typedynamic
, and at compile time otherwise.r
Bezeichnen Sie den Wiederaufnahme Delegaten (Async-Funktionen):Letr
denote the resumption delegate (Async functions):- Wenn
a
nicht implementiertICriticalNotifyCompletion
, wird der Ausdruck(a as (INotifyCompletion)).OnCompleted(r)
ausgewertet.Ifa
does not implementICriticalNotifyCompletion
, then the expression(a as (INotifyCompletion)).OnCompleted(r)
is evaluated. - Wenn
a
implementiertICriticalNotifyCompletion
, wird der Ausdruck(a as (ICriticalNotifyCompletion)).UnsafeOnCompleted(r)
ausgewertet.Ifa
does implementICriticalNotifyCompletion
, then the expression(a as (ICriticalNotifyCompletion)).UnsafeOnCompleted(r)
is evaluated. - Die Auswertung wird dann angehalten, und die Steuerung wird an den aktuellen Aufrufer der Async-Funktion zurückgegeben.Evaluation is then suspended, and control is returned to the current caller of the async function.
- Wenn
- Der Ausdruck wird entweder unmittelbar nach (wenn
b
wastrue
) oder nach einem späteren Aufruf des Wiederaufnahme Delegaten (wennb
Was istfalse
)(a).GetResult()
ausgewertet.Either immediately after (ifb
wastrue
), or upon later invocation of the resumption delegate (ifb
wasfalse
), the expression(a).GetResult()
is evaluated. Wenn ein Wert zurückgegeben wird, ist dieser Wert das Ergebnis der await_expression.If it returns a value, that value is the result of the await_expression. Andernfalls ist das Ergebnis "Nothing".Otherwise the result is nothing.
Die Implementierung der Schnittstellen Methoden eines akellers INotifyCompletion.OnCompleted
und ICriticalNotifyCompletion.UnsafeOnCompleted
sollte bewirken r
, dass der Delegat höchstens einmal aufgerufen wird.An awaiter's implementation of the interface methods INotifyCompletion.OnCompleted
and ICriticalNotifyCompletion.UnsafeOnCompleted
should cause the delegate r
to be invoked at most once. Andernfalls ist das Verhalten der einschließenden Async-Funktion nicht definiert.Otherwise, the behavior of the enclosing async function is undefined.
Arithmetische operatorenArithmetic operators
Die *
/
%
Operatoren,,, +
und -
werden als arithmetische Operatoren bezeichnet.The *
, /
, %
, +
, and -
operators are called the arithmetic operators.
multiplicative_expression
: unary_expression
| multiplicative_expression '*' unary_expression
| multiplicative_expression '/' unary_expression
| multiplicative_expression '%' unary_expression
;
additive_expression
: multiplicative_expression
| additive_expression '+' multiplicative_expression
| additive_expression '-' multiplicative_expression
;
Wenn ein Operand eines arithmetischen Operators den Kompilier Zeittyp aufweist dynamic
, wird der Ausdruck dynamisch gebunden (dynamische Bindung).If an operand of an arithmetic operator has the compile-time type dynamic
, then the expression is dynamically bound (Dynamic binding). In diesem Fall ist der Kompilier Zeittyp des Ausdrucks dynamic
, und die unten beschriebene Auflösung erfolgt zur Laufzeit mit dem Lauf Zeittyp der Operanden, die den Kompilier Zeittyp aufweisen dynamic
.In this case the compile-time type of the expression is dynamic
, and the resolution described below will take place at run-time using the run-time type of those operands that have the compile-time type dynamic
.
MultiplikationsoperatorMultiplication operator
Bei einem Vorgang des Formulars x * y
wird die binäre Operator Überladungs Auflösung (binäre Operator Überladungs Auflösung) angewendet, um eine bestimmte Operator Implementierung auszuwählen.For an operation of the form x * y
, binary operator overload resolution (Binary operator overload resolution) is applied to select a specific operator implementation. Die Operanden werden in die Parametertypen des ausgewählten Operators konvertiert, und der Ergebnistyp ist der Rückgabetyp des Operators.The operands are converted to the parameter types of the selected operator, and the type of the result is the return type of the operator.
Die vordefinierten Multiplikations Operatoren sind unten aufgeführt.The predefined multiplication operators are listed below. Alle Operatoren berechnen das Produkt von x
und y
.The operators all compute the product of x
and y
.
Integer-Multiplikation:Integer multiplication:
int operator *(int x, int y); uint operator *(uint x, uint y); long operator *(long x, long y); ulong operator *(ulong x, ulong y);
Wenn sich
checked
das Produkt in einem Kontext außerhalb des Bereichs des Ergebnis Typs befindet, wird eine ausgelöstSystem.OverflowException
.In achecked
context, if the product is outside the range of the result type, aSystem.OverflowException
is thrown. In einemunchecked
Kontext werden Überläufe nicht gemeldet, und alle signifikanten höherwertigen Bits außerhalb des Bereichs des Ergebnis Typs werden verworfen.In anunchecked
context, overflows are not reported and any significant high-order bits outside the range of the result type are discarded.Gleit Komma Multiplikation:Floating-point multiplication:
float operator *(float x, float y); double operator *(double x, double y);
Das Produkt wird gemäß den Regeln der IEEE 754-Arithmetik berechnet.The product is computed according to the rules of IEEE 754 arithmetic. In der folgenden Tabelle sind die Ergebnisse für alle möglichen Kombinationen aus endlichen Werten ungleich Null, Nullen, unendlichen Werten und NaN-Werten aufgeführt.The following table lists the results of all possible combinations of nonzero finite values, zeros, infinities, and NaN's. In der Tabelle sind
x
undy
positive endliche Werte.In the table,x
andy
are positive finite values.z
ist das Ergebnis vonx * y
.z
is the result ofx * y
. Wenn das Ergebnis für den Zieltyp zu groß ist, istz
ein unendlicher Wert.If the result is too large for the destination type,z
is infinity. Wenn das Ergebnis für den Zieltyp zu klein ist, istz
Null.If the result is too small for the destination type,z
is zero.+y+y -y-y +0+0 -0-0 +inf+inf -inf-inf NaNNaN +x+x +z+z -Z-z +0+0 -0-0 +inf+inf -inf-inf NaNNaN -X-x -Z-z +z+z -0-0 +0+0 -inf-inf +inf+inf NaNNaN +0+0 +0+0 -0-0 +0+0 -0-0 NaNNaN NaNNaN NaNNaN -0-0 -0-0 +0+0 -0-0 +0+0 NaNNaN NaNNaN NaNNaN +inf+inf +inf+inf -inf-inf NaNNaN NaNNaN +inf+inf -inf-inf NaNNaN -inf-inf -inf-inf +inf+inf NaNNaN NaNNaN -inf-inf +inf+inf NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN Dezimale Multiplikation:Decimal multiplication:
decimal operator *(decimal x, decimal y);
Wenn der resultierende Wert zu groß für die Darstellung im-
decimal
Format ist,System.OverflowException
wird eine ausgelöst.If the resulting value is too large to represent in thedecimal
format, aSystem.OverflowException
is thrown. Wenn der Ergebniswert zu klein ist, um imdecimal
Format darzustellen, ist das Ergebnis 0 (null).If the result value is too small to represent in thedecimal
format, the result is zero. Die Dezimalstellen des Ergebnisses, vor der Rundung, sind die Summe der Skalen der beiden Operanden.The scale of the result, before any rounding, is the sum of the scales of the two operands.Die Dezimal Multiplikation entspricht der Verwendung des Multiplikations Operators vom Typ
System.Decimal
.Decimal multiplication is equivalent to using the multiplication operator of typeSystem.Decimal
.
DivisionsoperatorDivision operator
Bei einem Vorgang des Formulars x / y
wird die binäre Operator Überladungs Auflösung (binäre Operator Überladungs Auflösung) angewendet, um eine bestimmte Operator Implementierung auszuwählen.For an operation of the form x / y
, binary operator overload resolution (Binary operator overload resolution) is applied to select a specific operator implementation. Die Operanden werden in die Parametertypen des ausgewählten Operators konvertiert, und der Ergebnistyp ist der Rückgabetyp des Operators.The operands are converted to the parameter types of the selected operator, and the type of the result is the return type of the operator.
Die vordefinierten Divisions Operatoren sind unten aufgeführt.The predefined division operators are listed below. Die Operatoren berechnen alle den Quotienten von x
und y
.The operators all compute the quotient of x
and y
.
Ganzzahlige Division:Integer division:
int operator /(int x, int y); uint operator /(uint x, uint y); long operator /(long x, long y); ulong operator /(ulong x, ulong y);
Wenn der Wert des rechten Operanden 0 (null) ist, wird eine ausgelöst
System.DivideByZeroException
.If the value of the right operand is zero, aSystem.DivideByZeroException
is thrown.Die Division rundet das Ergebnis auf 0 (null).The division rounds the result towards zero. Daher ist der absolute Wert des Ergebnisses die größtmögliche Ganzzahl, die kleiner oder gleich dem absoluten Wert des Quotienten der beiden Operanden ist.Thus the absolute value of the result is the largest possible integer that is less than or equal to the absolute value of the quotient of the two operands. Das Ergebnis ist 0 (null) oder positiv, wenn die beiden Operanden das gleiche Vorzeichen aufweisen und 0 (null) oder negativ ist, wenn die beiden Operanden gegenteilige Vorzeichen verfügen.The result is zero or positive when the two operands have the same sign and zero or negative when the two operands have opposite signs.
Wenn der linke Operand der kleinste darstellbare
int
-oderlong
-Wert und der rechte Operand ist-1
, tritt ein Überlauf auf.If the left operand is the smallest representableint
orlong
value and the right operand is-1
, an overflow occurs. In einemchecked
Kontext bewirkt dies,System.ArithmeticException
dass eine (oder eine Unterklasse davon) ausgelöst wird.In achecked
context, this causes aSystem.ArithmeticException
(or a subclass thereof) to be thrown. In einemunchecked
Kontext ist die Implementierung definiert, ob einSystem.ArithmeticException
(oder eine Unterklasse) ausgelöst wird, oder der Überlauf wird nicht gemeldet, und der resultierende Wert ist der des linken Operanden.In anunchecked
context, it is implementation-defined as to whether aSystem.ArithmeticException
(or a subclass thereof) is thrown or the overflow goes unreported with the resulting value being that of the left operand.Gleit Komma Division:Floating-point division:
float operator /(float x, float y); double operator /(double x, double y);
Der Quotienten wird gemäß den Regeln der IEEE 754-Arithmetik berechnet.The quotient is computed according to the rules of IEEE 754 arithmetic. In der folgenden Tabelle sind die Ergebnisse für alle möglichen Kombinationen aus endlichen Werten ungleich Null, Nullen, unendlichen Werten und NaN-Werten aufgeführt.The following table lists the results of all possible combinations of nonzero finite values, zeros, infinities, and NaN's. In der Tabelle sind
x
undy
positive endliche Werte.In the table,x
andy
are positive finite values.z
ist das Ergebnis vonx / y
.z
is the result ofx / y
. Wenn das Ergebnis für den Zieltyp zu groß ist, istz
ein unendlicher Wert.If the result is too large for the destination type,z
is infinity. Wenn das Ergebnis für den Zieltyp zu klein ist, istz
Null.If the result is too small for the destination type,z
is zero.+y+y -y-y +0+0 -0-0 +inf+inf -inf-inf NaNNaN +x+x +z+z -Z-z +inf+inf -inf-inf +0+0 -0-0 NaNNaN -X-x -Z-z +z+z -inf-inf +inf+inf -0-0 +0+0 NaNNaN +0+0 +0+0 -0-0 NaNNaN NaNNaN +0+0 -0-0 NaNNaN -0-0 -0-0 +0+0 NaNNaN NaNNaN -0-0 +0+0 NaNNaN +inf+inf +inf+inf -inf-inf +inf+inf -inf-inf NaNNaN NaNNaN NaNNaN -inf-inf -inf-inf +inf+inf -inf-inf +inf+inf NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN Dezimale Division:Decimal division:
decimal operator /(decimal x, decimal y);
Wenn der Wert des rechten Operanden 0 (null) ist, wird eine ausgelöst
System.DivideByZeroException
.If the value of the right operand is zero, aSystem.DivideByZeroException
is thrown. Wenn der resultierende Wert zu groß für die Darstellung im-decimal
Format ist,System.OverflowException
wird eine ausgelöst.If the resulting value is too large to represent in thedecimal
format, aSystem.OverflowException
is thrown. Wenn der Ergebniswert zu klein ist, um imdecimal
Format darzustellen, ist das Ergebnis 0 (null).If the result value is too small to represent in thedecimal
format, the result is zero. Die Skala des Ergebnisses ist die kleinste Skala, die ein Ergebnis mit dem nächstgelegenen darstellbaren Dezimalwert dem tatsächlichen mathematischen Ergebnis beibehält.The scale of the result is the smallest scale that will preserve a result equal to the nearest representable decimal value to the true mathematical result.Die Dezimal Division entspricht der Verwendung des Divisions Operators vom Typ
System.Decimal
.Decimal division is equivalent to using the division operator of typeSystem.Decimal
.
RestoperatorRemainder operator
Bei einem Vorgang des Formulars x % y
wird die binäre Operator Überladungs Auflösung (binäre Operator Überladungs Auflösung) angewendet, um eine bestimmte Operator Implementierung auszuwählen.For an operation of the form x % y
, binary operator overload resolution (Binary operator overload resolution) is applied to select a specific operator implementation. Die Operanden werden in die Parametertypen des ausgewählten Operators konvertiert, und der Ergebnistyp ist der Rückgabetyp des Operators.The operands are converted to the parameter types of the selected operator, and the type of the result is the return type of the operator.
Die vordefinierten Rest-Operatoren sind unten aufgeführt.The predefined remainder operators are listed below. Die Operatoren berechnen alle den Rest der Division zwischen x
und y
.The operators all compute the remainder of the division between x
and y
.
Ganzzahliger Rest:Integer remainder:
int operator %(int x, int y); uint operator %(uint x, uint y); long operator %(long x, long y); ulong operator %(ulong x, ulong y);
Das Ergebnis von
x % y
ist der Wert, der von erzeugt wirdx - (x / y) * y
.The result ofx % y
is the value produced byx - (x / y) * y
. Wenny
0 (null) ist, wird eine ausgelöstSystem.DivideByZeroException
.Ify
is zero, aSystem.DivideByZeroException
is thrown.Wenn der linke Operand der kleinste
int
-oderlong
-Wert und der rechte Operand ist-1
,System.OverflowException
wird eine ausgelöst.If the left operand is the smallestint
orlong
value and the right operand is-1
, aSystem.OverflowException
is thrown. In keinem Fall löstx % y
eine Ausnahme aus, bei derx / y
keine Ausnahme ausgelöst wird.In no case doesx % y
throw an exception wherex / y
would not throw an exception.Gleit Komma Restwert:Floating-point remainder:
float operator %(float x, float y); double operator %(double x, double y);
In der folgenden Tabelle sind die Ergebnisse für alle möglichen Kombinationen aus endlichen Werten ungleich Null, Nullen, unendlichen Werten und NaN-Werten aufgeführt.The following table lists the results of all possible combinations of nonzero finite values, zeros, infinities, and NaN's. In der Tabelle sind
x
undy
positive endliche Werte.In the table,x
andy
are positive finite values.z
Das Ergebnis vonx % y
und wird als berechnetx - n * y
, wobein
die größtmögliche Ganzzahl ist, die kleiner oder gleich istx / y
.z
is the result ofx % y
and is computed asx - n * y
, wheren
is the largest possible integer that is less than or equal tox / y
. Diese Methode zum Berechnen des Restwerts entspricht der für ganzzahligen Operanden, unterscheidet sich jedoch von der IEEE 754-Definition (bei dern
es sich um die ganze Zahl handelt, die am nächsten istx / y
).This method of computing the remainder is analogous to that used for integer operands, but differs from the IEEE 754 definition (in whichn
is the integer closest tox / y
).+y+y -y-y +0+0 -0-0 +inf+inf -inf-inf NaNNaN +x+x +z+z +z+z NaNNaN NaNNaN xx xx NaNNaN -X-x -Z-z -Z-z NaNNaN NaNNaN -X-x -X-x NaNNaN +0+0 +0+0 +0+0 NaNNaN NaNNaN +0+0 +0+0 NaNNaN -0-0 -0-0 -0-0 NaNNaN NaNNaN -0-0 -0-0 NaNNaN +inf+inf NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN -inf-inf NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN Dezimal Restwert:Decimal remainder:
decimal operator %(decimal x, decimal y);
Wenn der Wert des rechten Operanden 0 (null) ist, wird eine ausgelöst
System.DivideByZeroException
.If the value of the right operand is zero, aSystem.DivideByZeroException
is thrown. Die Dezimalstellen des Ergebnisses, vor der Rundung, sind die größere der Skalen der beiden Operanden, und das Vorzeichen des Ergebnisses ist, wenn ungleich NULL, mit dem von identischx
.The scale of the result, before any rounding, is the larger of the scales of the two operands, and the sign of the result, if non-zero, is the same as that ofx
.Der Dezimal Rest entspricht der Verwendung des Rest-Operators vom Typ
System.Decimal
.Decimal remainder is equivalent to using the remainder operator of typeSystem.Decimal
.
AdditionsoperatorAddition operator
Bei einem Vorgang des Formulars x + y
wird die binäre Operator Überladungs Auflösung (binäre Operator Überladungs Auflösung) angewendet, um eine bestimmte Operator Implementierung auszuwählen.For an operation of the form x + y
, binary operator overload resolution (Binary operator overload resolution) is applied to select a specific operator implementation. Die Operanden werden in die Parametertypen des ausgewählten Operators konvertiert, und der Ergebnistyp ist der Rückgabetyp des Operators.The operands are converted to the parameter types of the selected operator, and the type of the result is the return type of the operator.
Die vordefinierten Additions Operatoren sind unten aufgeführt.The predefined addition operators are listed below. Für numerische und Enumerationstypen berechnen die vordefinierten Additions Operatoren die Summe der beiden Operanden.For numeric and enumeration types, the predefined addition operators compute the sum of the two operands. Wenn ein oder beide Operanden vom Typ Zeichenfolge sind, verketten die vordefinierten Additions Operatoren die Zeichen folgen Darstellung der Operanden.When one or both operands are of type string, the predefined addition operators concatenate the string representation of the operands.
Ganzzahlige Addition:Integer addition:
int operator +(int x, int y); uint operator +(uint x, uint y); long operator +(long x, long y); ulong operator +(ulong x, ulong y);
In einem
checked
Kontext wird eine ausgelöst, wenn die Summe außerhalb des Bereichs des Ergebnis Typs liegtSystem.OverflowException
.In achecked
context, if the sum is outside the range of the result type, aSystem.OverflowException
is thrown. In einemunchecked
Kontext werden Überläufe nicht gemeldet, und alle signifikanten höherwertigen Bits außerhalb des Bereichs des Ergebnis Typs werden verworfen.In anunchecked
context, overflows are not reported and any significant high-order bits outside the range of the result type are discarded.Gleit Komma Addition:Floating-point addition:
float operator +(float x, float y); double operator +(double x, double y);
Die Summe wird gemäß den Regeln der IEEE 754-Arithmetik berechnet.The sum is computed according to the rules of IEEE 754 arithmetic. In der folgenden Tabelle sind die Ergebnisse für alle möglichen Kombinationen aus endlichen Werten ungleich Null, Nullen, unendlichen Werten und NaN-Werten aufgeführt.The following table lists the results of all possible combinations of nonzero finite values, zeros, infinities, and NaN's. In der Tabelle sind
x
undy
endliche Werte ungleich Null, undz
ist das Ergebnis ausx + y
.In the table,x
andy
are nonzero finite values, andz
is the result ofx + y
. Wennx
undy
die gleiche Größe jedoch andere Vorzeichen haben, istz
eine positive Null.Ifx
andy
have the same magnitude but opposite signs,z
is positive zero. Wenn zux + y
groß ist, um im Zieltyp darzustellen,z
ist ein Unendlichkeits Wert mit demselben Vorzeichen wiex + y
.Ifx + y
is too large to represent in the destination type,z
is an infinity with the same sign asx + y
.Yy +0+0 -0-0 +inf+inf -inf-inf NaNNaN wx zz xx xx +inf+inf -inf-inf NaNNaN +0+0 Yy +0+0 +0+0 +inf+inf -inf-inf NaNNaN -0-0 Yy +0+0 -0-0 +inf+inf -inf-inf NaNNaN +inf+inf +inf+inf +inf+inf +inf+inf +inf+inf NaNNaN NaNNaN -inf-inf -inf-inf -inf-inf -inf-inf NaNNaN -inf-inf NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN Dezimal Addition:Decimal addition:
decimal operator +(decimal x, decimal y);
Wenn der resultierende Wert zu groß für die Darstellung im-
decimal
Format ist,System.OverflowException
wird eine ausgelöst.If the resulting value is too large to represent in thedecimal
format, aSystem.OverflowException
is thrown. Die Dezimalstellen des Ergebnisses, vor der Rundung, sind die größere der Skalen der beiden Operanden.The scale of the result, before any rounding, is the larger of the scales of the two operands.Die Dezimal Addition entspricht der Verwendung des Additions Operators vom Typ
System.Decimal
.Decimal addition is equivalent to using the addition operator of typeSystem.Decimal
.Enumerationsaddition.Enumeration addition. Jeder Enumerationstyp stellt implizit die folgenden vordefinierten Operatoren bereit, wobei
E
der Enumerationstyp undU
der zugrunde liegende Typ von istE
:Every enumeration type implicitly provides the following predefined operators, whereE
is the enum type, andU
is the underlying type ofE
:E operator +(E x, U y); E operator +(U x, E y);
Zur Laufzeit werden diese Operatoren genau wie ausgewertet
(E)((U)x + (U)y)
.At run-time these operators are evaluated exactly as(E)((U)x + (U)y)
.Verkettung von Zeichen folgen:String concatenation:
string operator +(string x, string y); string operator +(string x, object y); string operator +(object x, string y);
Diese über Ladungen des binären
+
Operators führen die Verkettung von Zeichen folgen aus.These overloads of the binary+
operator perform string concatenation. Wenn ein Operand der Zeichen folgen Verkettung istnull
, wird eine leere Zeichenfolge ersetzt.If an operand of string concatenation isnull
, an empty string is substituted. Andernfalls wird jedes nicht-Zeichen folgen Argument in seine Zeichen folgen Darstellung konvertiert, indem dieToString
vom Typ geerbte virtuelle Methode aufgerufen wirdobject
.Otherwise, any non-string argument is converted to its string representation by invoking the virtualToString
method inherited from typeobject
. WennToString
zurückgibtnull
, wird eine leere Zeichenfolge ersetzt.IfToString
returnsnull
, an empty string is substituted.using System; class Test { static void Main() { string s = null; Console.WriteLine("s = >" + s + "<"); // displays s = >< int i = 1; Console.WriteLine("i = " + i); // displays i = 1 float f = 1.2300E+15F; Console.WriteLine("f = " + f); // displays f = 1.23E+15 decimal d = 2.900m; Console.WriteLine("d = " + d); // displays d = 2.900 } }
Das Ergebnis des Zeichenfolgenverkettungs-Operators ist eine Zeichenfolge, die aus den Zeichen des linken Operanden besteht, gefolgt von den Zeichen des rechten Operanden. Der Operator für die Zeichen folgen Verkettung gibt niemals einen
null
Wert zurück. EineSystem.OutOfMemoryException
kann ausgelöst werden, wenn nicht genügend Arbeitsspeicher zur Verfügung steht, um die resultierende Zeichenfolge zuzuordnen.ASystem.OutOfMemoryException
may be thrown if there is not enough memory available to allocate the resulting string.Delegatkombination.Delegate combination. Jeder Delegattyp stellt implizit den folgenden vordefinierten Operator bereit, wobei
D
der Delegattyp ist:Every delegate type implicitly provides the following predefined operator, whereD
is the delegate type:D operator +(D x, D y);
Der binäre
+
Operator führt eine Delegatkombination aus, wenn beide Operanden einen Delegattyp habenD
.The binary+
operator performs delegate combination when both operands are of some delegate typeD
. (Wenn die Operanden unterschiedliche Delegattypen aufweisen, tritt ein Bindungs Zeitfehler auf.) Wenn der erste Operand istnull
, ist das Ergebnis der Operation der Wert des zweiten Operanden (auch wenn dies ebenfalls der Wert istnull
).(If the operands have different delegate types, a binding-time error occurs.) If the first operand isnull
, the result of the operation is the value of the second operand (even if that is alsonull
). Andernfalls ist der zweite Operand, wenn der zweite Operand istnull
, das Ergebnis des Vorgangs der Wert des ersten Operanden.Otherwise, if the second operand isnull
, then the result of the operation is the value of the first operand. Andernfalls ist das Ergebnis des Vorgangs eine neue Delegatinstanz, die beim Aufrufen den ersten Operanden aufruft und dann den zweiten Operanden aufruft.Otherwise, the result of the operation is a new delegate instance that, when invoked, invokes the first operand and then invokes the second operand. Beispiele für die Kombination von Delegaten finden Sie unter Subtraktions Operator und Delegataufruf. For examples of delegate combination, see Subtraction operator and Delegate invocation. DaSystem.Delegate
kein Delegattyp ist,operator
+
ist für ihn nicht definiert.SinceSystem.Delegate
is not a delegate type,operator
+
is not defined for it.
SubtraktionsoperatorSubtraction operator
Bei einem Vorgang des Formulars x - y
wird die binäre Operator Überladungs Auflösung (binäre Operator Überladungs Auflösung) angewendet, um eine bestimmte Operator Implementierung auszuwählen.For an operation of the form x - y
, binary operator overload resolution (Binary operator overload resolution) is applied to select a specific operator implementation. Die Operanden werden in die Parametertypen des ausgewählten Operators konvertiert, und der Ergebnistyp ist der Rückgabetyp des Operators.The operands are converted to the parameter types of the selected operator, and the type of the result is the return type of the operator.
Die vordefinierten Subtraktions Operatoren sind unten aufgeführt.The predefined subtraction operators are listed below. Die Operatoren, die alle von subtrahieren y
x
.The operators all subtract y
from x
.
Ganzzahlige Subtraktion:Integer subtraction:
int operator -(int x, int y); uint operator -(uint x, uint y); long operator -(long x, long y); ulong operator -(ulong x, ulong y);
Wenn sich
checked
der Unterschied in einem Kontext außerhalb des Bereichs des Ergebnis Typs befindet, wird eine ausgelöstSystem.OverflowException
.In achecked
context, if the difference is outside the range of the result type, aSystem.OverflowException
is thrown. In einemunchecked
Kontext werden Überläufe nicht gemeldet, und alle signifikanten höherwertigen Bits außerhalb des Bereichs des Ergebnis Typs werden verworfen.In anunchecked
context, overflows are not reported and any significant high-order bits outside the range of the result type are discarded.Gleit Komma Subtraktion:Floating-point subtraction:
float operator -(float x, float y); double operator -(double x, double y);
Der Unterschied wird gemäß den Regeln der IEEE 754-Arithmetik berechnet.The difference is computed according to the rules of IEEE 754 arithmetic. In der folgenden Tabelle werden die Ergebnisse aller möglichen Kombinationen von nicht NULL Endwerten, Nullen, Infinities und Nane aufgelistet.The following table lists the results of all possible combinations of nonzero finite values, zeros, infinities, and NaNs. In der Tabelle sind
x
undy
endliche Werte ungleich Null, undz
ist das Ergebnis ausx - y
.In the table,x
andy
are nonzero finite values, andz
is the result ofx - y
. Wennx
undy
gleich sind, istz
eine positive Null.Ifx
andy
are equal,z
is positive zero. Wenn zux - y
groß ist, um im Zieltyp darzustellen,z
ist ein Unendlichkeits Wert mit demselben Vorzeichen wiex - y
.Ifx - y
is too large to represent in the destination type,z
is an infinity with the same sign asx - y
.Yy +0+0 -0-0 +inf+inf -inf-inf NaNNaN wx zz xx xx -inf-inf +inf+inf NaNNaN +0+0 -y-y +0+0 +0+0 -inf-inf +inf+inf NaNNaN -0-0 -y-y -0-0 +0+0 -inf-inf +inf+inf NaNNaN +inf+inf +inf+inf +inf+inf +inf+inf NaNNaN +inf+inf NaNNaN -inf-inf -inf-inf -inf-inf -inf-inf -inf-inf NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN NaNNaN Dezimale Subtraktion:Decimal subtraction:
decimal operator -(decimal x, decimal y);
Wenn der resultierende Wert zu groß für die Darstellung im-
decimal
Format ist,System.OverflowException
wird eine ausgelöst.If the resulting value is too large to represent in thedecimal
format, aSystem.OverflowException
is thrown. Die Dezimalstellen des Ergebnisses, vor der Rundung, sind die größere der Skalen der beiden Operanden.The scale of the result, before any rounding, is the larger of the scales of the two operands.Die dezimale Subtraktion entspricht der Verwendung des Subtraktions Operators vom Typ
System.Decimal
.Decimal subtraction is equivalent to using the subtraction operator of typeSystem.Decimal
.Enumerationssubtraktion.Enumeration subtraction. Jeder Enumerationstyp stellt implizit den folgenden vordefinierten Operator bereit, wobei
E
der Enumerationstyp undU
der zugrunde liegende Typ von istE
:Every enumeration type implicitly provides the following predefined operator, whereE
is the enum type, andU
is the underlying type ofE
:U operator -(E x, E y);
Dieser Operator wird genau wie ausgewertet
(U)((U)x - (U)y)
.This operator is evaluated exactly as(U)((U)x - (U)y)
. Mit anderen Worten, der-Operator berechnet den Unterschied zwischen den Ordinalwerten vonx
undy
, und der Ergebnistyp ist der zugrunde liegende Typ der Enumeration.In other words, the operator computes the difference between the ordinal values ofx
andy
, and the type of the result is the underlying type of the enumeration.E operator -(E x, U y);
Dieser Operator wird genau wie ausgewertet
(E)((U)x - y)
.This operator is evaluated exactly as(E)((U)x - y)
. Mit anderen Worten, der Operator subtrahiert einen Wert vom zugrunde liegenden Typ der Enumeration und gibt einen Wert der-Enumeration aus.In other words, the operator subtracts a value from the underlying type of the enumeration, yielding a value of the enumeration.Entfernen von Delegaten.Delegate removal. Jeder Delegattyp stellt implizit den folgenden vordefinierten Operator bereit, wobei
D
der Delegattyp ist:Every delegate type implicitly provides the following predefined operator, whereD
is the delegate type:D operator -(D x, D y);
Der binäre
-
Operator führt eine Delegatentfernung aus, wenn beide Operanden einen Delegattyp habenD
.The binary-
operator performs delegate removal when both operands are of some delegate typeD
. Wenn die Operanden unterschiedliche Delegattypen aufweisen, tritt ein Bindungs Zeitfehler auf.If the operands have different delegate types, a binding-time error occurs. Ist der erste Operandnull
, ist das Ergebnis des Vorgangsnull
.If the first operand isnull
, the result of the operation isnull
. Andernfalls ist der zweite Operand, wenn der zweite Operand istnull
, das Ergebnis des Vorgangs der Wert des ersten Operanden.Otherwise, if the second operand isnull
, then the result of the operation is the value of the first operand. Andernfalls stellen beide Operanden Aufruf Listen (Delegatdeklarationen) dar, die über mindestens einen Eintrag verfügen, und das Ergebnis ist eine neue Aufruf Liste, die aus der ersten Operanden Liste besteht, aus der die Einträge des zweiten Operanden entfernt wurden, vorausgesetzt, die Liste des zweiten Operanden ist eine ordnungsgemäße zusammenhängende unter Liste der ersten.Otherwise, both operands represent invocation lists (Delegate declarations) having one or more entries, and the result is a new invocation list consisting of the first operand's list with the second operand's entries removed from it, provided the second operand's list is a proper contiguous sublist of the first's. (Um die Übereinstimmung zu ermitteln, werden die entsprechenden Einträge als für den Delegat-Gleichheits Operator (Delegat-Gleichheits Operatoren) verglichen.) Andernfalls ist das Ergebnis der Wert des linken Operanden.(To determine sublist equality, corresponding entries are compared as for the delegate equality operator (Delegate equality operators).) Otherwise, the result is the value of the left operand. Die Listen der Operanden werden im Prozess nicht geändert.Neither of the operands' lists is changed in the process. Wenn die Liste des zweiten Operanden mit mehreren Unterlisten zusammenhängender Einträge in der Liste der ersten Operanden übereinstimmt, wird die am weitesten rechts gerichtete unter Liste von zusammenhängenden Einträgen entfernt.If the second operand's list matches multiple sublists of contiguous entries in the first operand's list, the right-most matching sublist of contiguous entries is removed. Sollte durch die Entfernung eine leere Liste entstehen, ist das Ergebnisnull
.If removal results in an empty list, the result isnull
. Beispiel:For example:delegate void D(int x); class C { public static void M1(int i) { /* ... */ } public static void M2(int i) { /* ... */ } } class Test { static void Main() { D cd1 = new D(C.M1); D cd2 = new D(C.M2); D cd3 = cd1 + cd2 + cd2 + cd1; // M1 + M2 + M2 + M1 cd3 -= cd1; // => M1 + M2 + M2 cd3 = cd1 + cd2 + cd2 + cd1; // M1 + M2 + M2 + M1 cd3 -= cd1 + cd2; // => M2 + M1 cd3 = cd1 + cd2 + cd2 + cd1; // M1 + M2 + M2 + M1 cd3 -= cd2 + cd2; // => M1 + M1 cd3 = cd1 + cd2 + cd2 + cd1; // M1 + M2 + M2 + M1 cd3 -= cd2 + cd1; // => M1 + M2 cd3 = cd1 + cd2 + cd2 + cd1; // M1 + M2 + M2 + M1 cd3 -= cd1 + cd1; // => M1 + M2 + M2 + M1 } }
SchiebeoperatorenShift operators
Die <<
>>
Operatoren und werden verwendet, um Bitverschiebungs Vorgänge auszuführen.The <<
and >>
operators are used to perform bit shifting operations.
shift_expression
: additive_expression
| shift_expression '<<' additive_expression
| shift_expression right_shift additive_expression
;
Wenn ein Operand eines shift_expression den Kompilier Zeittyp aufweist dynamic
, wird der Ausdruck dynamisch gebunden (dynamische Bindung).If an operand of a shift_expression has the compile-time type dynamic
, then the expression is dynamically bound (Dynamic binding). In diesem Fall ist der Kompilier Zeittyp des Ausdrucks dynamic
, und die unten beschriebene Auflösung erfolgt zur Laufzeit mit dem Lauf Zeittyp der Operanden, die den Kompilier Zeittyp aufweisen dynamic
.In this case the compile-time type of the expression is dynamic
, and the resolution described below will take place at run-time using the run-time type of those operands that have the compile-time type dynamic
.
Bei einem Vorgang des Formulars x << count
oder x >> count
wird die binäre Operator Überladungs Auflösung (binäre Operator Überladungs Auflösung) angewendet, um eine bestimmte Operator Implementierung auszuwählen.For an operation of the form x << count
or x >> count
, binary operator overload resolution (Binary operator overload resolution) is applied to select a specific operator implementation. Die Operanden werden in die Parametertypen des ausgewählten Operators konvertiert, und der Ergebnistyp ist der Rückgabetyp des Operators.The operands are converted to the parameter types of the selected operator, and the type of the result is the return type of the operator.
Beim Deklarieren eines überladenen Verschiebungs Operators muss der Typ des ersten Operanden immer die Klasse oder Struktur sein, die die Operator Deklaration enthält, und der Typ des zweiten Operanden muss immer sein int
.When declaring an overloaded shift operator, the type of the first operand must always be the class or struct containing the operator declaration, and the type of the second operand must always be int
.
Die vordefinierten Shift-Operatoren sind unten aufgeführt.The predefined shift operators are listed below.
Nach links verschieben:Shift left:
int operator <<(int x, int count); uint operator <<(uint x, int count); long operator <<(long x, int count); ulong operator <<(ulong x, int count);
Der
<<
Operator verschiebtx
nach links um eine Anzahl von Bits, die wie unten beschrieben berechnet werden.The<<
operator shiftsx
left by a number of bits computed as described below.Die höherwertigen Bits außerhalb des Bereichs des Ergebnis Typs von
x
werden verworfen, die restlichen Bits werden nach links verschoben, und die unteren leeren Bitpositionen werden auf 0 (null) festgelegt.The high-order bits outside the range of the result type ofx
are discarded, the remaining bits are shifted left, and the low-order empty bit positions are set to zero.Nach rechts verschieben:Shift right:
int operator >>(int x, int count); uint operator >>(uint x, int count); long operator >>(long x, int count); ulong operator >>(ulong x, int count);
Der
>>
Operator verschiebt sichx
nach rechts um eine Anzahl von Bits, die wie unten beschrieben berechnet werden.The>>
operator shiftsx
right by a number of bits computed as described below.Wenn
x
int
den Typ oder aufweistlong
, werden die nieder wertigen Bits vonx
verworfen, die restlichen Bits werden nach rechts verschoben, und die übergeordnete leere Bitpositionen werden auf 0 (null) festgelegt, wennx
nicht negativ ist, und auf einen Wert festgelegt, wennx
negativ ist.Whenx
is of typeint
orlong
, the low-order bits ofx
are discarded, the remaining bits are shifted right, and the high-order empty bit positions are set to zero ifx
is non-negative and set to one ifx
is negative.Wenn
x
uint
den Typ oder aufweistulong
, werden die nieder wertigen Bits vonx
verworfen, die restlichen Bits werden nach rechts verschoben, und die obersten leeren Bitpositionen werden auf 0 (null) festgelegt.Whenx
is of typeuint
orulong
, the low-order bits ofx
are discarded, the remaining bits are shifted right, and the high-order empty bit positions are set to zero.
Für die vordefinierten Operatoren wird die Anzahl der zu Verschiebungs Bits wie folgt berechnet:For the predefined operators, the number of bits to shift is computed as follows:
- Wenn der Typ von
x
int
oder istuint
, wird die UMSCHALT Anzahl durch die nieder wertigen fünf Bits von angegebencount
.When the type ofx
isint
oruint
, the shift count is given by the low-order five bits ofcount
. Mit anderen Worten: die UMSCHALT Anzahl wird aus berechnetcount & 0x1F
.In other words, the shift count is computed fromcount & 0x1F
. - Wenn der Typ von
x
long
oder istulong
, wird die UMSCHALT Anzahl durch die nieder wertigen sechs Bits von angegebencount
.When the type ofx
islong
orulong
, the shift count is given by the low-order six bits ofcount
. Mit anderen Worten: die UMSCHALT Anzahl wird aus berechnetcount & 0x3F
.In other words, the shift count is computed fromcount & 0x3F
.
Wenn die resultierende Verschiebungs Anzahl 0 (null) ist, geben die Schiebe Operatoren einfach den Wert von zurück x
.If the resulting shift count is zero, the shift operators simply return the value of x
.
Verschiebungs Vorgänge verursachen niemals Überläufe und erzeugen dieselben Ergebnisse in checked
den unchecked
Kontexten und.Shift operations never cause overflows and produce the same results in checked
and unchecked
contexts.
Wenn der linke Operand des Operators einen ganzzahligen >>
Typ mit Vorzeichen hat, führt der Operator eine arithmetische Verschiebung nach rechts aus, in der der Wert des signifikantesten Bits (das Signier Bit) des Operanden an die übergeordnete leere Bitpositionen weitergegeben wird.When the left operand of the >>
operator is of a signed integral type, the operator performs an arithmetic shift right wherein the value of the most significant bit (the sign bit) of the operand is propagated to the high-order empty bit positions. Wenn der linke Operand des Operators einen ganzzahligen >>
Typ ohne Vorzeichen aufweist, führt der Operator eine logische Schiebe nach rechts aus, bei der die Positionen für die hohe Reihenfolge von leeren Bitpositionen immer auf NULL festgelegt sind.When the left operand of the >>
operator is of an unsigned integral type, the operator performs a logical shift right wherein high-order empty bit positions are always set to zero. Explizite Umwandlungen können verwendet werden, um den umgekehrten Vorgang von auszuführen, der vom Operanden-Typ abgeleitet wird.To perform the opposite operation of that inferred from the operand type, explicit casts can be used. Wenn z. b. x
eine Variable vom Typ ist int
, führt der Vorgang unchecked((int)((uint)x >> y))
eine logische Verschiebung rechts von aus x
.For example, if x
is a variable of type int
, the operation unchecked((int)((uint)x >> y))
performs a logical shift right of x
.
Relationale und TyptestoperatorenRelational and type-testing operators
Die ==
!=
<
Operatoren,,, >
, <=
, >=
is
und as
werden als relationale und Typtest Operatoren bezeichnet.The ==
, !=
, <
, >
, <=
, >=
, is
and as
operators are called the relational and type-testing operators.
relational_expression
: shift_expression
| relational_expression '<' shift_expression
| relational_expression '>' shift_expression
| relational_expression '<=' shift_expression
| relational_expression '>=' shift_expression
| relational_expression 'is' type
| relational_expression 'as' type
;
equality_expression
: relational_expression
| equality_expression '==' relational_expression
| equality_expression '!=' relational_expression
;
Der is
-Operator wird im is-Operator beschrieben, und der- as
Operator wird im as-Operatorbeschrieben.The is
operator is described in The is operator and the as
operator is described in The as operator.
Die ==
!=
<
Operatoren,,, >
<=
und >=
sind Vergleichs Operatoren.The ==
, !=
, <
, >
, <=
and >=
operators are comparison operators.
Wenn ein Operand eines Vergleichs Operators den Kompilier Zeittyp aufweist dynamic
, wird der Ausdruck dynamisch gebunden (dynamische Bindung).If an operand of a comparison operator has the compile-time type dynamic
, then the expression is dynamically bound (Dynamic binding). In diesem Fall ist der Kompilier Zeittyp des Ausdrucks dynamic
, und die unten beschriebene Auflösung erfolgt zur Laufzeit mit dem Lauf Zeittyp der Operanden, die den Kompilier Zeittyp aufweisen dynamic
.In this case the compile-time type of the expression is dynamic
, and the resolution described below will take place at run-time using the run-time type of those operands that have the compile-time type dynamic
.
Bei einem Vorgang der Form x
op y
, bei dem op ein Vergleichs Operator ist, wird die Überladungs Auflösung (binäre Operator Überladungs Auflösung) angewendet, um eine bestimmte Operator Implementierung auszuwählen.For an operation of the form x
op y
, where op is a comparison operator, overload resolution (Binary operator overload resolution) is applied to select a specific operator implementation. Die Operanden werden in die Parametertypen des ausgewählten Operators konvertiert, und der Ergebnistyp ist der Rückgabetyp des Operators.The operands are converted to the parameter types of the selected operator, and the type of the result is the return type of the operator.
Die vordefinierten Vergleichs Operatoren werden in den folgenden Abschnitten beschrieben.The predefined comparison operators are described in the following sections. Alle vordefinierten Vergleichs Operatoren geben ein Ergebnis vom Typ zurück bool
, wie in der folgenden Tabelle beschrieben.All predefined comparison operators return a result of type bool
, as described in the following table.
VorgangOperation | ErgebnisResult |
---|---|
x == y |
true``x , wenn gleich ist y , false andernfalls.true if x is equal to y , false otherwise |
x != y |
true , wenn ungleich x ist y , false andernfalls.true if x is not equal to y , false otherwise |
x < y |
true , wenn x kleiner ist als y , sonst false true if x is less than y , false otherwise |
x > y |
true , wenn x größer ist als y , sonst false true if x is greater than y , false otherwise |
x <= y |
true , wenn x kleiner als oder gleich y , sonst false true if x is less than or equal to y , false otherwise |
x >= y |
true , wenn x größer als oder gleich y , sonst false true if x is greater than or equal to y , false otherwise |
Integer-Vergleichs OperatorenInteger comparison operators
Die vordefinierten ganzzahligen Vergleichs Operatoren lauten wie folgt:The predefined integer comparison operators are:
bool operator ==(int x, int y);
bool operator ==(uint x, uint y);
bool operator ==(long x, long y);
bool operator ==(ulong x, ulong y);
bool operator !=(int x, int y);
bool operator !=(uint x, uint y);
bool operator !=(long x, long y);
bool operator !=(ulong x, ulong y);
bool operator <(int x, int y);
bool operator <(uint x, uint y);
bool operator <(long x, long y);
bool operator <(ulong x, ulong y);
bool operator >(int x, int y);
bool operator >(uint x, uint y);
bool operator >(long x, long y);
bool operator >(ulong x, ulong y);
bool operator <=(int x, int y);
bool operator <=(uint x, uint y);
bool operator <=(long x, long y);
bool operator <=(ulong x, ulong y);
bool operator >=(int x, int y);
bool operator >=(uint x, uint y);
bool operator >=(long x, long y);
bool operator >=(ulong x, ulong y);
Jeder dieser Operatoren vergleicht die numerischen Werte der beiden ganzzahligen Operanden und gibt einen bool
Wert zurück, der angibt, ob die jeweilige Beziehung true
oder ist false
.Each of these operators compares the numeric values of the two integer operands and returns a bool
value that indicates whether the particular relation is true
or false
.
Vergleichs Operatoren für Gleit Komma ZahlenFloating-point comparison operators
Die vordefinierten Gleit Komma Vergleichs Operatoren lauten wie folgt:The predefined floating-point comparison operators are:
bool operator ==(float x, float y);
bool operator ==(double x, double y);
bool operator !=(float x, float y);
bool operator !=(double x, double y);
bool operator <(float x, float y);
bool operator <(double x, double y);
bool operator >(float x, float y);
bool operator >(double x, double y);
bool operator <=(float x, float y);
bool operator <=(double x, double y);
bool operator >=(float x, float y);
bool operator >=(double x, double y);
Die Operanden werden von den Operatoren gemäß den Regeln des IEEE 754-Standards verglichen:The operators compare the operands according to the rules of the IEEE 754 standard:
Wenn einer der beiden Operanden NaN ist, gilt das Ergebnis
false
für alle Operatoren mit Ausnahme!=
von, für die das Ergebnis isttrue
.If either operand is NaN, the result isfalse
for all operators except!=
, for which the result istrue
. Bei zwei-Operandenx != y
erzeugt immer dasselbe Ergebnis wie!(x == y)
.For any two operands,x != y
always produces the same result as!(x == y)
. Wenn jedoch ein oder beide Operanden NaN sind, führen die<
>
<=
Operatoren,, und>=
nicht zu den gleichen Ergebnissen wie die logische Negation des umgekehrten Operators.However, when one or both operands are NaN, the<
,>
,<=
, and>=
operators do not produce the same results as the logical negation of the opposite operator. Wenn z. b. einer der beiden Optionenx
undy
NaN ist, dannx < y
istfalse
, aber!(x >= y)
isttrue
.For example, if either ofx
andy
is NaN, thenx < y
isfalse
, but!(x >= y)
istrue
.Wenn keiner der Operanden NaN ist, vergleichen die Operatoren die Werte der beiden Gleit Komma Operanden in Bezug auf die Reihenfolge.When neither operand is NaN, the operators compare the values of the two floating-point operands with respect to the ordering
-inf < -max < ... < -min < -0.0 == +0.0 < +min < ... < +max < +inf
min
max
dabei sind und die kleinsten und größten positiven Endwerte, die im angegebenen Gleit Komma Format dargestellt werden können.wheremin
andmax
are the smallest and largest positive finite values that can be represented in the given floating-point format. Wichtige Auswirkungen dieser Reihenfolge:Notable effects of this ordering are:- Negative und positive Nullen gelten als gleich.Negative and positive zeros are considered equal.
- Minus unendlich gilt als kleiner als alle anderen Werte, aber gleichbedeutend mit einem anderen negativen unendlich.A negative infinity is considered less than all other values, but equal to another negative infinity.
- Eine positive Unendlichkeit gilt als größer als alle anderen Werte, aber gleichbedeutend mit einer anderen positiven unendlich.A positive infinity is considered greater than all other values, but equal to another positive infinity.
Dezimale Vergleichs OperatorenDecimal comparison operators
Die vordefinierten dezimalen Vergleichs Operatoren lauten wie folgt:The predefined decimal comparison operators are:
bool operator ==(decimal x, decimal y);
bool operator !=(decimal x, decimal y);
bool operator <(decimal x, decimal y);
bool operator >(decimal x, decimal y);
bool operator <=(decimal x, decimal y);
bool operator >=(decimal x, decimal y);
Jeder dieser Operatoren vergleicht die numerischen Werte der beiden Decimal-Operanden und gibt einen bool
Wert zurück, der angibt, ob die jeweilige Beziehung true
oder ist false
.Each of these operators compares the numeric values of the two decimal operands and returns a bool
value that indicates whether the particular relation is true
or false
. Jeder Dezimal Vergleich entspricht der Verwendung des entsprechenden relationalen or-Gleichheits Operators vom Typ System.Decimal
.Each decimal comparison is equivalent to using the corresponding relational or equality operator of type System.Decimal
.
Boolesche Gleichheits OperatorenBoolean equality operators
Die vordefinierten booleschen Gleichheits Operatoren lauten wie folgt:The predefined boolean equality operators are:
bool operator ==(bool x, bool y);
bool operator !=(bool x, bool y);
Das Ergebnis von ==
ist, true
Wenn sowohl x
als auch y
sind true
oder wenn sowohl x
als y
false
auch gleich sind.The result of ==
is true
if both x
and y
are true
or if both x
and y
are false
. Andernfalls ist das Ergebnis false
.Otherwise, the result is false
.
Das Ergebnis von !=
ist, false
Wenn sowohl x
als auch y
sind true
oder wenn sowohl x
als y
false
auch gleich sind.The result of !=
is false
if both x
and y
are true
or if both x
and y
are false
. Andernfalls ist das Ergebnis true
.Otherwise, the result is true
. Wenn die Operanden den Typ bool
haben, !=
erzeugt der Operator dasselbe Ergebnis wie der ^
Operator.When the operands are of type bool
, the !=
operator produces the same result as the ^
operator.
EnumerationsvergleichsoperatorenEnumeration comparison operators
Jeder Enumerationstyp stellt implizit die folgenden vordefinierten Vergleichs Operatoren bereit:Every enumeration type implicitly provides the following predefined comparison operators:
bool operator ==(E x, E y);
bool operator !=(E x, E y);
bool operator <(E x, E y);
bool operator >(E x, E y);
bool operator <=(E x, E y);
bool operator >=(E x, E y);
Das Ergebnis der Auswertung von x op y
, wobei x
und y
Ausdrücke eines Enumerationstyps E
mit einem zugrunde liegenden Typ sind U
, und op
ist einer der Vergleichs Operatoren, ist identisch mit dem Auswerten von ((U)x) op ((U)y)
.The result of evaluating x op y
, where x
and y
are expressions of an enumeration type E
with an underlying type U
, and op
is one of the comparison operators, is exactly the same as evaluating ((U)x) op ((U)y)
. Mit anderen Worten, die Vergleichs Operatoren des Enumerationstyps vergleichen einfach die zugrunde liegenden ganzzahligen Werte der beiden Operanden.In other words, the enumeration type comparison operators simply compare the underlying integral values of the two operands.
Verweistyp-Gleichheits OperatorenReference type equality operators
Die vordefinierten Verweistyp-Gleichheits Operatoren sind:The predefined reference type equality operators are:
bool operator ==(object x, object y);
bool operator !=(object x, object y);
Die Operatoren geben das Ergebnis des Vergleichs der beiden Verweise auf Gleichheit oder nicht Gleichheit zurück.The operators return the result of comparing the two references for equality or non-equality.
Da die vordefinierten Verweistyp-Gleichheits Operatoren Operanden vom Typ akzeptieren object
, gelten Sie für alle Typen, die keine anwendbaren Elemente und Member deklarieren operator ==
operator !=
.Since the predefined reference type equality operators accept operands of type object
, they apply to all types that do not declare applicable operator ==
and operator !=
members. Im Gegensatz dazu Blenden alle anwendbaren benutzerdefinierten Gleichheits Operatoren die vordefinierten Verweistyp-Gleichheits Operatoren aus.Conversely, any applicable user-defined equality operators effectively hide the predefined reference type equality operators.
Die vordefinierten Verweistyp-Gleichheits Operatoren erfordern eine der folgenden:The predefined reference type equality operators require one of the following:
- Beide Operanden sind ein Wert eines Typs, der bekanntermaßen eine reference_type oder das Literale ist
null
.Both operands are a value of a type known to be a reference_type or the literalnull
. Darüber hinaus ist eine explizite Verweis Konvertierung (explizite Verweis Konvertierungen) vom Typ eines der beiden Operanden bis zum Typ des anderen Operanden vorhanden.Furthermore, an explicit reference conversion (Explicit reference conversions) exists from the type of either operand to the type of the other operand. - Ein Operand ist ein Wert vom Typ,
T
wobeiT
eine type_parameter und der andere Operand das Literale istnull
.One operand is a value of typeT
whereT
is a type_parameter and the other operand is the literalnull
. AußerdemT
weist nicht die Werttyp Einschränkung auf.FurthermoreT
does not have the value type constraint.
Wenn eine dieser Bedingungen nicht zutrifft, tritt ein Fehler bei der Bindung auf.Unless one of these conditions are true, a binding-time error occurs. Wichtige Implikationen dieser Regeln sind:Notable implications of these rules are:
- Es handelt sich um einen Bindungs Fehler, bei dem die vordefinierten Verweistyp-Gleichheits Operatoren verwendet werden, um zwei Verweise zu vergleichen, die bekanntermaßen bei der Bindungs Zeit unterschiedlich sind.It is a binding-time error to use the predefined reference type equality operators to compare two references that are known to be different at binding-time. Wenn die Bindungs Zeit Typen der Operanden z. b. zwei Klassentypen und sind
A
B
und wederA
nochB
vom anderen abgeleitet sind, kann es unmöglich sein, dass die beiden Operanden auf das gleiche Objekt verweisen.For example, if the binding-time types of the operands are two class typesA
andB
, and if neitherA
norB
derives from the other, then it would be impossible for the two operands to reference the same object. Daher wird der Vorgang als Bindungs Zeit Fehler betrachtet.Thus, the operation is considered a binding-time error. - Die vordefinierten Verweistyp-Gleichheits Operatoren lassen nicht zu, dass Werttyp Operanden verglichen werden.The predefined reference type equality operators do not permit value type operands to be compared. Daher ist es nicht möglich, Werte dieses Struktur Typs zu vergleichen, es sei denn, ein Strukturtyp deklariert seine eigenen Gleichheits Operatoren.Therefore, unless a struct type declares its own equality operators, it is not possible to compare values of that struct type.
- Die vordefinierten Verweistyp-Gleichheits Operatoren bewirken nie, dass Boxing-Vorgänge für ihre Operanden ausgeführt werden.The predefined reference type equality operators never cause boxing operations to occur for their operands. Es wäre bedeutungslos, solche Boxing-Vorgänge auszuführen, da Verweise auf die neu zugeordneten geachtelten Instanzen notwendigerweise von allen anderen verweisen abweichen.It would be meaningless to perform such boxing operations, since references to the newly allocated boxed instances would necessarily differ from all other references.
- Wenn ein Operand eines Typparameter Typs
T
mit verglichen wirdnull
und der Lauf Zeittyp vonT
ein Werttyp ist, ist das Ergebnis des Vergleichsfalse
.If an operand of a type parameter typeT
is compared tonull
, and the run-time type ofT
is a value type, the result of the comparison isfalse
.
Im folgenden Beispiel wird überprüft, ob ein Argument eines nicht eingeschränkten Typparameter Typs ist null
.The following example checks whether an argument of an unconstrained type parameter type is null
.
class C<T>
{
void F(T x) {
if (x == null) throw new ArgumentNullException();
...
}
}
Das x == null
-Konstrukt ist zulässig T
, obwohl einen Werttyp darstellen könnte, und das Ergebnis wird einfach als definiert, false
Wenn T
ein Werttyp ist.The x == null
construct is permitted even though T
could represent a value type, and the result is simply defined to be false
when T
is a value type.
Bei einem Vorgang im Formular x == y
oder x != y
, sofern zutreffend operator ==
oder operator !=
vorhanden, wählt die Operator Überladungs Auflösung (binäre Operator Überladungs Auflösung) diesen Operator anstelle des vordefinierten Verweistyp Gleichheits Operators aus.For an operation of the form x == y
or x != y
, if any applicable operator ==
or operator !=
exists, the operator overload resolution (Binary operator overload resolution) rules will select that operator instead of the predefined reference type equality operator. Es ist jedoch immer möglich, den vordefinierten Verweistyp Gleichheits Operator auszuwählen, indem eine oder beide der Operanden explizit in den Typ umgewandelt werden object
.However, it is always possible to select the predefined reference type equality operator by explicitly casting one or both of the operands to type object
. Das BeispielThe example
using System;
class Test
{
static void Main() {
string s = "Test";
string t = string.Copy(s);
Console.WriteLine(s == t);
Console.WriteLine((object)s == t);
Console.WriteLine(s == (object)t);
Console.WriteLine((object)s == (object)t);
}
}
erzeugt die Ausgabeproduces the output
True
False
False
False
Die s
t
Variablen und verweisen auf zwei unterschiedliche string
Instanzen, die die gleichen Zeichen enthalten.The s
and t
variables refer to two distinct string
instances containing the same characters. Der erste Vergleichswert True
gibt an, dass der vordefinierte Zeichen folgen Gleichheits Operator (Zeichen folgen GleichheitsOperator) ausgewählt ist, wenn beide Operanden vom Typ sind string
.The first comparison outputs True
because the predefined string equality operator (String equality operators) is selected when both operands are of type string
. Die verbleibenden Vergleiche werden alle ausgegeben, False
da der vordefinierte Verweistyp Gleichheits Operator ausgewählt wird, wenn einer oder beide Operanden den Typ haben object
.The remaining comparisons all output False
because the predefined reference type equality operator is selected when one or both of the operands are of type object
.
Beachten Sie, dass die oben beschriebene Technik für Werttypen nicht sinnvoll ist.Note that the above technique is not meaningful for value types. Das BeispielThe example
class Test
{
static void Main() {
int i = 123;
int j = 123;
System.Console.WriteLine((object)i == (object)j);
}
}
gibt Ausgaben False
aus, da die Umwandlungen Verweise auf zwei separate Instanzen von geboxten int
Werten erstellen.outputs False
because the casts create references to two separate instances of boxed int
values.
Operatoren für Zeichen folgenString equality operators
Die vordefinierten Zeichen folgen-Gleichheits Operatoren sind:The predefined string equality operators are:
bool operator ==(string x, string y);
bool operator !=(string x, string y);
Zwei string
Werte werden als gleich betrachtet, wenn eine der folgenden Punkte zutrifft:Two string
values are considered equal when one of the following is true:
- Beide Werte sind
null
.Both values arenull
. - Beide Werte sind Verweise ungleich NULL auf Zeichen folgen Instanzen, die identische Längen und identische Zeichen an jeder Zeichenposition aufweisen.Both values are non-null references to string instances that have identical lengths and identical characters in each character position.
Die Gleichheits Operatoren für Zeichen folgen vergleichen Zeichen folgen Werte anstelle von Zeichen folgen verweisen.The string equality operators compare string values rather than string references. Wenn zwei separate Zeichen folgen Instanzen genau dieselbe Zeichenfolge enthalten, sind die Werte der Zeichen folgen gleich, aber die Verweise unterscheiden sich.When two separate string instances contain the exact same sequence of characters, the values of the strings are equal, but the references are different. Wie in Verweistyp Gleichheits Operatorenbeschrieben, können die Verweistyp-Gleichheits Operatoren verwendet werden, um Zeichen folgen Verweise anstelle von Zeichen folgen Werten zu vergleichen.As described in Reference type equality operators, the reference type equality operators can be used to compare string references instead of string values.
DelegatenoperatorenDelegate equality operators
Jeder Delegattyp stellt implizit die folgenden vordefinierten Vergleichs Operatoren bereit:Every delegate type implicitly provides the following predefined comparison operators:
bool operator ==(System.Delegate x, System.Delegate y);
bool operator !=(System.Delegate x, System.Delegate y);
Zwei Delegatinstanzen werden wie folgt als gleich betrachtet:Two delegate instances are considered equal as follows:
- Wenn eine der Delegatinstanzen ist
null
, sind Sie nur dann gleich, wenn beide gleich sindnull
.If either of the delegate instances isnull
, they are equal if and only if both arenull
. - Wenn die Delegaten einen anderen Lauf Zeittyp aufweisen, sind Sie nie gleich.If the delegates have different run-time type they are never equal.
- Wenn beide Delegatinstanzen über eine Aufruf Liste (Delegatdeklarationen) verfügen, sind diese Instanzen nur dann gleich, wenn Ihre Aufruf Listen dieselbe Länge aufweisen und jeder Eintrag in einer Aufruf Liste (wie unten definiert) dem entsprechenden Eintrag in der Reihenfolge in der Aufruf Liste eines anderen entspricht.If both of the delegate instances have an invocation list (Delegate declarations), those instances are equal if and only if their invocation lists are the same length, and each entry in one's invocation list is equal (as defined below) to the corresponding entry, in order, in the other's invocation list.
Die folgenden Regeln bestimmen die Gleichheit von Aufruf Listeneinträgen:The following rules govern the equality of invocation list entries:
- Wenn zwei Aufruf Listeneinträge auf dieselbe statische Methode verweisen, sind die Einträge gleich.If two invocation list entries both refer to the same static method then the entries are equal.
- Wenn zwei Aufruf Listeneinträge auf dieselbe nicht statische Methode im gleichen Zielobjekt verweisen (wie durch die Verweis Gleichheits Operatoren definiert), sind die Einträge gleich.If two invocation list entries both refer to the same non-static method on the same target object (as defined by the reference equality operators) then the entries are equal.
- Aufruf Listeneinträge, die aus der Auswertung semantisch identischer anonymous_method_expression s oder lambda_expression s mit demselben (möglicherweise leeren) Satz erfasster externer Variablen Instanzen erstellt werden, sind zulässig (aber nicht erforderlich).Invocation list entries produced from evaluation of semantically identical anonymous_method_expression s or lambda_expression s with the same (possibly empty) set of captured outer variable instances are permitted (but not required) to be equal.
Gleichheits Operatoren und NULLEquality operators and null
Der ==
-Operator und der- !=
Operator gestatten einem Operanden einen Wert eines Typs, der NULL-Werte zulässt, und der andere als null
Literalwert, auch wenn kein vordefinierter oder benutzerdefinierter Operator für den Vorgang vorhanden ist.The ==
and !=
operators permit one operand to be a value of a nullable type and the other to be the null
literal, even if no predefined or user-defined operator (in unlifted or lifted form) exists for the operation.
Für einen Vorgang eines der FormulareFor an operation of one of the forms
x == null
null == x
x != null
null != x
dabei x
ist ein Ausdruck eines Typs, der NULL-Werte zulässt, wenn die Operator Überladungs Auflösung (binäre Operator Überladungs Auflösung) keinen anwendbaren Operator findet, wird das Ergebnis stattdessen aus der- HasValue
Eigenschaft von berechnet x
.where x
is an expression of a nullable type, if operator overload resolution (Binary operator overload resolution) fails to find an applicable operator, the result is instead computed from the HasValue
property of x
. Insbesondere werden die ersten beiden Formulare in übersetzt !x.HasValue
, und die letzten beiden Formulare werden in übersetzt x.HasValue
.Specifically, the first two forms are translated into !x.HasValue
, and last two forms are translated into x.HasValue
.
Der is-OperatorThe is operator
Der- is
Operator wird verwendet, um dynamisch zu überprüfen, ob der Lauf Zeittyp eines Objekts mit einem angegebenen Typ kompatibel ist.The is
operator is used to dynamically check if the run-time type of an object is compatible with a given type. Das Ergebnis des Vorgangs E is T
, wobei E
ein Ausdruck und T
ein Typ ist, ist ein boolescher Wert, der angibt, ob E
erfolgreich T
durch eine Verweis Konvertierung, eine Boxing-Konvertierung oder eine Unboxing-Konvertierung in den Typ konvertiert werden kann.The result of the operation E is T
, where E
is an expression and T
is a type, is a boolean value indicating whether E
can successfully be converted to type T
by a reference conversion, a boxing conversion, or an unboxing conversion. Der Vorgang wird wie folgt ausgewertet, nachdem Typargumente für alle Typparameter ersetzt wurden:The operation is evaluated as follows, after type arguments have been substituted for all type parameters:
- Wenn
E
eine anonyme Funktion ist, tritt ein Kompilierzeitfehler auf.IfE
is an anonymous function, a compile-time error occurs - Wenn
E
eine Methoden Gruppe oder dasnull
Literale ist, wenn der Typ vonE
ein Verweistyp oder ein Werte zulässt-Typ ist und der Wert vonE
NULL ist, ist das Ergebnis false.IfE
is a method group or thenull
literal, of if the type ofE
is a reference type or a nullable type and the value ofE
is null, the result is false. - Stellen Sie andernfalls
D
den dynamischen Typ vonE
wie folgt dar:Otherwise, letD
represent the dynamic type ofE
as follows:- Wenn der Typ von
E
ein Verweistyp ist,D
ist der Lauf Zeittyp des instanzverweises vonE
.If the type ofE
is a reference type,D
is the run-time type of the instance reference byE
. - Wenn der Typ von
E
ein Typ ist, der NULL-Werte zulässt,D
ist der zugrunde liegende Typ dieses Typs, der NULL-Werte zulässt.If the type ofE
is a nullable type,D
is the underlying type of that nullable type. - Wenn der Typ von
E
ein Werttyp ist, der keine NULL-Werte zulässt,D
ist der Typ vonE
.If the type ofE
is a non-nullable value type,D
is the type ofE
.
- Wenn der Typ von
- Das Ergebnis des Vorgangs hängt von
D
undT
wie folgt ab:The result of the operation depends onD
andT
as follows:- Wenn
T
ein Verweistyp ist, ist das Ergebnis true, wennD
undT
denselben Typ haben, wennD
ein Verweistyp und eine implizite Verweis Konvertierung vonD
in vorhanden istT
, oder wennD
ein Werttyp und eine Boxingkonvertierung vonD
in vorhanden istT
.IfT
is a reference type, the result is true ifD
andT
are the same type, ifD
is a reference type and an implicit reference conversion fromD
toT
exists, or ifD
is a value type and a boxing conversion fromD
toT
exists. - Wenn
T
ein Typ ist, der NULL-Werte zulässt, ist das Ergebnis true, wennD
der zugrunde liegende Typ von istT
.IfT
is a nullable type, the result is true ifD
is the underlying type ofT
. - Wenn
T
ein Werttyp ist, der keine NULL-Werte zulässt, ist das Ergebnis true, wennD
undT
denselben Typ haben.IfT
is a non-nullable value type, the result is true ifD
andT
are the same type. - Andernfalls ist das Ergebnis false.Otherwise, the result is false.
- Wenn
Beachten Sie, dass benutzerdefinierte Konvertierungen vom-Operator nicht berücksichtigt werden is
.Note that user defined conversions, are not considered by the is
operator.
Der as-OperatorThe as operator
Der- as
Operator wird verwendet, um einen Wert explizit in einen angegebenen Verweistyp oder Werte zulässt-Typ zu konvertieren.The as
operator is used to explicitly convert a value to a given reference type or nullable type. Anders als bei einem Umwandlungs Ausdruck (Cast-Ausdrücke) löst der as
Operator nie eine Ausnahme aus.Unlike a cast expression (Cast expressions), the as
operator never throws an exception. Wenn die angegebene Konvertierung nicht möglich ist, ist der resultierende Wert null
.Instead, if the indicated conversion is not possible, the resulting value is null
.
Bei einem Vorgang des Formulars E as T
E
muss ein Ausdruck sein, und er T
muss ein Verweistyp sein, ein Typparameter, der als Verweistyp bekannt ist, oder ein Typ, der NULL-Werte zulässt.In an operation of the form E as T
, E
must be an expression and T
must be a reference type, a type parameter known to be a reference type, or a nullable type. Außerdem muss mindestens einer der folgenden Punkte zutreffen. andernfalls tritt ein Kompilierzeitfehler auf:Furthermore, at least one of the following must be true, or otherwise a compile-time error occurs:
- Eine Identität (Identitäts Konvertierung), implizite NULL-Werte zulassen (implizit NULL-Wertezulassen), impliziter Verweis (implizite Verweis Konvertierungen), Boxing (Boxing-Konvertierungen), explizite NULL-Werte zulassen (explizite Konvertierungen, die NULL zulassen), expliziter Verweis (explizite Verweis Konvertierungen) oder Unboxing-Konvertierung (Unboxing-Konvertierung) von
E
inT
An identity (Identity conversion), implicit nullable (Implicit nullable conversions), implicit reference (Implicit reference conversions), boxing (Boxing conversions), explicit nullable (Explicit nullable conversions), explicit reference (Explicit reference conversions), or unboxing (Unboxing conversions) conversion exists fromE
toT
. - Der Typ von
E
oderT
ist ein offener Typ.The type ofE
orT
is an open type. E
ist dasnull
Literale.E
is thenull
literal.
Wenn der Kompilier Zeittyp von E
nicht ist dynamic
, erzeugt der Vorgang E as T
dasselbe Ergebnis wieIf the compile-time type of E
is not dynamic
, the operation E as T
produces the same result as
E is T ? (T)(E) : (T)null
außer dass E
nur einmal überprüft wird.except that E
is only evaluated once. Es ist zu erwarten, dass der Compiler E as T
eine Optimierung durchführt, um höchstens eine dynamische Typüberprüfung auszuführen, im Gegensatz zu den zwei dynamischen Typüberprüfungen, die von der obigen Erweiterung impliziert werden.The compiler can be expected to optimize E as T
to perform at most one dynamic type check as opposed to the two dynamic type checks implied by the expansion above.
Wenn der Kompilier Zeittyp von den Wert E
dynamic
hat, ist der Operator im Gegensatz zum Cast Operator as
nicht dynamisch gebunden (dynamische Bindung).If the compile-time type of E
is dynamic
, unlike the cast operator the as
operator is not dynamically bound (Dynamic binding). Daher ist die Erweiterung in diesem Fall:Therefore the expansion in this case is:
E is T ? (T)(object)(E) : (T)null
Beachten Sie, dass einige Konvertierungen, wie z. b. benutzerdefinierte Konvertierungen, mit dem-Operator nicht möglich sind as
und stattdessen mithilfe von Umwandlungs Ausdrücken ausgeführt werden.Note that some conversions, such as user defined conversions, are not possible with the as
operator and should instead be performed using cast expressions.
Im BeispielIn the example
class X
{
public string F(object o) {
return o as string; // OK, string is a reference type
}
public T G<T>(object o) where T: Attribute {
return o as T; // Ok, T has a class constraint
}
public U H<U>(object o) {
return o as U; // Error, U is unconstrained
}
}
der Typparameter T
von G
ist bekannt, dass es sich um einen Verweistyp handelt, da er die-Klassen Einschränkung aufweist.the type parameter T
of G
is known to be a reference type, because it has the class constraint. Der Typparameter U
von H
ist jedoch nicht zulässig. Daher ist die Verwendung des- as
Operators in unzulässig H
.The type parameter U
of H
is not however; hence the use of the as
operator in H
is disallowed.
Logische OperatorenLogical operators
Die &
^
|
Operatoren, und werden als logische Operatoren bezeichnet.The &
, ^
, and |
operators are called the logical operators.
and_expression
: equality_expression
| and_expression '&' equality_expression
;
exclusive_or_expression
: and_expression
| exclusive_or_expression '^' and_expression
;
inclusive_or_expression
: exclusive_or_expression
| inclusive_or_expression '|' exclusive_or_expression
;
Wenn ein Operand eines logischen Operators den Kompilier Zeittyp aufweist dynamic
, wird der Ausdruck dynamisch gebunden (dynamische Bindung).If an operand of a logical operator has the compile-time type dynamic
, then the expression is dynamically bound (Dynamic binding). In diesem Fall ist der Kompilier Zeittyp des Ausdrucks dynamic
, und die unten beschriebene Auflösung erfolgt zur Laufzeit mit dem Lauf Zeittyp der Operanden, die den Kompilier Zeittyp aufweisen dynamic
.In this case the compile-time type of the expression is dynamic
, and the resolution described below will take place at run-time using the run-time type of those operands that have the compile-time type dynamic
.
Bei einem Vorgang im Formular x op y
, bei dem op
es sich um einen der logischen Operatoren handelt, wird die Überladungs Auflösung (binäre Operator Überladungs Auflösung) angewendet, um eine bestimmte Operator Implementierung auszuwählen.For an operation of the form x op y
, where op
is one of the logical operators, overload resolution (Binary operator overload resolution) is applied to select a specific operator implementation. Die Operanden werden in die Parametertypen des ausgewählten Operators konvertiert, und der Ergebnistyp ist der Rückgabetyp des Operators.The operands are converted to the parameter types of the selected operator, and the type of the result is the return type of the operator.
Die vordefinierten logischen Operatoren werden in den folgenden Abschnitten beschrieben.The predefined logical operators are described in the following sections.
Ganz Zahl logische OperatorenInteger logical operators
Die vordefinierten ganzzahligen logischen Operatoren lauten wie folgt:The predefined integer logical operators are:
int operator &(int x, int y);
uint operator &(uint x, uint y);
long operator &(long x, long y);
ulong operator &(ulong x, ulong y);
int operator |(int x, int y);
uint operator |(uint x, uint y);
long operator |(long x, long y);
ulong operator |(ulong x, ulong y);
int operator ^(int x, int y);
uint operator ^(uint x, uint y);
long operator ^(long x, long y);
ulong operator ^(ulong x, ulong y);
Der- &
Operator berechnet die bitweise logische AND
der beiden Operanden, der |
-Operator berechnet die bitweise logische OR
der beiden Operanden, und der- ^
Operator berechnet das bitweise logische exklusive-Element der beiden- OR
Operanden.The &
operator computes the bitwise logical AND
of the two operands, the |
operator computes the bitwise logical OR
of the two operands, and the ^
operator computes the bitwise logical exclusive OR
of the two operands. Von diesen Vorgängen können keine über Flüsse durchlaufen werden.No overflows are possible from these operations.
Logische EnumerationsoperatorenEnumeration logical operators
Jeder Enumerationstyp E
stellt implizit die folgenden vordefinierten logischen Operatoren bereit:Every enumeration type E
implicitly provides the following predefined logical operators:
E operator &(E x, E y);
E operator |(E x, E y);
E operator ^(E x, E y);
Das Ergebnis der Auswertung von x op y
, wobei x
und y
Ausdrücke eines Enumerationstyps E
mit einem zugrunde liegenden Typ sind U
, und op
ist einer der logischen Operatoren, ist identisch mit dem Auswerten von (E)((U)x op (U)y)
.The result of evaluating x op y
, where x
and y
are expressions of an enumeration type E
with an underlying type U
, and op
is one of the logical operators, is exactly the same as evaluating (E)((U)x op (U)y)
. Mit anderen Worten: die logischen Operatoren des Enumerationstyps führen einfach die logische Operation für den zugrunde liegenden Typ der beiden Operanden aus.In other words, the enumeration type logical operators simply perform the logical operation on the underlying type of the two operands.
Logische boolesche OperatorenBoolean logical operators
Die vordefinierten booleschen logischen Operatoren lauten wie folgt:The predefined boolean logical operators are:
bool operator &(bool x, bool y);
bool operator |(bool x, bool y);
bool operator ^(bool x, bool y);
Das Ergebnis von x & y
ist true
, wenn sowohl x
als auch y
zu true
ausgewertet werden.The result of x & y
is true
if both x
and y
are true
. Andernfalls ist das Ergebnis false
.Otherwise, the result is false
.
Das Ergebnis von x | y
ist, true
Wenn entweder x
oder y
ist true
.The result of x | y
is true
if either x
or y
is true
. Andernfalls ist das Ergebnis false
.Otherwise, the result is false
.
Das Ergebnis von x ^ y
ist true
, wenn den Wert x
true
y
hat und ist false
, oder x
ist false
und ist y
true
.The result of x ^ y
is true
if x
is true
and y
is false
, or x
is false
and y
is true
. Andernfalls ist das Ergebnis false
.Otherwise, the result is false
. Wenn die Operanden vom Typ sind bool
, ^
berechnet der Operator dasselbe Ergebnis wie der !=
Operator.When the operands are of type bool
, the ^
operator computes the same result as the !=
operator.
Boolesche logische Operatoren, die NULL-Werte zulassenNullable boolean logical operators
Der booleschen-Typ, der NULL bool?
-Werte zulässt, kann drei Werte, true
, false
und darstellen null
und ist konzeptionell vergleichbar mit dem dreiwertigen Typ, der für boolesche Ausdrücke in SQL verwendet wird.The nullable boolean type bool?
can represent three values, true
, false
, and null
, and is conceptually similar to the three-valued type used for boolean expressions in SQL. Um sicherzustellen, dass die Ergebnisse, die von den &
|
bool?
Operatoren und für Operanden erzeugt werden, mit der dreiwertigen Logik von SQL übereinstimmen, werden die folgenden vordefinierten Operatoren bereitgestellt:To ensure that the results produced by the &
and |
operators for bool?
operands are consistent with SQL's three-valued logic, the following predefined operators are provided:
bool? operator &(bool? x, bool? y);
bool? operator |(bool? x, bool? y);
In der folgenden Tabelle werden die Ergebnisse aufgelistet, die von diesen Operatoren für alle Kombinationen der Werte true
, und erzeugt werden false
null
.The following table lists the results produced by these operators for all combinations of the values true
, false
, and null
.
x |
y |
x & y |
x | y |
---|---|---|---|
true |
true |
true |
true |
true |
false |
false |
true |
true |
null |
null |
true |
false |
true |
false |
true |
false |
false |
false |
false |
false |
null |
false |
null |
null |
true |
null |
true |
null |
false |
false |
null |
null |
null |
null |
null |
Bedingte logische OperatorenConditional logical operators
Die Operatoren &&
und ||
werden als bedingte logische Operatoren bezeichnet.The &&
and ||
operators are called the conditional logical operators. Sie werden auch als "Kurzschluss" logische Operatoren bezeichnet.They are also called the "short-circuiting" logical operators.
conditional_and_expression
: inclusive_or_expression
| conditional_and_expression '&&' inclusive_or_expression
;
conditional_or_expression
: conditional_and_expression
| conditional_or_expression '||' conditional_and_expression
;
Die &&
||
Operatoren und sind bedingte Versionen der &
-und- |
Operatoren:The &&
and ||
operators are conditional versions of the &
and |
operators:
- Der-Vorgang
x && y
entspricht dem-Vorgang, mit dem Unterschied,x & y
dassy
nur ausgewertet wird, wennx
nicht istfalse
.The operationx && y
corresponds to the operationx & y
, except thaty
is evaluated only ifx
is notfalse
. - Der-Vorgang
x || y
entspricht dem-Vorgang, mit dem Unterschied,x | y
dassy
nur ausgewertet wird, wennx
nicht isttrue
.The operationx || y
corresponds to the operationx | y
, except thaty
is evaluated only ifx
is nottrue
.
Wenn ein Operand eines bedingten logischen Operators den Kompilier Zeittyp aufweist dynamic
, wird der Ausdruck dynamisch gebunden (dynamische Bindung).If an operand of a conditional logical operator has the compile-time type dynamic
, then the expression is dynamically bound (Dynamic binding). In diesem Fall ist der Kompilier Zeittyp des Ausdrucks dynamic
, und die unten beschriebene Auflösung erfolgt zur Laufzeit mit dem Lauf Zeittyp der Operanden, die den Kompilier Zeittyp aufweisen dynamic
.In this case the compile-time type of the expression is dynamic
, and the resolution described below will take place at run-time using the run-time type of those operands that have the compile-time type dynamic
.
Ein Vorgang des Formulars x && y
oder x || y
wird durch Anwenden der Überladungs Auflösung (binäre Operator Überladungs Auflösung) so verarbeitet, als ob der Vorgang geschrieben wurde x & y
oder x | y
.An operation of the form x && y
or x || y
is processed by applying overload resolution (Binary operator overload resolution) as if the operation was written x & y
or x | y
. Dies ergibt folgende Szenarien:Then,
- Wenn die Überladungs Auflösung keinen einzelnen optimalen Operator findet oder wenn die Überladungs Auflösung einen der vordefinierten logischen ganzzahligen Operatoren auswählt, tritt ein Bindungs Zeitfehler auf.If overload resolution fails to find a single best operator, or if overload resolution selects one of the predefined integer logical operators, a binding-time error occurs.
- Andernfalls wird der Vorgang wie in booleschen bedingten logischenOperatoren beschrieben verarbeitet, wenn der ausgewählte Operator einer der vordefinierten booleschen logischen Operatoren (boolesche logische Operatoren) oder NULL-Werte zulässt.Otherwise, if the selected operator is one of the predefined boolean logical operators (Boolean logical operators) or nullable boolean logical operators (Nullable boolean logical operators), the operation is processed as described in Boolean conditional logical operators.
- Andernfalls ist der ausgewählte Operator ein benutzerdefinierter Operator, und der Vorgang wird wie unter Benutzerdefinierte bedingte logische Operatorenbeschrieben verarbeitet.Otherwise, the selected operator is a user-defined operator, and the operation is processed as described in User-defined conditional logical operators.
Es ist nicht möglich, die bedingten logischen Operatoren direkt zu überladen.It is not possible to directly overload the conditional logical operators. Da die bedingten logischen Operatoren jedoch in Bezug auf die regulären logischen Operatoren ausgewertet werden, sind über Ladungen der regulären logischen Operatoren mit bestimmten Einschränkungen auch als über Ladungen der bedingten logischen Operatoren zu berücksichtigen.However, because the conditional logical operators are evaluated in terms of the regular logical operators, overloads of the regular logical operators are, with certain restrictions, also considered overloads of the conditional logical operators. Dies wird weiter unten unter Benutzerdefinierte bedingte logische Operatorenbeschrieben.This is described further in User-defined conditional logical operators.
Boolesche bedingte logische OperatorenBoolean conditional logical operators
Wenn die Operanden von &&
oder ||
vom Typ sind bool
oder wenn es sich bei den Operanden um Typen handelt, die keinen anwendbaren operator &
oder definieren operator |
, aber implizite Konvertierungen in definieren, bool
wird der Vorgang wie folgt verarbeitet:When the operands of &&
or ||
are of type bool
, or when the operands are of types that do not define an applicable operator &
or operator |
, but do define implicit conversions to bool
, the operation is processed as follows:
- Der Vorgang
x && y
wird als ausgewertetx ? y : false
.The operationx && y
is evaluated asx ? y : false
. Anders ausgedrückt,x
wird zuerst ausgewertet und in den-Typ konvertiertbool
.In other words,x
is first evaluated and converted to typebool
. Wenn den Wert hat,x
true
y
wird ausgewertet und in den-Typ konvertiertbool
, und dies wird das Ergebnis des Vorgangs.Then, ifx
istrue
,y
is evaluated and converted to typebool
, and this becomes the result of the operation. Andernfalls ist das Ergebnis des Vorgangsfalse
.Otherwise, the result of the operation isfalse
. - Der Vorgang
x || y
wird als ausgewertetx ? true : y
.The operationx || y
is evaluated asx ? true : y
. Anders ausgedrückt,x
wird zuerst ausgewertet und in den-Typ konvertiertbool
.In other words,x
is first evaluated and converted to typebool
. Wenn den Wertx
true
hat, ist das Ergebnis des Vorgangstrue
.Then, ifx
istrue
, the result of the operation istrue
. Andernfallsy
wird ausgewertet und in den-Typ konvertiertbool
, und dies wird das Ergebnis des Vorgangs.Otherwise,y
is evaluated and converted to typebool
, and this becomes the result of the operation.
Benutzerdefinierte bedingte logische OperatorenUser-defined conditional logical operators
Wenn es sich bei den Operanden von &&
oder ||
um Typen handelt, die ein anwendbares benutzerdefiniertes oder deklarieren operator &
operator |
, müssen die beiden folgenden Optionen true sein, wobei T
der Typ ist, in dem der ausgewählte Operator deklariert ist:When the operands of &&
or ||
are of types that declare an applicable user-defined operator &
or operator |
, both of the following must be true, where T
is the type in which the selected operator is declared:
- Der Rückgabetyp und der Typ jedes Parameters des ausgewählten Operators müssen sein
T
.The return type and the type of each parameter of the selected operator must beT
. Mit anderen Worten, der-Operator muss das logischeAND
oder das logischeOR
von zwei Operanden vom Typ berechnenT
, und muss ein Ergebnis vom Typ zurückgebenT
.In other words, the operator must compute the logicalAND
or the logicalOR
of two operands of typeT
, and must return a result of typeT
. T
muss Deklarationen vonoperator true
und enthaltenoperator false
.T
must contain declarations ofoperator true
andoperator false
.
Ein Fehler bei der Bindungs Zeit tritt auf, wenn eine dieser Anforderungen nicht erfüllt wird.A binding-time error occurs if either of these requirements is not satisfied. Andernfalls wird der- &&
Vorgang oder der- ||
Vorgang ausgewertet, indem der benutzerdefinierte operator true
oder operator false
der ausgewählte benutzerdefinierte Operator kombiniert wird:Otherwise, the &&
or ||
operation is evaluated by combining the user-defined operator true
or operator false
with the selected user-defined operator:
- Der Vorgang
x && y
wird als ausgewertetT.false(x) ? x : T.&(x, y)
, wobeiT.false(x)
ein Aufruf von ist, deroperator false
in deklariert istT
, undT.&(x, y)
ein Aufruf des ausgewähltenoperator &
.The operationx && y
is evaluated asT.false(x) ? x : T.&(x, y)
, whereT.false(x)
is an invocation of theoperator false
declared inT
, andT.&(x, y)
is an invocation of the selectedoperator &
. Mit anderen Worten,x
wird zuerst ausgewertet und füroperator false
das Ergebnis aufgerufen, um zu bestimmen, obx
definitiv false ist.In other words,x
is first evaluated andoperator false
is invoked on the result to determine ifx
is definitely false. Wenn dannx
definitiv false ist, ist das Ergebnis der Operation der Wert, der zuvor für berechnet wurdex
.Then, ifx
is definitely false, the result of the operation is the value previously computed forx
. Andernfallsy
wird ausgewertet, und der ausgewählteoperator &
wird für den Wert aufgerufen, der zuvor für berechnet wurde,x
und der Wert, der für berechnet wird,y
um das Ergebnis des Vorgangs zu erhalten.Otherwise,y
is evaluated, and the selectedoperator &
is invoked on the value previously computed forx
and the value computed fory
to produce the result of the operation. - Der Vorgang
x || y
wird als ausgewertetT.true(x) ? x : T.|(x, y)
, wobeiT.true(x)
ein Aufruf von ist, deroperator true
in deklariert istT
, undT.|(x,y)
ein Aufruf des ausgewähltenoperator|
.The operationx || y
is evaluated asT.true(x) ? x : T.|(x, y)
, whereT.true(x)
is an invocation of theoperator true
declared inT
, andT.|(x,y)
is an invocation of the selectedoperator|
. Mit anderen Worten,x
wird zuerst ausgewertet und füroperator true
das Ergebnis aufgerufen, um zu bestimmen, obx
definitiv true ist.In other words,x
is first evaluated andoperator true
is invoked on the result to determine ifx
is definitely true. Wenn dannx
definitiv true ist, ist das Ergebnis der Operation der Wert, der zuvor für berechnet wurdex
.Then, ifx
is definitely true, the result of the operation is the value previously computed forx
. Andernfallsy
wird ausgewertet, und der ausgewählteoperator |
wird für den Wert aufgerufen, der zuvor für berechnet wurde,x
und der Wert, der für berechnet wird,y
um das Ergebnis des Vorgangs zu erhalten.Otherwise,y
is evaluated, and the selectedoperator |
is invoked on the value previously computed forx
and the value computed fory
to produce the result of the operation.
Bei beiden Vorgängen wird der von angegebene Ausdruck x
nur einmal ausgewertet, und der von angegebene Ausdruck y
wird entweder nicht genau einmal ausgewertet oder ausgewertet.In either of these operations, the expression given by x
is only evaluated once, and the expression given by y
is either not evaluated or evaluated exactly once.
Ein Beispiel für einen Typ, der operator true
und implementiert operator false
, finden Sie unter Daten Bank boolescher Typ.For an example of a type that implements operator true
and operator false
, see Database boolean type.
The null coalescing operator (Der NULL-Sammeloperator)The null coalescing operator
Der- ??
Operator wird als NULL-Sammel Operator bezeichnet.The ??
operator is called the null coalescing operator.
null_coalescing_expression
: conditional_or_expression
| conditional_or_expression '??' null_coalescing_expression
;
Ein NULL-Sammel Ausdruck des Formulars a ?? b
erfordert a
, dass ein Typ oder Verweistyp ist, der NULL-Werte zulässt.A null coalescing expression of the form a ?? b
requires a
to be of a nullable type or reference type. Wenn a
nicht NULL ist, ist das Ergebnis von a ?? b
a
. andernfalls ist das Ergebnis b
.If a
is non-null, the result of a ?? b
is a
; otherwise, the result is b
. Der Vorgang wertet b
nur aus, wenn a
NULL ist.The operation evaluates b
only if a
is null.
Der NULL-Sammel Operator ist rechts assoziativ, was bedeutet, dass Vorgänge von rechts nach Links gruppiert werden.The null coalescing operator is right-associative, meaning that operations are grouped from right to left. Beispielsweise wird ein Ausdruck des Formulars a ?? b ?? c
als ausgewertet a ?? (b ?? c)
.For example, an expression of the form a ?? b ?? c
is evaluated as a ?? (b ?? c)
. In der Regel gibt ein Ausdruck der Form E1 ?? E2 ?? ... ?? En
den ersten der Operanden zurück, der nicht NULL ist, oder NULL, wenn alle Operanden NULL sind.In general terms, an expression of the form E1 ?? E2 ?? ... ?? En
returns the first of the operands that is non-null, or null if all operands are null.
Der Typ des Ausdrucks a ?? b
hängt davon ab, welche impliziten Konvertierungen für die Operanden verfügbar sind.The type of the expression a ?? b
depends on which implicit conversions are available on the operands. In der angegebenen Reihenfolge ist der Typ a ?? b
von A0
, A
oder B
, wobei A
der Typ von a
(bereitgestellt ist, der einen- a
Typ aufweist), B
der Typ von b
(bereitgestellt mit b
einem-Typ) und A0
der zugrunde liegende Typ von ist, A
Wenn A
ein Typ ist, der NULL-Werte zulässt, A
andernfalls.In order of preference, the type of a ?? b
is A0
, A
, or B
, where A
is the type of a
(provided that a
has a type), B
is the type of b
(provided that b
has a type), and A0
is the underlying type of A
if A
is a nullable type, or A
otherwise. Insbesondere a ?? b
wird wie folgt verarbeitet:Specifically, a ?? b
is processed as follows:
- Wenn
A
vorhanden und kein Werte zulässt-Typ oder Verweistyp ist, tritt ein Kompilierzeitfehler auf.IfA
exists and is not a nullable type or a reference type, a compile-time error occurs. - Wenn
b
ein dynamischer Ausdruck ist, ist der Ergebnistypdynamic
.Ifb
is a dynamic expression, the result type isdynamic
. Zur Laufzeita
wird zuerst ausgewertet.At run-time,a
is first evaluated. Wenna
nicht NULL ist,a
wird in Dynamic konvertiert, und dies wird zum Ergebnis.Ifa
is not null,a
is converted to dynamic, and this becomes the result. Andernfallsb
wird ausgewertet, und dies wird zum Ergebnis.Otherwise,b
is evaluated, and this becomes the result. - Andernfalls
A
b
A0
ist der Ergebnistyp, wenn vorhanden und ein Typ ist, der NULL-Werte zulässt, und eine implizite Konvertierung von in vorhanden istA0
.Otherwise, ifA
exists and is a nullable type and an implicit conversion exists fromb
toA0
, the result type isA0
. Zur Laufzeita
wird zuerst ausgewertet.At run-time,a
is first evaluated. Wenna
nicht NULL ist,a
wird in den-Typ entpacktA0
, und dies wird zum Ergebnis.Ifa
is not null,a
is unwrapped to typeA0
, and this becomes the result. Andernfallsb
wird ausgewertet und inA0
den-Typ konvertiert, sodass dies das Ergebnis ist.Otherwise,b
is evaluated and converted to typeA0
, and this becomes the result. - Andernfalls
A
b
A
ist der Ergebnistyp, wenn vorhanden und eine implizite Konvertierung von in vorhanden istA
.Otherwise, ifA
exists and an implicit conversion exists fromb
toA
, the result type isA
. Zur Laufzeita
wird zuerst ausgewertet.At run-time,a
is first evaluated. Wenna
nicht NULL ist,a
wird das Ergebnis.Ifa
is not null,a
becomes the result. Andernfallsb
wird ausgewertet und inA
den-Typ konvertiert, sodass dies das Ergebnis ist.Otherwise,b
is evaluated and converted to typeA
, and this becomes the result. - Andernfalls
b
B
a
B
ist der Ergebnistyp, wenn einen-Typ aufweist und eine implizite Konvertierung von in vorhanden istB
.Otherwise, ifb
has a typeB
and an implicit conversion exists froma
toB
, the result type isB
. Zur Laufzeita
wird zuerst ausgewertet.At run-time,a
is first evaluated. Wenna
nicht NULL ist,a
wird in den-Typ entpacktA0
(wennA
vorhanden und NULL-Werte zulässt) und inB
den-Typ konvertiert werden. Dies wird zum Ergebnis.Ifa
is not null,a
is unwrapped to typeA0
(ifA
exists and is nullable) and converted to typeB
, and this becomes the result. Andernfallsb
wird ausgewertet und zum Ergebnis.Otherwise,b
is evaluated and becomes the result. - Andernfalls
a
sind und nichtb
kompatibel, und es tritt ein Kompilierzeitfehler auf.Otherwise,a
andb
are incompatible, and a compile-time error occurs.
Bedingter OperatorConditional operator
Der- ?:
Operator wird als Bedingter Operator bezeichnet.The ?:
operator is called the conditional operator. Es wird manchmal auch als ternärer Operator bezeichnet.It is at times also called the ternary operator.
conditional_expression
: null_coalescing_expression
| null_coalescing_expression '?' expression ':' expression
;
Ein bedingter Ausdruck des Formulars b ? x : y
wertet die Bedingung zuerst aus b
.A conditional expression of the form b ? x : y
first evaluates the condition b
. Wenn den Wert b
true
hat, x
wird ausgewertet und zum Ergebnis des Vorgangs.Then, if b
is true
, x
is evaluated and becomes the result of the operation. Andernfalls y
wird ausgewertet und wird zum Ergebnis des Vorgangs.Otherwise, y
is evaluated and becomes the result of the operation. Ein bedingter Ausdruck wertet nie sowohl x
als auch aus y
.A conditional expression never evaluates both x
and y
.
Der bedingte Operator ist rechts assoziativ, was bedeutet, dass Vorgänge von rechts nach Links gruppiert werden.The conditional operator is right-associative, meaning that operations are grouped from right to left. Beispielsweise wird ein Ausdruck des Formulars a ? b : c ? d : e
als ausgewertet a ? b : (c ? d : e)
.For example, an expression of the form a ? b : c ? d : e
is evaluated as a ? b : (c ? d : e)
.
Der erste Operand des ?:
Operators muss ein Ausdruck sein, der implizit in konvertiert werden kann bool
, oder ein Ausdruck eines Typs, der implementiert operator true
.The first operand of the ?:
operator must be an expression that can be implicitly converted to bool
, or an expression of a type that implements operator true
. Wenn keine dieser Anforderungen erfüllt ist, tritt ein Kompilierzeitfehler auf.If neither of these requirements is satisfied, a compile-time error occurs.
Mit dem zweiten und dritten Operanden x
y
des ?:
Operators wird der Typ des bedingten Ausdrucks gesteuert.The second and third operands, x
and y
, of the ?:
operator control the type of the conditional expression.
- Wenn den
x
Typ aufweistX
und deny
Typ hat,Y
dannIfx
has typeX
andy
has typeY
then- Wenn eine implizite Konvertierung (implizite Konvertierungen) von
X
inY
, aber nicht vonY
in vorhanden istX
, dannY
ist der Typ des bedingten Ausdrucks.If an implicit conversion (Implicit conversions) exists fromX
toY
, but not fromY
toX
, thenY
is the type of the conditional expression. - Wenn eine implizite Konvertierung (implizite Konvertierungen) von
Y
inX
, aber nicht vonX
in vorhanden istY
, dannX
ist der Typ des bedingten Ausdrucks.If an implicit conversion (Implicit conversions) exists fromY
toX
, but not fromX
toY
, thenX
is the type of the conditional expression. - Andernfalls kann kein Ausdruckstyp ermittelt werden, und es tritt ein Kompilierzeitfehler auf.Otherwise, no expression type can be determined, and a compile-time error occurs.
- Wenn eine implizite Konvertierung (implizite Konvertierungen) von
- Wenn nur einer von
x
undy
einen-Typ aufweist und sowohlx
als auchy
, von implizit in diesen Typ konvertiert werden können, ist dies der Typ des bedingten Ausdrucks.If only one ofx
andy
has a type, and bothx
andy
, of are implicitly convertible to that type, then that is the type of the conditional expression. - Andernfalls kann kein Ausdruckstyp ermittelt werden, und es tritt ein Kompilierzeitfehler auf.Otherwise, no expression type can be determined, and a compile-time error occurs.
Die Lauf Zeit Verarbeitung eines bedingten Ausdrucks der Form b ? x : y
besteht aus den folgenden Schritten:The run-time processing of a conditional expression of the form b ? x : y
consists of the following steps:
- Zuerst
b
wird ausgewertet, und derbool
Wert vonb
wird bestimmt:First,b
is evaluated, and thebool
value ofb
is determined:- Wenn eine implizite Konvertierung vom Typ von
b
inbool
vorhanden ist, wird diese implizite Konvertierung durchgeführt, um einenbool
Wert zu erhalten.If an implicit conversion from the type ofb
tobool
exists, then this implicit conversion is performed to produce abool
value. - Andernfalls wird die
operator true
, die durch den Typ von definiertb
wird, aufgerufen, um einen Wert zu erhaltenbool
.Otherwise, theoperator true
defined by the type ofb
is invoked to produce abool
value.
- Wenn eine implizite Konvertierung vom Typ von
- Wenn der
bool
durch den obigen Schritt erstellte Wert isttrue
,x
wird ausgewertet und in den Typ des bedingten Ausdrucks konvertiert, und dies wird das Ergebnis des bedingten Ausdrucks.If thebool
value produced by the step above istrue
, thenx
is evaluated and converted to the type of the conditional expression, and this becomes the result of the conditional expression. - Andernfalls
y
wird ausgewertet und in den Typ des bedingten Ausdrucks konvertiert, und dies wird das Ergebnis des bedingten Ausdrucks.Otherwise,y
is evaluated and converted to the type of the conditional expression, and this becomes the result of the conditional expression.
Anonymous function expressions (Anonyme Funktionsausdrücke)Anonymous function expressions
Eine anonyme Funktion ist ein Ausdruck, der eine "Inline"-Methoden Definition darstellt.An anonymous function is an expression that represents an "in-line" method definition. Eine anonyme Funktion verfügt nicht über einen Wert oder einen Typ in und von sich selbst, kann jedoch in einen kompatiblen Delegaten oder Ausdrucks Strukturtyp konvertiert werden.An anonymous function does not have a value or type in and of itself, but is convertible to a compatible delegate or expression tree type. Die Auswertung einer anonymen Funktions Konvertierung hängt vom Zieltyp der Konvertierung ab: Wenn es sich um einen Delegattyp handelt, wird die Konvertierung zu einem Delegatwert ausgewertet, der auf die Methode verweist, die von der anonymen Funktion definiert wird.The evaluation of an anonymous function conversion depends on the target type of the conversion: If it is a delegate type, the conversion evaluates to a delegate value referencing the method which the anonymous function defines. Wenn es sich um einen Ausdrucks bauentyp handelt, wird die Konvertierung zu einer Ausdrucks Baumstruktur ausgewertet, die die Struktur der Methode als Objektstruktur darstellt.If it is an expression tree type, the conversion evaluates to an expression tree which represents the structure of the method as an object structure.
Aus historischen Gründen gibt es zwei syntaktische Varianten von anonymen Funktionen, nämlich lambda_expression s und anonymous_method_expression s.For historical reasons there are two syntactic flavors of anonymous functions, namely lambda_expression s and anonymous_method_expression s. Für fast alle Zwecke sind lambda_expression s präziser und ausdrucksstarker als anonymous_method_expression s, die für die Abwärtskompatibilität in der Sprache verbleiben.For almost all purposes, lambda_expression s are more concise and expressive than anonymous_method_expression s, which remain in the language for backwards compatibility.
lambda_expression
: anonymous_function_signature '=>' anonymous_function_body
;
anonymous_method_expression
: 'delegate' explicit_anonymous_function_signature? block
;
anonymous_function_signature
: explicit_anonymous_function_signature
| implicit_anonymous_function_signature
;
explicit_anonymous_function_signature
: '(' explicit_anonymous_function_parameter_list? ')'
;
explicit_anonymous_function_parameter_list
: explicit_anonymous_function_parameter (',' explicit_anonymous_function_parameter)*
;
explicit_anonymous_function_parameter
: anonymous_function_parameter_modifier? type identifier
;
anonymous_function_parameter_modifier
: 'ref'
| 'out'
;
implicit_anonymous_function_signature
: '(' implicit_anonymous_function_parameter_list? ')'
| implicit_anonymous_function_parameter
;
implicit_anonymous_function_parameter_list
: implicit_anonymous_function_parameter (',' implicit_anonymous_function_parameter)*
;
implicit_anonymous_function_parameter
: identifier
;
anonymous_function_body
: expression
| block
;
Der Operator =>
verfügt über die gleiche Rangfolge wie die Zuweisung (=
) und ist rechtsassoziativ.The =>
operator has the same precedence as assignment (=
) and is right-associative.
Eine anonyme Funktion mit dem async
-Modifizierer ist eine Async-Funktion und folgt den in Async-Funktionenbeschriebenen Regeln.An anonymous function with the async
modifier is an async function and follows the rules described in Async functions.
Die Parameter einer anonymen Funktion in Form eines lambda_expression können explizit oder implizit eingegeben werden.The parameters of an anonymous function in the form of a lambda_expression can be explicitly or implicitly typed. In einer explizit typisierten Parameterliste wird der Typ jedes Parameters explizit angegeben.In an explicitly typed parameter list, the type of each parameter is explicitly stated. In einer implizit typisierten Parameterliste werden die Parametertypen aus dem Kontext abgeleitet, in dem die anonyme Funktion auftritt – insbesondere wenn die anonyme Funktion in einen kompatiblen Delegattyp oder Ausdrucks Strukturtyp konvertiert wird, stellt dieser Typ die Parametertypen (Anonyme Funktions Konvertierungen) bereit.In an implicitly typed parameter list, the types of the parameters are inferred from the context in which the anonymous function occurs—specifically, when the anonymous function is converted to a compatible delegate type or expression tree type, that type provides the parameter types (Anonymous function conversions).
In einer anonymen Funktion mit einem einzelnen, implizit typisierten Parameter können die Klammern in der Parameterliste weggelassen werden.In an anonymous function with a single, implicitly typed parameter, the parentheses may be omitted from the parameter list. Anders ausgedrückt: eine anonyme Funktion der FormIn other words, an anonymous function of the form
( param ) => expr
kann abgekürzt werden zucan be abbreviated to
param => expr
Die Parameterliste einer anonymen Funktion in Form einer anonymous_method_expression ist optional.The parameter list of an anonymous function in the form of an anonymous_method_expression is optional. Wenn angegeben, müssen die Parameter explizit typisiert werden.If given, the parameters must be explicitly typed. Andernfalls kann die anonyme Funktion in einen Delegaten mit einer beliebigen Parameterliste konvertiert werden, die keine out
Parameter enthält.If not, the anonymous function is convertible to a delegate with any parameter list not containing out
parameters.
Ein Block Körper einer anonymen Funktion ist erreichbar (Endpunkte und Erreichbarkeit), es sei denn, die anonyme Funktion tritt innerhalb einer nicht erreichbaren Anweisung auf.A block body of an anonymous function is reachable (End points and reachability) unless the anonymous function occurs inside an unreachable statement.
Im folgenden finden Sie einige Beispiele für anonyme Funktionen:Some examples of anonymous functions follow below:
x => x + 1 // Implicitly typed, expression body
x => { return x + 1; } // Implicitly typed, statement body
(int x) => x + 1 // Explicitly typed, expression body
(int x) => { return x + 1; } // Explicitly typed, statement body
(x, y) => x * y // Multiple parameters
() => Console.WriteLine() // No parameters
async (t1,t2) => await t1 + await t2 // Async
delegate (int x) { return x + 1; } // Anonymous method expression
delegate { return 1 + 1; } // Parameter list omitted
Das Verhalten von lambda_expression s und anonymous_method_expression s ist mit Ausnahme der folgenden Punkte identisch:The behavior of lambda_expression s and anonymous_method_expression s is the same except for the following points:
- anonymous_method_expression s erlauben, dass die Parameterliste vollständig ausgelassen wird, sodass die Konvertierungs Möglichkeit zum Delegieren von Typen von Wert Parametern ermöglicht wird.anonymous_method_expression s permit the parameter list to be omitted entirely, yielding convertibility to delegate types of any list of value parameters.
- lambda_expression s zulassen, dass Parametertypen ausgelassen und abgeleitet werden, während anonymous_method_expression s Parametertypen explizit angeben müssen.lambda_expression s permit parameter types to be omitted and inferred whereas anonymous_method_expression s require parameter types to be explicitly stated.
- Der Text eines lambda_expression kann ein Ausdruck oder ein Anweisungsblock sein, während der Text eines anonymous_method_expression ein Anweisungsblock sein muss.The body of a lambda_expression can be an expression or a statement block whereas the body of an anonymous_method_expression must be a statement block.
- Nur lambda_expression s verfügen über Konvertierungen in kompatible Ausdrucks Baumstruktur Typen (Ausdrucks Baumstruktur Typen).Only lambda_expression s have conversions to compatible expression tree types (Expression tree types).
Anonyme Funktions SignaturenAnonymous function signatures
Der optionale anonymous_function_signature einer anonymen Funktion definiert die Namen und optional die Typen der formalen Parameter für die anonyme Funktion.The optional anonymous_function_signature of an anonymous function defines the names and optionally the types of the formal parameters for the anonymous function. Der Gültigkeitsbereich der Parameter der anonymen Funktion ist der anonymous_function_body.The scope of the parameters of the anonymous function is the anonymous_function_body. (Bereiche) In Verbindung mit der Parameterliste (falls angegeben) bildet der anonyme Methoden Text einen Deklarations Raum (Deklarationen).(Scopes) Together with the parameter list (if given) the anonymous-method-body constitutes a declaration space (Declarations). Daher ist es ein Kompilierzeitfehler, wenn der Name eines Parameters der anonymen Funktion mit dem Namen einer lokalen Variablen, lokalen Konstante oder eines Parameters identisch ist, deren Bereich die anonymous_method_expression oder lambda_expression enthält.It is thus a compile-time error for the name of a parameter of the anonymous function to match the name of a local variable, local constant or parameter whose scope includes the anonymous_method_expression or lambda_expression.
Wenn eine anonyme Funktion über eine explicit_anonymous_function_signature verfügt, ist der Satz kompatibler Delegattypen und Ausdrucks Baum Typen auf diejenigen beschränkt, die dieselben Parametertypen und Modifizierer in der gleichen Reihenfolge aufweisen.If an anonymous function has an explicit_anonymous_function_signature, then the set of compatible delegate types and expression tree types is restricted to those that have the same parameter types and modifiers in the same order. Im Gegensatz zu Methoden Gruppen Konvertierungen (Methoden Gruppen Konvertierungen) wird die kontra Varianz anonymer Funktionsparameter Typen nicht unterstützt.In contrast to method group conversions (Method group conversions), contra-variance of anonymous function parameter types is not supported. Wenn eine anonyme Funktion keine anonymous_function_signature hat, ist der Satz kompatibler Delegattypen und Ausdrucks Baum Typen auf diejenigen beschränkt, die keine Parameter haben out
.If an anonymous function does not have an anonymous_function_signature, then the set of compatible delegate types and expression tree types is restricted to those that have no out
parameters.
Beachten Sie, dass ein anonymous_function_signature keine Attribute oder ein Parameter Array enthalten kann.Note that an anonymous_function_signature cannot include attributes or a parameter array. Dennoch kann ein anonymous_function_signature mit einem Delegattyp kompatibel sein, dessen Parameterliste ein Parameter Array enthält.Nevertheless, an anonymous_function_signature may be compatible with a delegate type whose parameter list contains a parameter array.
Beachten Sie auch, dass bei der Konvertierung in einen Ausdrucks bauentyp, auch wenn diese kompatibel ist, während der Kompilierzeit (Ausdrucks Baumstruktur Typen) weiterhin Fehler auftreten können.Note also that conversion to an expression tree type, even if compatible, may still fail at compile-time (Expression tree types).
Anonyme Funktions TexteAnonymous function bodies
Der Text (Ausdruck oder Block) einer anonymen Funktion unterliegt den folgenden Regeln:The body (expression or block) of an anonymous function is subject to the following rules:
- Wenn die anonyme Funktion eine Signatur enthält, sind die in der Signatur angegebenen Parameter im Textkörper verfügbar.If the anonymous function includes a signature, the parameters specified in the signature are available in the body. Wenn die anonyme Funktion keine Signatur aufweist, kann Sie in einen Delegattyp oder einen Ausdruckstyp mit Parametern (Anonyme Funktions Konvertierungen) konvertiert werden, aber auf die Parameter kann im Text nicht zugegriffen werden.If the anonymous function has no signature it can be converted to a delegate type or expression type having parameters (Anonymous function conversions), but the parameters cannot be accessed in the body.
- Mit Ausnahme
ref
von-oder-out
Parametern, die in der Signatur (sofern vorhanden) der nächstgelegenen einschließenden anonymen Funktion angegeben sind, ist dies ein Kompilierzeitfehler für den Text, um auf einen-ref
oder-out
Parameter zuzugreifenExcept forref
orout
parameters specified in the signature (if any) of the nearest enclosing anonymous function, it is a compile-time error for the body to access aref
orout
parameter. - Wenn der Typ von
this
ein Strukturtyp ist, ist dies ein Kompilierzeitfehler für den Text, auf den zugegriffen werden kannthis
.When the type ofthis
is a struct type, it is a compile-time error for the body to accessthis
. Dies gilt unabhängig davon, ob der Zugriff explizit (wie inthis.x
) oder implizit ist (wie in,x
wobeix
ein Instanzmember der Struktur ist).This is true whether the access is explicit (as inthis.x
) or implicit (as inx
wherex
is an instance member of the struct). Diese Regel verhindert einen solchen Zugriff und wirkt sich nicht darauf aus, ob die Member-Suche zu einem Member der Struktur führt.This rule simply prohibits such access and does not affect whether member lookup results in a member of the struct. - Der Text hat Zugriff auf die äußeren Variablen (äußere Variablen) der anonymen Funktion.The body has access to the outer variables (Outer variables) of the anonymous function. Der Zugriff auf eine äußere Variable verweist auf die Instanz der Variablen, die zum Zeitpunkt der Auswertung der lambda_expression oder anonymous_method_expression (Auswertung anonymer Funktions Ausdrücke) aktiv ist.Access of an outer variable will reference the instance of the variable that is active at the time the lambda_expression or anonymous_method_expression is evaluated (Evaluation of anonymous function expressions).
- Es ist ein Kompilierzeitfehler, wenn der Text eine
goto
Anweisung, einebreak
Anweisung oder eine Anweisung enthält,continue
deren Ziel außerhalb des Texts oder innerhalb des Texts einer enthaltenen anonymen Funktion liegt.It is a compile-time error for the body to contain agoto
statement,break
statement, orcontinue
statement whose target is outside the body or within the body of a contained anonymous function. - Eine-
return
Anweisung im Text gibt die Steuerung von einem Aufruf der nächsten einschließenden anonymen Funktion zurück, nicht vom einschließenden Funktionsmember.Areturn
statement in the body returns control from an invocation of the nearest enclosing anonymous function, not from the enclosing function member. Ein Ausdruck, der in einer-return
Anweisung angegeben ist, muss implizit in den Rückgabetyp des Delegattyps oder Ausdrucks Struktur Typs konvertiert werden, in den die nächstgelegene einschließende lambda_expression oder anonymous_method_expression konvertiert wird (Anonyme Funktions Konvertierungen).An expression specified in areturn
statement must be implicitly convertible to the return type of the delegate type or expression tree type to which the nearest enclosing lambda_expression or anonymous_method_expression is converted (Anonymous function conversions).
Es ist explizit nicht angegeben, ob es eine Möglichkeit gibt, den Block einer anonymen Funktion auszuführen, außer durch Auswertung und Aufruf der lambda_expression oder anonymous_method_expression.It is explicitly unspecified whether there is any way to execute the block of an anonymous function other than through evaluation and invocation of the lambda_expression or anonymous_method_expression. Insbesondere kann der Compiler eine anonyme Funktion durch das Zusammenführen einer oder mehrerer benannter Methoden oder Typen implementieren.In particular, the compiler may choose to implement an anonymous function by synthesizing one or more named methods or types. Die Namen dieser Elemente mit synthetischer kompilarverwendung müssen ein für die Compilerverwendung reserviertes Formular sein.The names of any such synthesized elements must be of a form reserved for compiler use.
Überladungs Auflösung und Anonyme FunktionenOverload resolution and anonymous functions
Anonyme Funktionen in einer Argumentliste sind an der Typrückschluss-und Überladungs Auflösung beteiligt.Anonymous functions in an argument list participate in type inference and overload resolution. Die genauen Regeln finden Sie unter Typrückschluss und Überladungs Auflösung .Please refer to Type inference and Overload resolution for the exact rules.
Das folgende Beispiel veranschaulicht die Auswirkung anonymer Funktionen auf die Überladungs Auflösung.The following example illustrates the effect of anonymous functions on overload resolution.
class ItemList<T>: List<T>
{
public int Sum(Func<T,int> selector) {
int sum = 0;
foreach (T item in this) sum += selector(item);
return sum;
}
public double Sum(Func<T,double> selector) {
double sum = 0;
foreach (T item in this) sum += selector(item);
return sum;
}
}
Die- ItemList<T>
Klasse verfügt über zwei Sum
Methoden.The ItemList<T>
class has two Sum
methods. Jede übernimmt ein- selector
Argument, das den Wert aus einem Listenelement in Summen extrahiert.Each takes a selector
argument, which extracts the value to sum over from a list item. Der extrahierte Wert kann entweder ein int
oder ein sein, double
und die resultierende Summe ist ebenfalls entweder ein int
oder ein double
.The extracted value can be either an int
or a double
and the resulting sum is likewise either an int
or a double
.
Die Sum
Methoden können z. b. verwendet werden, um Summen aus einer Liste von Detail Zeilen in einer Reihenfolge zu berechnen.The Sum
methods could for example be used to compute sums from a list of detail lines in an order.
class Detail
{
public int UnitCount;
public double UnitPrice;
...
}
void ComputeSums() {
ItemList<Detail> orderDetails = GetOrderDetails(...);
int totalUnits = orderDetails.Sum(d => d.UnitCount);
double orderTotal = orderDetails.Sum(d => d.UnitPrice * d.UnitCount);
...
}
Beim ersten Aufruf von orderDetails.Sum
Sum
sind beide Methoden anwendbar, da die anonyme Funktion d => d. UnitCount
sowohl mit als auch mit kompatibel Func<Detail,int>
ist Func<Detail,double>
.In the first invocation of orderDetails.Sum
, both Sum
methods are applicable because the anonymous function d => d. UnitCount
is compatible with both Func<Detail,int>
and Func<Detail,double>
. Die Überladungs Auflösung wählt jedoch die erste Sum
Methode aus, da die Konvertierung in Func<Detail,int>
besser ist als die Konvertierung in Func<Detail,double>
.However, overload resolution picks the first Sum
method because the conversion to Func<Detail,int>
is better than the conversion to Func<Detail,double>
.
Beim zweiten Aufruf von orderDetails.Sum
ist nur die zweite Sum
Methode anwendbar, da die anonyme Funktion d => d.UnitPrice * d.UnitCount
einen Wert vom Typ erzeugt double
.In the second invocation of orderDetails.Sum
, only the second Sum
method is applicable because the anonymous function d => d.UnitPrice * d.UnitCount
produces a value of type double
. Daher wählt die Überladungs Auflösung die zweite Sum
Methode für diesen Aufruf aus.Thus, overload resolution picks the second Sum
method for that invocation.
Anonyme Funktionen und dynamische BindungAnonymous functions and dynamic binding
Eine anonyme Funktion kann kein Empfänger, Argument oder Operand eines dynamisch gebundenen Vorgangs sein.An anonymous function cannot be a receiver, argument or operand of a dynamically bound operation.
Äußere VariablenOuter variables
Alle lokalen Variablen, Wert Parameter oder Parameter Arrays, deren Bereich die lambda_expression oder anonymous_method_expression enthält, werden als äußere Variable der anonymen Funktion bezeichnet.Any local variable, value parameter, or parameter array whose scope includes the lambda_expression or anonymous_method_expression is called an outer variable of the anonymous function. In einem Instanzfunktionsmember einer Klasse this
wird der Wert als Wert Parameter betrachtet und ist eine äußere Variable einer beliebigen anonymen Funktion, die im Funktionsmember enthalten ist.In an instance function member of a class, the this
value is considered a value parameter and is an outer variable of any anonymous function contained within the function member.
Erfasste äußere VariablenCaptured outer variables
Wenn auf eine äußere Variable durch eine anonyme Funktion verwiesen wird, wird die äußere Variable als von der anonymen Funktion aufgezeichnet .When an outer variable is referenced by an anonymous function, the outer variable is said to have been captured by the anonymous function. Normalerweise ist die Lebensdauer einer lokalen Variable auf die Ausführung des Blocks oder der Anweisung beschränkt, mit der Sie verknüpft ist (lokale Variablen).Ordinarily, the lifetime of a local variable is limited to execution of the block or statement with which it is associated (Local variables). Die Lebensdauer einer erfassten äußeren Variable wird jedoch mindestens so lange verlängert, bis der Delegat oder die Ausdrucks Struktur, der aus der anonymen Funktion erstellt wurde, für Garbage Collection qualifiziert wird.However, the lifetime of a captured outer variable is extended at least until the delegate or expression tree created from the anonymous function becomes eligible for garbage collection.
Im BeispielIn the example
using System;
delegate int D();
class Test
{
static D F() {
int x = 0;
D result = () => ++x;
return result;
}
static void Main() {
D d = F();
Console.WriteLine(d());
Console.WriteLine(d());
Console.WriteLine(d());
}
}
die lokale Variable x
wird von der anonymen Funktion aufgezeichnet, und die Lebensdauer von x
wird mindestens so lange verlängert, bis der Delegat, der von zurückgegeben wird, F
für Garbage Collection qualifiziert ist (was bis zum Ende des Programms nicht erfolgt).the local variable x
is captured by the anonymous function, and the lifetime of x
is extended at least until the delegate returned from F
becomes eligible for garbage collection (which doesn't happen until the very end of the program). Da jeder Aufruf der anonymen Funktion auf derselben Instanz von ausgeführt wird x
, lautet die Ausgabe des Beispiels wie folgt:Since each invocation of the anonymous function operates on the same instance of x
, the output of the example is:
1
2
3
Wenn eine lokale Variable oder ein value-Parameter von einer anonymen Funktion aufgezeichnet wird, wird die lokale Variable oder der Parameter nicht mehr als eine festgelegte Variable (fest-und verschiebbare Variablen) betrachtet, sondern als eine verschiebbare Variable angesehen.When a local variable or a value parameter is captured by an anonymous function, the local variable or parameter is no longer considered to be a fixed variable (Fixed and moveable variables), but is instead considered to be a moveable variable. Folglich unsafe
muss jeglicher Code, der die Adresse einer erfassten äußeren Variablen annimmt, zuerst die- fixed
Anweisung verwenden, um die Variable zu korrigieren.Thus any unsafe
code that takes the address of a captured outer variable must first use the fixed
statement to fix the variable.
Beachten Sie, dass im Gegensatz zu einer nicht erfassten Variablen eine aufgezeichnete lokale Variable gleichzeitig für mehrere Ausführungs Threads verfügbar gemacht werden kann.Note that unlike an uncaptured variable, a captured local variable can be simultaneously exposed to multiple threads of execution.
Instanziierung von lokalen VariablenInstantiation of local variables
Eine lokale Variable wird als instanziiert betrachtet, wenn die Ausführung in den Gültigkeitsbereich der Variablen eintritt.A local variable is considered to be instantiated when execution enters the scope of the variable. Wenn z. b. die folgende Methode aufgerufen wird, wird die lokale Variable x
dreimal instanziiert und initialisiert – einmal für jede Iterationen der Schleife.For example, when the following method is invoked, the local variable x
is instantiated and initialized three times—once for each iteration of the loop.
static void F() {
for (int i = 0; i < 3; i++) {
int x = i * 2 + 1;
...
}
}
Das Verschieben der Deklaration von x
außerhalb der Schleife führt jedoch zu einer einzelnen Instanziierung von x
:However, moving the declaration of x
outside the loop results in a single instantiation of x
:
static void F() {
int x;
for (int i = 0; i < 3; i++) {
x = i * 2 + 1;
...
}
}
Bei nicht Erfassung kann nicht genau beachtet werden, wie oft eine lokale Variable instanziiert wird – da die Lebensdauer der Instanziierungen disjunkt ist, kann jede Instanziierung einfach denselben Speicherort verwenden.When not captured, there is no way to observe exactly how often a local variable is instantiated—because the lifetimes of the instantiations are disjoint, it is possible for each instantiation to simply use the same storage location. Wenn eine anonyme Funktion jedoch eine lokale Variable erfasst, werden die Auswirkungen der Instanziierung offensichtlich.However, when an anonymous function captures a local variable, the effects of instantiation become apparent.
Das BeispielThe example
using System;
delegate void D();
class Test
{
static D[] F() {
D[] result = new D[3];
for (int i = 0; i < 3; i++) {
int x = i * 2 + 1;
result[i] = () => { Console.WriteLine(x); };
}
return result;
}
static void Main() {
foreach (D d in F()) d();
}
}
erzeugt die Ausgabe:produces the output:
1
3
5
Wenn jedoch die Deklaration von x
außerhalb der Schleife verschoben wird:However, when the declaration of x
is moved outside the loop:
static D[] F() {
D[] result = new D[3];
int x;
for (int i = 0; i < 3; i++) {
x = i * 2 + 1;
result[i] = () => { Console.WriteLine(x); };
}
return result;
}
die Ausgabe lautet:the output is:
5
5
5
Wenn eine for-Schleife eine Iterations Variable deklariert, wird die Variable selbst als außerhalb der Schleife deklariert.If a for-loop declares an iteration variable, that variable itself is considered to be declared outside of the loop. Wenn das Beispiel so geändert wird, dass die Iterations Variable selbst aufgezeichnet wird:Thus, if the example is changed to capture the iteration variable itself:
static D[] F() {
D[] result = new D[3];
for (int i = 0; i < 3; i++) {
result[i] = () => { Console.WriteLine(i); };
}
return result;
}
Es wird nur eine Instanz der Iterations Variablen aufgezeichnet, die die Ausgabe erzeugt:only one instance of the iteration variable is captured, which produces the output:
3
3
3
Es ist möglich, dass anonyme Funktions Delegaten einige erfasste Variablen freigeben, aber über separate Instanzen anderer Instanzen verfügen.It is possible for anonymous function delegates to share some captured variables yet have separate instances of others. Wenn beispielsweise F
in geändert wird.For example, if F
is changed to
static D[] F() {
D[] result = new D[3];
int x = 0;
for (int i = 0; i < 3; i++) {
int y = 0;
result[i] = () => { Console.WriteLine("{0} {1}", ++x, ++y); };
}
return result;
}
die drei Delegaten erfassen dieselbe Instanz von x
, aber separate Instanzen von y
, und die Ausgabe lautet:the three delegates capture the same instance of x
but separate instances of y
, and the output is:
1 1
2 1
3 1
Separate anonyme Funktionen können dieselbe Instanz einer äußeren Variablen erfassen.Separate anonymous functions can capture the same instance of an outer variable. Im Beispiel:In the example:
using System;
delegate void Setter(int value);
delegate int Getter();
class Test
{
static void Main() {
int x = 0;
Setter s = (int value) => { x = value; };
Getter g = () => { return x; };
s(5);
Console.WriteLine(g());
s(10);
Console.WriteLine(g());
}
}
die beiden anonymen Funktionen erfassen dieselbe Instanz der lokalen Variablen x
und können daher über diese Variable kommunizieren.the two anonymous functions capture the same instance of the local variable x
, and they can thus "communicate" through that variable. Die Ausgabe des Beispiels lautet wie folgt:The output of the example is:
5
10
Auswertung anonymer Funktions AusdrückeEvaluation of anonymous function expressions
Eine anonyme Funktion F
muss immer in einen Delegattyp D
oder einen Ausdrucks bauentyp konvertiert werden E
, entweder direkt oder durch die Ausführung eines Ausdrucks zum Erstellen eines new D(F)
Delegaten.An anonymous function F
must always be converted to a delegate type D
or an expression tree type E
, either directly or through the execution of a delegate creation expression new D(F)
. Diese Konvertierung bestimmt das Ergebnis der anonymen Funktion, wie in Anonyme Funktions Konvertierungenbeschrieben.This conversion determines the result of the anonymous function, as described in Anonymous function conversions.
AbfrageausdrückeQuery expressions
Abfrage Ausdrücke bieten eine sprach integrierte Syntax für Abfragen, die relationalen und hierarchischen Abfrage Sprachen wie SQL und XQuery ähneln.Query expressions provide a language integrated syntax for queries that is similar to relational and hierarchical query languages such as SQL and XQuery.
query_expression
: from_clause query_body
;
from_clause
: 'from' type? identifier 'in' expression
;
query_body
: query_body_clauses? select_or_group_clause query_continuation?
;
query_body_clauses
: query_body_clause
| query_body_clauses query_body_clause
;
query_body_clause
: from_clause
| let_clause
| where_clause
| join_clause
| join_into_clause
| orderby_clause
;
let_clause
: 'let' identifier '=' expression
;
where_clause
: 'where' boolean_expression
;
join_clause
: 'join' type? identifier 'in' expression 'on' expression 'equals' expression
;
join_into_clause
: 'join' type? identifier 'in' expression 'on' expression 'equals' expression 'into' identifier
;
orderby_clause
: 'orderby' orderings
;
orderings
: ordering (',' ordering)*
;
ordering
: expression ordering_direction?
;
ordering_direction
: 'ascending'
| 'descending'
;
select_or_group_clause
: select_clause
| group_clause
;
select_clause
: 'select' expression
;
group_clause
: 'group' expression 'by' expression
;
query_continuation
: 'into' identifier query_body
;
Ein Abfrage Ausdruck beginnt mit einer from
-Klausel und endet mit einer- select
oder- group
Klausel.A query expression begins with a from
clause and ends with either a select
or group
clause. Auf die Initial- from
Klausel können NULL oder mehr from
Klauseln, let
, where
oder join
folgen orderby
.The initial from
clause can be followed by zero or more from
, let
, where
, join
or orderby
clauses. Jede from
Klausel ist ein Generator, der eine *Range-Variable _ einführt, in der die Elemente einer _ -Sequenz * liegen.Each from
clause is a generator introducing a range variable _ which ranges over the elements of a _sequence**. Jede let
Klausel führt eine Bereichs Variable ein, die einen Wert darstellt, der mithilfe vorheriger Bereichs Variablen berechnet wurde.Each let
clause introduces a range variable representing a value computed by means of previous range variables. Jede- where
Klausel ist ein Filter, der Elemente aus dem Ergebnis ausschließt.Each where
clause is a filter that excludes items from the result. Jede join
Klausel vergleicht die angegebenen Schlüssel der Quell Sequenz mit Schlüsseln einer anderen Sequenz und gibt passende Paare aus.Each join
clause compares specified keys of the source sequence with keys of another sequence, yielding matching pairs. Jede- orderby
Klausel ordnet Elemente gemäß den angegebenen Kriterien neu an. Die abschließende- select
oder- group
Klausel gibt die Form des Ergebnisses in Bezug auf die Bereichs Variablen an.Each orderby
clause reorders items according to specified criteria.The final select
or group
clause specifies the shape of the result in terms of the range variables. Zum Schluss kann eine- into
Klausel verwendet werden, um Abfragen zu "Splice" zu verwenden, indem die Ergebnisse einer Abfrage als Generator in einer nachfolgenden Abfrage behandelt werden.Finally, an into
clause can be used to "splice" queries by treating the results of one query as a generator in a subsequent query.
Mehrdeutigkeiten in Abfrage AusdrückenAmbiguities in query expressions
Abfrage Ausdrücke enthalten eine Reihe von "Kontext Schlüsselwörtern", d. h. Bezeichner, die in einem bestimmten Kontext eine besondere Bedeutung haben.Query expressions contain a number of "contextual keywords", i.e., identifiers that have special meaning in a given context. Dabei handelt es sich insbesondere um from
, where
, join
, on
, equals
, into
, let
, orderby
, ascending
, descending
, select
group
und by
.Specifically these are from
, where
, join
, on
, equals
, into
, let
, orderby
, ascending
, descending
, select
, group
and by
. Um Mehrdeutigkeiten in Abfrage Ausdrücken zu vermeiden, die durch die gemischte Verwendung dieser Bezeichner als Schlüsselwörter oder einfache Namen verursacht werden, werden diese Bezeichner als Schlüsselwörter betrachtet, wenn Sie an einer beliebigen Stelle innerhalb eines Abfrage Ausdrucks auftreten.In order to avoid ambiguities in query expressions caused by mixed use of these identifiers as keywords or simple names, these identifiers are considered keywords when occurring anywhere within a query expression.
Zu diesem Zweck ist ein Abfrage Ausdruck ein beliebiger Ausdruck, der mit " from identifier
" gefolgt von einem beliebigen Token mit Ausnahme von "" ;
, " =
" oder " ,
" beginnt.For this purpose, a query expression is any expression that starts with "from identifier
" followed by any token except ";
", "=
" or ",
".
Um diese Wörter als Bezeichner innerhalb eines Abfrage Ausdrucks zu verwenden, kann Ihnen "" (Bezeichner) vorangestellt werden @
.In order to use these words as identifiers within a query expression, they can be prefixed with "@
" (Identifiers).
Abfrage Ausdrucks ÜbersetzungQuery expression translation
In der Programmiersprache c# ist die Ausführungs Semantik von Abfrage Ausdrücken nicht angegeben.The C# language does not specify the execution semantics of query expressions. Stattdessen werden Abfrage Ausdrücke in Aufrufe von Methoden übersetzt, die dem Abfrage Ausdrucksmuster (dem Abfrage Ausdrucksmuster) entsprechen.Rather, query expressions are translated into invocations of methods that adhere to the query expression pattern (The query expression pattern). Abfrage Ausdrücke werden insbesondere in Aufrufe von Methoden mit den Namen Where
, Select
, SelectMany
, Join
, GroupJoin
, OrderBy
, OrderByDescending
, ThenBy
, ThenByDescending
, und übersetzt GroupBy
Cast
. Diese Methoden verfügen über bestimmte Signaturen und Ergebnistypen, wie im Abfrage Ausdrucksmusterbeschrieben.Specifically, query expressions are translated into invocations of methods named Where
, Select
, SelectMany
, Join
, GroupJoin
, OrderBy
, OrderByDescending
, ThenBy
, ThenByDescending
, GroupBy
, and Cast
.These methods are expected to have particular signatures and result types, as described in The query expression pattern. Diese Methoden können Instanzmethoden des Objekts sein, das abgefragt wird, oder Erweiterungs Methoden, die sich außerhalb des Objekts befinden, und Sie implementieren die tatsächliche Ausführung der Abfrage.These methods can be instance methods of the object being queried or extension methods that are external to the object, and they implement the actual execution of the query.
Die Übersetzung von Abfrage Ausdrücken in Methodenaufrufe ist eine syntaktische Zuordnung, die vor der Durchführung einer Typbindung oder Überladungs Auflösung auftritt.The translation from query expressions to method invocations is a syntactic mapping that occurs before any type binding or overload resolution has been performed. Es ist garantiert, dass die Übersetzung syntaktisch korrekt ist, aber es wird nicht garantiert, dass semantisch korrekter c#-Code erzeugt wird.The translation is guaranteed to be syntactically correct, but it is not guaranteed to produce semantically correct C# code. Nach der Übersetzung von Abfrage Ausdrücken werden die resultierenden Methodenaufrufe als reguläre Methodenaufrufe verarbeitet. Dies kann wiederum zu Fehlern führen, z. b. wenn die Methoden nicht vorhanden sind, wenn Argumente falsche Typen aufweisen oder wenn die Methoden generisch sind und der Typrückschluss fehlschlägt.Following translation of query expressions, the resulting method invocations are processed as regular method invocations, and this may in turn uncover errors, for example if the methods do not exist, if arguments have wrong types, or if the methods are generic and type inference fails.
Ein Abfrage Ausdruck wird durch wiederholtes Anwenden der folgenden Übersetzungen verarbeitet, bis keine weiteren Reduzierungen möglich sind.A query expression is processed by repeatedly applying the following translations until no further reductions are possible. Die Übersetzungen werden in der Reihenfolge der Anwendung aufgelistet: in jedem Abschnitt wird davon ausgegangen, dass die Übersetzungen in den vorangehenden Abschnitten umfassend ausgeführt wurden, und sobald Sie aufgebraucht sind, wird ein Abschnitt bei der Verarbeitung desselben Abfrage Ausdrucks nicht mehr untersucht.The translations are listed in order of application: each section assumes that the translations in the preceding sections have been performed exhaustively, and once exhausted, a section will not later be revisited in the processing of the same query expression.
Die Zuweisung zu Bereichs Variablen ist in Abfrage Ausdrücken nicht zulässig.Assignment to range variables is not allowed in query expressions. Eine c#-Implementierung darf diese Einschränkung jedoch nicht immer erzwingen, da dies möglicherweise manchmal nicht mit dem hier dargestellten syntaktische Translation-Schema möglich ist.However a C# implementation is permitted to not always enforce this restriction, since this may sometimes not be possible with the syntactic translation scheme presented here.
Bestimmte Übersetzungen fügen Bereichs Variablen mit transparenten Bezeichner ein, die von angegeben werden *
.Certain translations inject range variables with transparent identifiers denoted by *
. Die besonderen Eigenschaften von transparenten bezeichmern werden in transparenten bezeichmernweiter erläutert.The special properties of transparent identifiers are discussed further in Transparent identifiers.
SELECT-und GroupBy-Klauseln mit FortsetzungenSelect and groupby clauses with continuations
Ein Abfrage Ausdruck mit einer FortsetzungA query expression with a continuation
from ... into x ...
wird übersetzt inis translated into
from x in ( from ... ) ...
Bei den Übersetzungen in den folgenden Abschnitten wird davon ausgegangen, dass Abfragen keine into
Fortsetzungen aufweisen.The translations in the following sections assume that queries have no into
continuations.
Das BeispielThe example
from c in customers
group c by c.Country into g
select new { Country = g.Key, CustCount = g.Count() }
wird übersetzt inis translated into
from g in
from c in customers
group c by c.Country
select new { Country = g.Key, CustCount = g.Count() }
die letzte Übersetzung, von derthe final translation of which is
customers.
GroupBy(c => c.Country).
Select(g => new { Country = g.Key, CustCount = g.Count() })
Explizite Bereichs Variablen TypenExplicit range variable types
Eine from
Klausel, die explizit einen Bereichs Variablentyp angibt.A from
clause that explicitly specifies a range variable type
from T x in e
wird übersetzt inis translated into
from x in ( e ) . Cast < T > ( )
Eine join
Klausel, die explizit einen Bereichs Variablentyp angibt.A join
clause that explicitly specifies a range variable type
join T x in e on k1 equals k2
wird übersetzt inis translated into
join x in ( e ) . Cast < T > ( ) on k1 equals k2
Bei den Übersetzungen in den folgenden Abschnitten wird davon ausgegangen, dass Abfragen keine expliziten Bereichs Variablen Typen aufweisen.The translations in the following sections assume that queries have no explicit range variable types.
Das BeispielThe example
from Customer c in customers
where c.City == "London"
select c
wird übersetzt inis translated into
from c in customers.Cast<Customer>()
where c.City == "London"
select c
die letzte Übersetzung, von derthe final translation of which is
customers.
Cast<Customer>().
Where(c => c.City == "London")
Explizite Bereichs Variablen Typen eignen sich zum Abfragen von Auflistungen, die die nicht generische- IEnumerable
Schnittstelle implementieren, nicht jedoch die generische- IEnumerable<T>
Schnittstelle.Explicit range variable types are useful for querying collections that implement the non-generic IEnumerable
interface, but not the generic IEnumerable<T>
interface. Im obigen Beispiel wäre dies der Fall, wenn customers
vom Typ wäre ArrayList
.In the example above, this would be the case if customers
were of type ArrayList
.
Degenerierte Abfrage AusdrückeDegenerate query expressions
Ein Abfrage Ausdruck der FormA query expression of the form
from x in e select x
wird übersetzt inis translated into
( e ) . Select ( x => x )
Das BeispielThe example
from c in customers
select c
wird übersetzt inis translated into
customers.Select(c => c)
Ein degenerierter Abfrage Ausdruck ist ein Ausdruck, der die Elemente der Quelle trivial auswählt.A degenerate query expression is one that trivially selects the elements of the source. In einer späteren Phase der Übersetzung werden degenerierte Abfragen entfernt, die durch andere Übersetzungsschritte eingeführt wurden, indem Sie durch ihre Quelle ersetzt werden.A later phase of the translation removes degenerate queries introduced by other translation steps by replacing them with their source. Es ist jedoch wichtig zu gewährleisten, dass das Ergebnis eines Abfrage Ausdrucks nie das Quell Objekt selbst ist, da dadurch der Typ und die Identität der Quelle für den Client der Abfrage offengelegt werden.It is important however to ensure that the result of a query expression is never the source object itself, as that would reveal the type and identity of the source to the client of the query. Daher schützt dieser Schritt degenerierte Abfragen, die direkt im Quellcode geschrieben wurden, indem explizit Select
für die Quelle aufgerufen wird.Therefore this step protects degenerate queries written directly in source code by explicitly calling Select
on the source. Dann werden die Implementierer von Select
und anderen Abfrage Operatoren übernommen, um sicherzustellen, dass diese Methoden nie das Quell Objekt selbst zurückgeben.It is then up to the implementers of Select
and other query operators to ensure that these methods never return the source object itself.
From-, Let-, WHERE-, Join-und OrderBy-KlauselnFrom, let, where, join and orderby clauses
Ein Abfrage Ausdruck mit einer zweiten from
Klausel gefolgt von einer- select
Klausel.A query expression with a second from
clause followed by a select
clause
from x1 in e1
from x2 in e2
select v
wird übersetzt inis translated into
( e1 ) . SelectMany( x1 => e2 , ( x1 , x2 ) => v )
Ein Abfrage Ausdruck mit einer zweiten from
Klausel, gefolgt von einem anderen Element als einer- select
Klausel:A query expression with a second from
clause followed by something other than a select
clause:
from x1 in e1
from x2 in e2
...
wird übersetzt inis translated into
from * in ( e1 ) . SelectMany( x1 => e2 , ( x1 , x2 ) => new { x1 , x2 } )
...
Ein Abfrage Ausdruck mit einer- let
Klausel.A query expression with a let
clause
from x in e
let y = f
...
wird übersetzt inis translated into
from * in ( e ) . Select ( x => new { x , y = f } )
...
Ein Abfrage Ausdruck mit einer- where
Klausel.A query expression with a where
clause
from x in e
where f
...
wird übersetzt inis translated into
from x in ( e ) . Where ( x => f )
...
Ein Abfrage Ausdruck mit einer- join
Klausel ohne, into
gefolgt von einer- select
Klausel.A query expression with a join
clause without an into
followed by a select
clause
from x1 in e1
join x2 in e2 on k1 equals k2
select v
wird übersetzt inis translated into
( e1 ) . Join( e2 , x1 => k1 , x2 => k2 , ( x1 , x2 ) => v )
Ein Abfrage Ausdruck mit einer- join
Klausel ohne, into
gefolgt von einem anderen als einer- select
Klausel.A query expression with a join
clause without an into
followed by something other than a select
clause
from x1 in e1
join x2 in e2 on k1 equals k2
...
wird übersetzt inis translated into
from * in ( e1 ) . Join( e2 , x1 => k1 , x2 => k2 , ( x1 , x2 ) => new { x1 , x2 })
...
Ein Abfrage Ausdruck mit einer- join
Klausel mit einer, into
gefolgt von einer- select
Klausel.A query expression with a join
clause with an into
followed by a select
clause
from x1 in e1
join x2 in e2 on k1 equals k2 into g
select v
wird übersetzt inis translated into
( e1 ) . GroupJoin( e2 , x1 => k1 , x2 => k2 , ( x1 , g ) => v )
Ein Abfrage Ausdruck mit einer- join
Klausel mit einem into
gefolgt von einer- select
Klausel.A query expression with a join
clause with an into
followed by something other than a select
clause
from x1 in e1
join x2 in e2 on k1 equals k2 into g
...
wird übersetzt inis translated into
from * in ( e1 ) . GroupJoin( e2 , x1 => k1 , x2 => k2 , ( x1 , g ) => new { x1 , g })
...
Ein Abfrage Ausdruck mit einer- orderby
Klausel.A query expression with an orderby
clause
from x in e
orderby k1 , k2 , ..., kn
...
wird übersetzt inis translated into
from x in ( e ) .
OrderBy ( x => k1 ) .
ThenBy ( x => k2 ) .
... .
ThenBy ( x => kn )
...
Wenn eine ORDER-Klausel einen descending
Richtungsindikator angibt, wird stattdessen ein Aufruf von OrderByDescending
oder ThenByDescending
erzeugt.If an ordering clause specifies a descending
direction indicator, an invocation of OrderByDescending
or ThenByDescending
is produced instead.
Bei den folgenden Übersetzungen wird davon ausgegangen, dass es keine let
where
join
-, orderby
-oder-Klauseln und nicht mehr als eine anfängliche- from
Klausel in jedem Abfrage Ausdruck gibt.The following translations assume that there are no let
, where
, join
or orderby
clauses, and no more than the one initial from
clause in each query expression.
Das BeispielThe example
from c in customers
from o in c.Orders
select new { c.Name, o.OrderID, o.Total }
wird übersetzt inis translated into
customers.
SelectMany(c => c.Orders,
(c,o) => new { c.Name, o.OrderID, o.Total }
)
Das BeispielThe example
from c in customers
from o in c.Orders
orderby o.Total descending
select new { c.Name, o.OrderID, o.Total }
wird übersetzt inis translated into
from * in customers.
SelectMany(c => c.Orders, (c,o) => new { c, o })
orderby o.Total descending
select new { c.Name, o.OrderID, o.Total }
die letzte Übersetzung, von derthe final translation of which is
customers.
SelectMany(c => c.Orders, (c,o) => new { c, o }).
OrderByDescending(x => x.o.Total).
Select(x => new { x.c.Name, x.o.OrderID, x.o.Total })
dabei x
ist ein vom Compiler generierter Bezeichner, der andernfalls unsichtbar ist und nicht zugänglich ist.where x
is a compiler generated identifier that is otherwise invisible and inaccessible.
Das BeispielThe example
from o in orders
let t = o.Details.Sum(d => d.UnitPrice * d.Quantity)
where t >= 1000
select new { o.OrderID, Total = t }
wird übersetzt inis translated into
from * in orders.
Select(o => new { o, t = o.Details.Sum(d => d.UnitPrice * d.Quantity) })
where t >= 1000
select new { o.OrderID, Total = t }
die letzte Übersetzung, von derthe final translation of which is
orders.
Select(o => new { o, t = o.Details.Sum(d => d.UnitPrice * d.Quantity) }).
Where(x => x.t >= 1000).
Select(x => new { x.o.OrderID, Total = x.t })
dabei x
ist ein vom Compiler generierter Bezeichner, der andernfalls unsichtbar ist und nicht zugänglich ist.where x
is a compiler generated identifier that is otherwise invisible and inaccessible.
Das BeispielThe example
from c in customers
join o in orders on c.CustomerID equals o.CustomerID
select new { c.Name, o.OrderDate, o.Total }
wird übersetzt inis translated into
customers.Join(orders, c => c.CustomerID, o => o.CustomerID,
(c, o) => new { c.Name, o.OrderDate, o.Total })
Das BeispielThe example
from c in customers
join o in orders on c.CustomerID equals o.CustomerID into co
let n = co.Count()
where n >= 10
select new { c.Name, OrderCount = n }
wird übersetzt inis translated into
from * in customers.
GroupJoin(orders, c => c.CustomerID, o => o.CustomerID,
(c, co) => new { c, co })
let n = co.Count()
where n >= 10
select new { c.Name, OrderCount = n }
die letzte Übersetzung, von derthe final translation of which is
customers.
GroupJoin(orders, c => c.CustomerID, o => o.CustomerID,
(c, co) => new { c, co }).
Select(x => new { x, n = x.co.Count() }).
Where(y => y.n >= 10).
Select(y => new { y.x.c.Name, OrderCount = y.n)
dabei x
sind und vom y
Compiler generierte Bezeichner, die ansonsten unsichtbar sind und nicht zugänglich sind.where x
and y
are compiler generated identifiers that are otherwise invisible and inaccessible.
Das BeispielThe example
from o in orders
orderby o.Customer.Name, o.Total descending
select o
hat die endgültige Übersetzunghas the final translation
orders.
OrderBy(o => o.Customer.Name).
ThenByDescending(o => o.Total)
Select-KlauselnSelect clauses
Ein Abfrage Ausdruck der FormA query expression of the form
from x in e select v
wird übersetzt inis translated into
( e ) . Select ( x => v )
mit der Ausnahme, dass v der Bezeichner x ist, ist die Übersetzung einfachexcept when v is the identifier x, the translation is simply
( e )
Beispiel:For example
from c in customers.Where(c => c.City == "London")
select c
wird einfach in übersetztis simply translated into
customers.Where(c => c.City == "London")
GroupBy-KlauselnGroupby clauses
Ein Abfrage Ausdruck der FormA query expression of the form
from x in e group v by k
wird übersetzt inis translated into
( e ) . GroupBy ( x => k , x => v )
außer wenn v der Bezeichner x ist, ist die Übersetzungexcept when v is the identifier x, the translation is
( e ) . GroupBy ( x => k )
Das BeispielThe example
from c in customers
group c.Name by c.Country
wird übersetzt inis translated into
customers.
GroupBy(c => c.Country, c => c.Name)
Transparente BezeichnerTransparent identifiers
Bestimmte Übersetzungen fügen Bereichs Variablen mit *transparenten Bezeichner _ ein, die von angegeben werden _
.Certain translations inject range variables with *transparent identifiers _ denoted by _
. Transparente Bezeichner sind keine ordnungsgemäße Sprachfunktion. Sie sind nur als Zwischenschritt im Übersetzungsprozess des Abfrage Ausdrucks vorhanden.Transparent identifiers are not a proper language feature; they exist only as an intermediate step in the query expression translation process.
Wenn eine Abfrage Übersetzung einen transparenten Bezeichner einfügt, verbreiten weitere Übersetzungsschritte den transparenten Bezeichner an anonyme Funktionen und anonyme Objektinitialisierer.When a query translation injects a transparent identifier, further translation steps propagate the transparent identifier into anonymous functions and anonymous object initializers. In diesen Kontexten weisen transparente Bezeichner folgendes Verhalten auf:In those contexts, transparent identifiers have the following behavior:
- Wenn ein transparenter Bezeichner als Parameter in einer anonymen Funktion auftritt, werden die Member des zugeordneten anonymen Typs automatisch im Gültigkeitsbereich des Texts der anonymen Funktion angezeigt.When a transparent identifier occurs as a parameter in an anonymous function, the members of the associated anonymous type are automatically in scope in the body of the anonymous function.
- Wenn sich ein Element mit einem transparenten Bezeichner im Gültigkeitsbereich befindet, sind die Member dieses Members ebenfalls im Gültigkeitsbereich.When a member with a transparent identifier is in scope, the members of that member are in scope as well.
- Wenn ein transparenter Bezeichner als Member-Deklarator in einem anonymen Objektinitialisierer auftritt, führt er einen Member mit einem transparenten Bezeichner ein.When a transparent identifier occurs as a member declarator in an anonymous object initializer, it introduces a member with a transparent identifier.
- In den oben beschriebenen Übersetzungs Schritten werden transparente Bezeichner immer mit anonymen Typen eingeführt, mit dem Ziel, mehrere Bereichs Variablen als Member eines einzelnen Objekts zu erfassen.In the translation steps described above, transparent identifiers are always introduced together with anonymous types, with the intent of capturing multiple range variables as members of a single object. Eine Implementierung von c# darf einen anderen Mechanismus als anonyme Typen verwenden, um mehrere Bereichs Variablen zu gruppieren.An implementation of C# is permitted to use a different mechanism than anonymous types to group together multiple range variables. In den folgenden Übersetzungs Beispielen wird davon ausgegangen, dass anonyme Typen verwendet werden, und es wird gezeigt, wie transparente Bezeichner übersetzt werden können.The following translation examples assume that anonymous types are used, and show how transparent identifiers can be translated away.
Das BeispielThe example
from c in customers
from o in c.Orders
orderby o.Total descending
select new { c.Name, o.Total }
wird übersetzt inis translated into
from * in customers.
SelectMany(c => c.Orders, (c,o) => new { c, o })
orderby o.Total descending
select new { c.Name, o.Total }
weiter übersetzt inwhich is further translated into
customers.
SelectMany(c => c.Orders, (c,o) => new { c, o }).
OrderByDescending(* => o.Total).
Select(* => new { c.Name, o.Total })
, die beim Löschen transparenter Bezeichner entspricht.which, when transparent identifiers are erased, is equivalent to
customers.
SelectMany(c => c.Orders, (c,o) => new { c, o }).
OrderByDescending(x => x.o.Total).
Select(x => new { x.c.Name, x.o.Total })
dabei x
ist ein vom Compiler generierter Bezeichner, der andernfalls unsichtbar ist und nicht zugänglich ist.where x
is a compiler generated identifier that is otherwise invisible and inaccessible.
Das BeispielThe example
from c in customers
join o in orders on c.CustomerID equals o.CustomerID
join d in details on o.OrderID equals d.OrderID
join p in products on d.ProductID equals p.ProductID
select new { c.Name, o.OrderDate, p.ProductName }
wird übersetzt inis translated into
from * in customers.
Join(orders, c => c.CustomerID, o => o.CustomerID,
(c, o) => new { c, o })
join d in details on o.OrderID equals d.OrderID
join p in products on d.ProductID equals p.ProductID
select new { c.Name, o.OrderDate, p.ProductName }
Dies wird weiter reduziert aufwhich is further reduced to
customers.
Join(orders, c => c.CustomerID, o => o.CustomerID, (c, o) => new { c, o }).
Join(details, * => o.OrderID, d => d.OrderID, (*, d) => new { *, d }).
Join(products, * => d.ProductID, p => p.ProductID, (*, p) => new { *, p }).
Select(* => new { c.Name, o.OrderDate, p.ProductName })
die letzte Übersetzung, von derthe final translation of which is
customers.
Join(orders, c => c.CustomerID, o => o.CustomerID,
(c, o) => new { c, o }).
Join(details, x => x.o.OrderID, d => d.OrderID,
(x, d) => new { x, d }).
Join(products, y => y.d.ProductID, p => p.ProductID,
(y, p) => new { y, p }).
Select(z => new { z.y.x.c.Name, z.y.x.o.OrderDate, z.p.ProductName })
dabei x
y
sind, und vom Compiler generierte Bezeichner z
, die andernfalls unsichtbar und nicht zugänglich sind.where x
, y
, and z
are compiler generated identifiers that are otherwise invisible and inaccessible.
Das Abfrage AusdrucksmusterThe query expression pattern
Das Abfrage Ausdrucksmuster stellt ein Muster von Methoden dar, die von Typen implementiert werden können, um Abfrage Ausdrücke zu unterstützen.The Query expression pattern establishes a pattern of methods that types can implement to support query expressions. Da Abfrage Ausdrücke über eine syntaktische Zuordnung in Methodenaufrufe übersetzt werden, haben Typen bei der Implementierung des Abfrage Ausdrucks Musters eine beträchtliche Flexibilität.Because query expressions are translated to method invocations by means of a syntactic mapping, types have considerable flexibility in how they implement the query expression pattern. Beispielsweise können die Methoden des Musters als Instanzmethoden oder als Erweiterungs Methoden implementiert werden, da beide die gleiche Aufruf Syntax aufweisen und die Methoden Delegaten oder Ausdrucks Baumstrukturen anfordern können, da anonyme Funktionen in beides konvertierbar sind.For example, the methods of the pattern can be implemented as instance methods or as extension methods because the two have the same invocation syntax, and the methods can request delegates or expression trees because anonymous functions are convertible to both.
Die empfohlene Form eines generischen Typs C<T>
, der das Abfrage Ausdrucksmuster unterstützt, ist unten dargestellt.The recommended shape of a generic type C<T>
that supports the query expression pattern is shown below. Ein generischer Typ wird verwendet, um die richtigen Beziehungen zwischen Parameter-und Ergebnistypen zu veranschaulichen, aber es ist auch möglich, das Muster für nicht generische Typen zu implementieren.A generic type is used in order to illustrate the proper relationships between parameter and result types, but it is possible to implement the pattern for non-generic types as well.
delegate R Func<T1,R>(T1 arg1);
delegate R Func<T1,T2,R>(T1 arg1, T2 arg2);
class C
{
public C<T> Cast<T>();
}
class C<T> : C
{
public C<T> Where(Func<T,bool> predicate);
public C<U> Select<U>(Func<T,U> selector);
public C<V> SelectMany<U,V>(Func<T,C<U>> selector,
Func<T,U,V> resultSelector);
public C<V> Join<U,K,V>(C<U> inner, Func<T,K> outerKeySelector,
Func<U,K> innerKeySelector, Func<T,U,V> resultSelector);
public C<V> GroupJoin<U,K,V>(C<U> inner, Func<T,K> outerKeySelector,
Func<U,K> innerKeySelector, Func<T,C<U>,V> resultSelector);
public O<T> OrderBy<K>(Func<T,K> keySelector);
public O<T> OrderByDescending<K>(Func<T,K> keySelector);
public C<G<K,T>> GroupBy<K>(Func<T,K> keySelector);
public C<G<K,E>> GroupBy<K,E>(Func<T,K> keySelector,
Func<T,E> elementSelector);
}
class O<T> : C<T>
{
public O<T> ThenBy<K>(Func<T,K> keySelector);
public O<T> ThenByDescending<K>(Func<T,K> keySelector);
}
class G<K,T> : C<T>
{
public K Key { get; }
}
Die oben genannten Methoden verwenden die generischen Delegattypen Func<T1,R>
und Func<T1,T2,R>
, aber Sie könnten auch andere Delegattypen von Delegaten oder Ausdrücken mit denselben Beziehungen in Parameter-und Ergebnistypen verwenden.The methods above use the generic delegate types Func<T1,R>
and Func<T1,T2,R>
, but they could equally well have used other delegate or expression tree types with the same relationships in parameter and result types.
Beachten Sie die empfohlene Beziehung zwischen C<T>
und O<T>
, wodurch sichergestellt wird, dass die ThenBy
-Methode und die- ThenByDescending
Methode nur für das Ergebnis eines oder verfügbar sind OrderBy
OrderByDescending
.Notice the recommended relationship between C<T>
and O<T>
which ensures that the ThenBy
and ThenByDescending
methods are available only on the result of an OrderBy
or OrderByDescending
. Beachten Sie auch die empfohlene Form des Ergebnisses von GroupBy
--eine Sequenz von Sequenzen, wobei jede innere Sequenz über eine zusätzliche Key
Eigenschaft verfügt.Also notice the recommended shape of the result of GroupBy
-- a sequence of sequences, where each inner sequence has an additional Key
property.
Der- System.Linq
Namespace stellt eine Implementierung des Abfrage Operator Musters für jeden Typ bereit, der die- System.Collections.Generic.IEnumerable<T>
Schnittstelle implementiert.The System.Linq
namespace provides an implementation of the query operator pattern for any type that implements the System.Collections.Generic.IEnumerable<T>
interface.
ZuweisungsoperatorenAssignment operators
Die Zuweisungs Operatoren weisen einer Variablen, einer Eigenschaft, einem Ereignis oder einem Indexer-Element einen neuen Wert zu.The assignment operators assign a new value to a variable, a property, an event, or an indexer element.
assignment
: unary_expression assignment_operator expression
;
assignment_operator
: '='
| '+='
| '-='
| '*='
| '/='
| '%='
| '&='
| '|='
| '^='
| '<<='
| right_shift_assignment
;
Der linke Operand einer Zuweisung muss ein Ausdruck sein, der als Variable, Eigenschaften Zugriff, Indexerzugriff oder Ereignis Zugriff klassifiziert ist.The left operand of an assignment must be an expression classified as a variable, a property access, an indexer access, or an event access.
Der- =
Operator wird als einfacher Zuweisungs Operator bezeichnet.The =
operator is called the simple assignment operator. Er weist den Wert des rechten Operanden der Variablen, der Eigenschaft oder dem Indexer-Element zu, die durch den linken Operanden angegeben werden.It assigns the value of the right operand to the variable, property, or indexer element given by the left operand. Der linke Operand des einfachen Zuweisungs Operators ist möglicherweise kein Ereignis Zugriff (außer wie in Feld ähnlichen Ereignissenbeschrieben).The left operand of the simple assignment operator may not be an event access (except as described in Field-like events). Der einfache Zuweisungs Operator wird unter einfache Zuweisungbeschrieben.The simple assignment operator is described in Simple assignment.
Die anderen Zuweisungs Operatoren als der- =
Operator werden als Verbund Zuweisungs Operatoren bezeichnet.The assignment operators other than the =
operator are called the compound assignment operators. Diese Operatoren führen den angegebenen Vorgang für die beiden Operanden aus und weisen dann den resultierenden Wert der Variablen, der Eigenschaft oder dem Indexer-Element zu, das durch den linken Operanden angegeben wird.These operators perform the indicated operation on the two operands, and then assign the resulting value to the variable, property, or indexer element given by the left operand. Die Verbund Zuweisungs Operatoren werden unter Verbund Zuweisungbeschrieben.The compound assignment operators are described in Compound assignment.
Die +=
-=
Operatoren und mit einem Ereignis Zugriffs Ausdruck als Linker Operand werden als Ereignis Zuweisungs Operatoren bezeichnet.The +=
and -=
operators with an event access expression as the left operand are called the event assignment operators. Kein anderer Zuweisungs Operator ist mit einem Ereignis Zugriff als Linker Operand gültig.No other assignment operator is valid with an event access as the left operand. Die Ereignis Zuweisungs Operatoren werden unter Ereignis Zuweisungbeschrieben.The event assignment operators are described in Event assignment.
Die Zuweisungs Operatoren sind rechts assoziativ, was bedeutet, dass Vorgänge von rechts nach Links gruppiert werden.The assignment operators are right-associative, meaning that operations are grouped from right to left. Beispielsweise wird ein Ausdruck des Formulars a = b = c
als ausgewertet a = (b = c)
.For example, an expression of the form a = b = c
is evaluated as a = (b = c)
.
Einfache ZuweisungSimple assignment
Der- =
Operator wird als einfacher Zuweisungs Operator bezeichnet.The =
operator is called the simple assignment operator.
Wenn der linke Operand einer einfachen Zuweisung das Format E.P
aufweist oder wenn E[Ei]
E
den Kompilier Zeittyp aufweist dynamic
, wird die Zuweisung dynamisch gebunden (dynamische Bindung).If the left operand of a simple assignment is of the form E.P
or E[Ei]
where E
has the compile-time type dynamic
, then the assignment is dynamically bound (Dynamic binding). In diesem Fall ist der Kompilier Zeittyp des Zuweisungs Ausdrucks dynamic
, und die unten beschriebene Auflösung erfolgt zur Laufzeit basierend auf dem Lauf Zeittyp von E
.In this case the compile-time type of the assignment expression is dynamic
, and the resolution described below will take place at run-time based on the run-time type of E
.
In einer einfachen Zuweisung muss der rechte Operand ein Ausdruck sein, der implizit in den Typ des linken Operanden konvertiert werden kann.In a simple assignment, the right operand must be an expression that is implicitly convertible to the type of the left operand. Der-Vorgang weist den Wert des rechten Operanden der Variablen, der Eigenschaft oder dem Indexer-Element zu, die durch den linken Operanden angegeben werden.The operation assigns the value of the right operand to the variable, property, or indexer element given by the left operand.
Das Ergebnis eines einfachen Zuweisungs Ausdrucks ist der Wert, der dem linken Operanden zugewiesen wird.The result of a simple assignment expression is the value assigned to the left operand. Das Ergebnis hat denselben Typ wie der linke Operand und wird immer als Wert klassifiziert.The result has the same type as the left operand and is always classified as a value.
Wenn der linke Operand eine Eigenschaft oder ein Indexer-Zugriff ist, muss die Eigenschaft oder der Indexer über einen set
Accessor verfügen.If the left operand is a property or indexer access, the property or indexer must have a set
accessor. Wenn dies nicht der Fall ist, tritt ein Bindungs Zeitfehler auf.If this is not the case, a binding-time error occurs.
Die Lauf Zeit Verarbeitung einer einfachen Zuweisung des Formulars x = y
besteht aus den folgenden Schritten:The run-time processing of a simple assignment of the form x = y
consists of the following steps:
- Wenn
x
als Variable klassifiziert ist:Ifx
is classified as a variable:x
wird ausgewertet, um die Variable zu entwickeln.x
is evaluated to produce the variable.y
wird ausgewertet und, falls erforderlich, durch eine implizite Konvertierung in den Typ von konvertiertx
(implizite Konvertierungen).y
is evaluated and, if required, converted to the type ofx
through an implicit conversion (Implicit conversions).- Wenn die von angegebene Variable
x
ein Array Element einer reference_type ist, wird eine Lauf Zeit Überprüfung durchgeführt, um sicherzustellen, dass der für berechnete Werty
mit der Array Instanz von kompatibel ist, bei derx
es sich um ein Element handelt.If the variable given byx
is an array element of a reference_type, a run-time check is performed to ensure that the value computed fory
is compatible with the array instance of whichx
is an element. Die Überprüfungy
ist erfolgreich, wenn istnull
, oder wenn eine implizite Verweis Konvertierung (implizite Verweis Konvertierungen) aus dem tatsächlichen Typ der Instanz vorhanden ist, auf die von verwiesen wird,y
auf den tatsächlichen Elementtyp der Array Instanz, die enthältx
.The check succeeds ify
isnull
, or if an implicit reference conversion (Implicit reference conversions) exists from the actual type of the instance referenced byy
to the actual element type of the array instance containingx
. Andernfalls wird eineSystem.ArrayTypeMismatchException
ausgelöst.Otherwise, aSystem.ArrayTypeMismatchException
is thrown. - Der Wert, der sich aus der Auswertung und Konvertierung von ergibt,
y
wird an dem Speicherort gespeichert, der durch die Auswertung von angegeben wirdx
.The value resulting from the evaluation and conversion ofy
is stored into the location given by the evaluation ofx
.
- Wenn
x
als Eigenschaft oder Indexer-Zugriff klassifiziert ist:Ifx
is classified as a property or indexer access:- Der Instanzausdruck (wenn
x
nicht iststatic
), und die Argumentliste (wennx
ein Indexer-Zugriff ist), die zugeordnet istx
, wird ausgewertet, und die Ergebnisse werden im nachfolgenden accessoraufruf verwendetset
.The instance expression (ifx
is notstatic
) and the argument list (ifx
is an indexer access) associated withx
are evaluated, and the results are used in the subsequentset
accessor invocation. y
wird ausgewertet und, falls erforderlich, durch eine implizite Konvertierung in den Typ von konvertiertx
(implizite Konvertierungen).y
is evaluated and, if required, converted to the type ofx
through an implicit conversion (Implicit conversions).- Der-
set
Accessor vonx
wird mit dem Wert aufgerufen, der füry
als sein-Argument berechnet wirdvalue
.Theset
accessor ofx
is invoked with the value computed fory
as itsvalue
argument.
- Der Instanzausdruck (wenn
Die Array-Co-Varianz Regeln (Array-Kovarianz) erlauben, dass ein Wert eines Arraytyps A[]
ein Verweis auf eine Instanz eines Arraytyps B[]
ist, vorausgesetzt, dass eine implizite Verweis Konvertierung von in vorhanden ist B
A
.The array co-variance rules (Array covariance) permit a value of an array type A[]
to be a reference to an instance of an array type B[]
, provided an implicit reference conversion exists from B
to A
. Aufgrund dieser Regeln erfordert die Zuweisung zu einem Array Element einer reference_type eine Lauf Zeit Überprüfung, um sicherzustellen, dass der zugewiesene Wert mit der Array Instanz kompatibel ist.Because of these rules, assignment to an array element of a reference_type requires a run-time check to ensure that the value being assigned is compatible with the array instance. Im BeispielIn the example
string[] sa = new string[10];
object[] oa = sa;
oa[0] = null; // Ok
oa[1] = "Hello"; // Ok
oa[2] = new ArrayList(); // ArrayTypeMismatchException
die letzte Zuweisung bewirkt System.ArrayTypeMismatchException
, dass eine ausgelöst wird, da eine Instanz von ArrayList
nicht in einem Element von gespeichert werden kann string[]
.the last assignment causes a System.ArrayTypeMismatchException
to be thrown because an instance of ArrayList
cannot be stored in an element of a string[]
.
Wenn eine in einem struct_type deklarierte Eigenschaft oder ein Indexer das Ziel einer Zuweisung ist, muss der Instanzausdruck, der der Eigenschaft oder dem Indexer-Zugriff zugeordnet ist, als Variable klassifiziert werden.When a property or indexer declared in a struct_type is the target of an assignment, the instance expression associated with the property or indexer access must be classified as a variable. Wenn der Instanzausdruck als Wert klassifiziert wird, tritt ein Fehler bei der Bindung auf.If the instance expression is classified as a value, a binding-time error occurs. Aufgrund des Mitglieds Zugriffsgilt die gleiche Regel auch für Felder.Because of Member access, the same rule also applies to fields.
Bei den Deklarationen:Given the declarations:
struct Point
{
int x, y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int X {
get { return x; }
set { x = value; }
}
public int Y {
get { return y; }
set { y = value; }
}
}
struct Rectangle
{
Point a, b;
public Rectangle(Point a, Point b) {
this.a = a;
this.b = b;
}
public Point A {
get { return a; }
set { a = value; }
}
public Point B {
get { return b; }
set { b = value; }
}
}
im Beispielin the example
Point p = new Point();
p.X = 100;
p.Y = 100;
Rectangle r = new Rectangle();
r.A = new Point(10, 10);
r.B = p;
die Zuweisungen für p.X
, p.Y
, r.A
und r.B
sind zulässig, da p
und r
Variablen sind.the assignments to p.X
, p.Y
, r.A
, and r.B
are permitted because p
and r
are variables. Im BeispielHowever, in the example
Rectangle r = new Rectangle();
r.A.X = 10;
r.A.Y = 10;
r.B.X = 100;
r.B.Y = 100;
die Zuweisungen sind ungültig, da r.A
und r.B
keine Variablen sind.the assignments are all invalid, since r.A
and r.B
are not variables.
VerbundzuweisungCompound assignment
Wenn der linke Operand einer Verbund Zuweisung das Format E.P
aufweist oder wenn E[Ei]
E
den Kompilier Zeittyp aufweist dynamic
, wird die Zuweisung dynamisch gebunden (dynamische Bindung).If the left operand of a compound assignment is of the form E.P
or E[Ei]
where E
has the compile-time type dynamic
, then the assignment is dynamically bound (Dynamic binding). In diesem Fall ist der Kompilier Zeittyp des Zuweisungs Ausdrucks dynamic
, und die unten beschriebene Auflösung erfolgt zur Laufzeit basierend auf dem Lauf Zeittyp von E
.In this case the compile-time type of the assignment expression is dynamic
, and the resolution described below will take place at run-time based on the run-time type of E
.
Ein Vorgang des Formulars x op= y
wird verarbeitet, indem die binäre Operator Überladungs Auflösung (binäre Operator Überladungs Auflösung) angewendet wird, als ob der Vorgang geschrieben wurde x op y
.An operation of the form x op= y
is processed by applying binary operator overload resolution (Binary operator overload resolution) as if the operation was written x op y
. Dies ergibt folgende Szenarien:Then,
- Wenn der Rückgabetyp des ausgewählten Operators implizit in den Typ von konvertiert
x
werden kann, wird der Vorgang als ausgewertetx = x op y
, mit der Ausnahme, dassx
nur einmal ausgewertet wird.If the return type of the selected operator is implicitly convertible to the type ofx
, the operation is evaluated asx = x op y
, except thatx
is evaluated only once. - Andernfalls wird, wenn der ausgewählte Operator ein vordefinierter Operator ist, der Rückgabetyp des ausgewählten Operators explizit in den Typ von konvertiert
x
werden kann, und wenny
implizit in den Typ von konvertiert werden kann,x
oder wenn der Operator ein Shift-Operator ist, wird der Vorgang als ausgewertetx = (T)(x op y)
, wobeiT
der Typ von istx
, außer dassx
nur einmal ausgewertet wird.Otherwise, if the selected operator is a predefined operator, if the return type of the selected operator is explicitly convertible to the type ofx
, and ify
is implicitly convertible to the type ofx
or the operator is a shift operator, then the operation is evaluated asx = (T)(x op y)
, whereT
is the type ofx
, except thatx
is evaluated only once. - Andernfalls ist die Verbund Zuweisung ungültig, und es tritt ein Bindungs Zeitfehler auf.Otherwise, the compound assignment is invalid, and a binding-time error occurs.
Der Begriff "nur einmal ausgewertet" bedeutet, dass bei der Auswertung von x op y
die Ergebnisse aller eingebenden Ausdrücke von x
temporär gespeichert und dann wieder verwendet werden, wenn die Zuweisung zu erfolgt x
.The term "evaluated only once" means that in the evaluation of x op y
, the results of any constituent expressions of x
are temporarily saved and then reused when performing the assignment to x
. Beispielsweise werden in der A()[B()] += C()
-Zuweisung, bei der A
eine Methode zurückgibt int[]
, und B
und C
sind Methoden zurückgegeben int
, die-Methoden nur einmal in der Reihenfolge, A
, aufgerufen B
C
.For example, in the assignment A()[B()] += C()
, where A
is a method returning int[]
, and B
and C
are methods returning int
, the methods are invoked only once, in the order A
, B
, C
.
Wenn der linke Operand einer Verbund Zuweisung ein Eigenschaften Zugriff oder ein Indexer-Zugriff ist, muss die Eigenschaft oder der Indexer sowohl einen get
-Accessor als auch einen- set
Accessor aufweisen.When the left operand of a compound assignment is a property access or indexer access, the property or indexer must have both a get
accessor and a set
accessor. Wenn dies nicht der Fall ist, tritt ein Bindungs Zeitfehler auf.If this is not the case, a binding-time error occurs.
Mit der zweiten obigen Regel x op= y
können Sie x = (T)(x op y)
in bestimmten Kontexten als ausgewertet werden.The second rule above permits x op= y
to be evaluated as x = (T)(x op y)
in certain contexts. Die Regel besteht darin, dass die vordefinierten Operatoren als Verbund Operatoren verwendet werden können, wenn der linke Operand vom Typ sbyte
, byte
, short
, ushort
oder ist char
.The rule exists such that the predefined operators can be used as compound operators when the left operand is of type sbyte
, byte
, short
, ushort
, or char
. Auch wenn beide Argumente von einem dieser Typen sind, führen die vordefinierten Operatoren zu einem Ergebnis vom Typ int
, wie in Binäre numerischeErweiterungen beschrieben.Even when both arguments are of one of those types, the predefined operators produce a result of type int
, as described in Binary numeric promotions. Daher wäre es ohne Umwandlung nicht möglich, das Ergebnis dem linken Operanden zuzuweisen.Thus, without a cast it would not be possible to assign the result to the left operand.
Die intuitive Auswirkung der Regel auf vordefinierte Operatoren ist nur x op= y
zulässig, wenn sowohl x op y
als auch zulässig x = y
sind.The intuitive effect of the rule for predefined operators is simply that x op= y
is permitted if both of x op y
and x = y
are permitted. Im BeispielIn the example
byte b = 0;
char ch = '\0';
int i = 0;
b += 1; // Ok
b += 1000; // Error, b = 1000 not permitted
b += i; // Error, b = i not permitted
b += (byte)i; // Ok
ch += 1; // Error, ch = 1 not permitted
ch += (char)1; // Ok
der intuitive Grund für jeden Fehler ist, dass eine entsprechende einfache Zuweisung ebenfalls ein Fehler wäre.the intuitive reason for each error is that a corresponding simple assignment would also have been an error.
Dies bedeutet auch, dass aufgesetzte Zuweisungs Vorgänge aufgesetzte Vorgänge unterstützen.This also means that compound assignment operations support lifted operations. Im BeispielIn the example
int? i = 0;
i += 1; // Ok
der Operator "angehoben" +(int?,int?)
wird verwendet.the lifted operator +(int?,int?)
is used.
Ereignis ZuweisungEvent assignment
Wenn der linke Operand eines +=
or- -=
Operators als Ereignis Zugriff klassifiziert ist, wird der Ausdruck wie folgt ausgewertet:If the left operand of a +=
or -=
operator is classified as an event access, then the expression is evaluated as follows:
- Der Instanzausdruck des Ereignis Zugriffs wird ausgewertet, falls vorhanden.The instance expression, if any, of the event access is evaluated.
- Der rechte Operand des
+=
Operators or-=
wird ausgewertet und, falls erforderlich, durch eine implizite Konvertierung in den Typ des linken Operanden konvertiert (implizite Konvertierungen).The right operand of the+=
or-=
operator is evaluated, and, if required, converted to the type of the left operand through an implicit conversion (Implicit conversions). - Ein Ereignis Accessor des Ereignisses wird mit einer Argumentliste aufgerufen, die den rechten Operanden nach der Auswertung und ggf. Konvertierung umfasst.An event accessor of the event is invoked, with argument list consisting of the right operand, after evaluation and, if necessary, conversion. Wenn der-Operator war
+=
,add
wird der-Accessor aufgerufen. wenn der-Operator war-=
, wird der-remove
Accessor aufgerufen.If the operator was+=
, theadd
accessor is invoked; if the operator was-=
, theremove
accessor is invoked.
Ein Ereignis Zuweisungs Ausdruck ergibt keinen Wert.