AusdrückeExpressions

Ein Ausdruck ist eine Sequenz von Operatoren und Operanden.An expression is a sequence of operators and operands. In diesem Kapitel wird die Syntax, die Reihenfolge der Auswertung von Operanden und Operatoren und Bedeutung von Ausdrücken definiert.This chapter defines the syntax, order of evaluation of operands and operators, and meaning of expressions.

AusdrucksklassifizierungenExpression 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 hat einen zugeordneten Typ, d. h. 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 verwendet werden, als der linken Seite von einem Member_access (Memberzugriff).An expression with this classification can only appear as the left hand side of a member_access (Member access). In einem anderen Kontext bewirkt, dass ein Ausdruck, der als Namespace klassifiziert einen Fehler während der Kompilierung.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 verwendet werden, als der linken Seite von einem Member_access (Memberzugriff), oder als Operand für die as Operator (den Operator ), wird die is Operator (der is-Operator), oder die typeof Operator (der Typeof-Operator).An expression with this classification can only appear as the left hand side of a member_access (Member access), or as an operand for the as operator (The as operator), the is operator (The is operator), or the typeof operator (The typeof operator). In einem anderen Kontext bewirkt, dass ein Ausdruck, der als Typ klassifiziert einen Fehler während der Kompilierung.In any other context, an expression classified as a type causes a compile-time error.
  • Eine Methodengruppe, ein Satz von überladenen Methoden, die sich aus einer Membersuche ergibt (Membersuche).A method group, which is a set of overloaded methods resulting from a member lookup (Member lookup). Eine Methodengruppe kann es sich um einen zugeordneten Instanzausdruck und einer Argumentliste für den zugeordneten Typ haben.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 Ausdrucks für die Instanz die Instanz, die durch dargestellt this (diesen Zugriff).When an instance method is invoked, the result of evaluating the instance expression becomes the instance represented by this (This access). Eine Methodengruppe ist zulässig, eine Invocation_expression (Aufrufausdrücke), ein Delegate_creation_expression (Delegaterstellung Ausdrücke) sowie der linken Seite des ein is-Operator, und in einen kompatiblen Delegattyp implizit konvertiert werden kann (Gruppe Konvertierungen).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 einem anderen Kontext bewirkt, dass ein Ausdruck, der als eine Methodengruppe klassifiziert einen Fehler während der Kompilierung.In any other context, an expression classified as a method group causes a compile-time error.
  • Ein null-Literal.A null literal. Ein Ausdruck mit dieser Klassifizierung kann implizit in einem Referenztyp oder nullable-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 bzw. den Typ für die Ausdrucksbaumstruktur konvertiert werden.An expression with this classification can be implicitly converted to a compatible delegate type or expression tree type.
  • Ein Eigenschaftenzugriff.A property access. Jedem Eigenschaftenzugriff ist einen zugeordneten Typ, d. h. den Typ der Eigenschaft.Every property access has an associated type, namely the type of the property. Darüber hinaus möglicherweise Zugriff auf eine Eigenschaft einen zugeordneten Instanzausdruck.Furthermore, a property access may have an associated instance expression. Wenn ein Accessor (die get oder set Block) einer Instanz der Zugriff auf Eigenschaften aufgerufen wird, das Ergebnis der Auswertung des Ausdrucks für die Instanz wird die Instanz, die durch dargestellt this (diesen Zugriff).When an accessor (the get or set block) of an instance property access is invoked, the result of evaluating the instance expression becomes the instance represented by this (This access).
  • Ein Event-Zugriff.An event access. Jedes Ereigniszugriff verfügt über einen zugeordneten Typ, d. h. den Typ des Ereignisses.Every event access has an associated type, namely the type of the event. Darüber hinaus kann ein Ereignis einen zugeordneten Instanzausdruck zugreifen.Furthermore, an event access may have an associated instance expression. Ein Ereigniszugriff möglicherweise angezeigt, wie der linke Operand des der += und -= Operatoren (Ereignis Zuweisung).An event access may appear as the left hand operand of the += and -= operators (Event assignment). In einem anderen Kontext bewirkt, dass ein Ausdruck, der klassifiziert als Zugriffs-Ereignis einen Fehler während der Kompilierung.In any other context, an expression classified as an event access causes a compile-time error.
  • Indexzugriff.An indexer access. Jeder Indexzugriff verfügt über einen zugeordneten Typ, d. h. der Elementtyp des Indexers.Every indexer access has an associated type, namely the element type of the indexer. Darüber hinaus hat Indexzugriff einen zugeordneten Instanzausdruck und eine Liste zugeordnete Argument.Furthermore, an indexer access has an associated instance expression and an associated argument list. Wenn ein Accessor (die get oder set Block) eines Indexers Zugriff aufgerufen wird, das Ergebnis der Auswertung des Ausdrucks für die Instanz wird die Instanz, die durch dargestellt this (diesen Zugriff), und das Ergebnis des Auswerten der Argumentliste, wird die Parameterliste des Aufrufs.When an accessor (the get or set block) of an indexer access is invoked, the result of evaluating the instance expression becomes the instance represented by this (This access), and the result of evaluating the argument list becomes the parameter list of the invocation.
  • "Nothing".Nothing. Dies tritt auf, wenn der Ausdruck einen Aufruf einer Methode mit einem Rückgabetyp von void.This occurs when the expression is an invocation of a method with a return type of void. Ein Ausdruck, der als "nothing" nur im Kontext gültig ist klassifiziert einen Statement_expression (ausdrucksanweisungen).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, Typ, Methodengruppe oder Ereigniszugriff.The final result of an expression is never a namespace, type, method group, or event access. Stattdessen sind diese Kategorien von Ausdrücken wie oben erwähnt, intermediate-Konstrukte, 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.

Eine Eigenschaft oder Indexzugriff ist immer neu klassifiziert als Wert durch Aufrufen von der get-Accessor oder set-Accessor.A property access or indexer access is always reclassified as a value by performing an invocation of the get accessor or the set accessor. Die bestimmte Zugriffsmethode richtet sich nach der im Rahmen der Eigenschaft oder der Indexer-Zugriff: Wenn der Zugriff auf das Ziel einer Zuweisung, ist die set-Accessor wird 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 die get-Accessor wird aufgerufen, um den aktuellen Wert zu erhalten (Werte Ausdrücke).Otherwise, the get accessor is invoked to obtain the current value (Values of expressions).

Werte der AusdrückeValues of expressions

Die meisten Konstrukte, bei denen einen Ausdruck erfordern schließlich den Ausdruck zur Angabe einer Wert.Most of the constructs that involve an expression ultimately require the expression to denote a value. In solchen Fällen, wenn der tatsächliche Ausdruck steht für einen Namespace, einen Typ, einer Methodengruppe oder nichts, tritt ein Fehler während der Kompilierung.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 einen Eigenschaftenzugriff, Indexzugriff oder eine Variable kennzeichnet, wird der Wert der Eigenschaft, Indexer oder Variable jedoch 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, die derzeit in den Speicherort identifiziert, die von der Variablen gespeichert.The value of a variable is simply the value currently stored in the storage location identified by the variable. Eine Variable muss definitiv zugewiesen berücksichtigt werden (definitive Zuweisung), bevor der Wert abgerufen werden kann, oder andernfalls tritt ein Fehler während der Kompilierung 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 Eigenschaftsausdrucks Zugriff wird ermittelt, durch den Aufruf der get-Accessor der Eigenschaft.The value of a property access expression is obtained by invoking the get accessor of the property. Wenn die Eigenschaft keine get-Accessor, ein Fehler während der Kompilierung auftritt.If the property has no get accessor, a compile-time error occurs. Andernfalls einen Member-Funktionsaufruf (Überprüfungen zur Kompilierzeit der dynamischen überladungsauflösung) ausgeführt wird, und das Ergebnis des Aufrufs wird der Wert der Eigenschaftsausdruck den Zugriff.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 Ausdrucks der Indexer-Zugriff wird ermittelt, durch den Aufruf der get-Accessor des Indexers.The value of an indexer access expression is obtained by invoking the get accessor of the indexer. Wenn der Indexer keine get-Accessor, ein Fehler während der Kompilierung auftritt.If the indexer has no get accessor, a compile-time error occurs. Andernfalls einen Member-Funktionsaufruf (Überprüfungen zur Kompilierzeit der dynamischen überladungsauflösung) erfolgt mit dem Argument Liste der Indexer-Access-Ausdruck zugeordnet ist, und das Ergebnis des Aufrufs wird der Wert der Zugriff Indexerausdrucks.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.

Statische und dynamische BindungStatic and Dynamic Binding

Der Prozess des bestimmens der Bedeutung eines Vorgangs basierend auf den Typ oder den Wert der enthaltenen Ausdrücke (Argumente, Operanden, Empfänger) wird häufig als bezeichnet Bindung.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. Beispielsweise wird die Bedeutung eines Methodenaufrufs bestimmt basierend auf dem Typ, der den Empfänger und die Argumente.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 den Typ des Operanden bestimmt.The meaning of an operator is determined based on the type of its operands.

In C# geschrieben, die Bedeutung eines Vorgangs in der Regel richtet sich zum Zeitpunkt der Kompilierung, basierend auf dem Zeitpunkt der Kompilierung von 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. Ebenso, wenn ein Ausdruck einen Fehler enthält, der Fehler wird erkannt und vom Compiler gemeldet.Likewise, if an expression contains an error, the error is detected and reported by the compiler. Dieser Ansatz wird bezeichnet als statische Bindung.This approach is known as static binding.

Allerdings ist ein Ausdruck eines dynamischen Ausdrucks (z. B. weist den Typ dynamic) Dies bedeutet, dass eine Bindung, die sie ein Teil ist basieren soll auf die Laufzeit-Typinformationen (d. h. der tatsächliche Typ des Objekts zur Laufzeit Dies bedeutet) anstatt den Typ am hat während der Kompilierung.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 ist die Zeit aus diesem Grund zurückgestellt, in dem der Vorgang ist während der Ausführung des Programms ausgeführt werden.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 bezeichnet dynamische Bindung.This is referred to as dynamic binding.

Wenn ein Vorgang dynamisch gebunden ist, wird vom Compiler nur wenig oder keine Überprüfung ausgeführt.When an operation is dynamically bound, little or no checking is performed by the compiler. Wenn die Bindung zur Laufzeit ein Fehler auftritt, werden stattdessen Fehler als Ausnahmen zur Laufzeit gemeldet.Instead if the run-time binding fails, errors are reported as exceptions at run-time.

Die folgenden Vorgänge in c# unterliegen Bindung aus:The following operations in C# are subject to binding:

  • Memberzugriff: e.MMember access: e.M
  • Methodenaufruf: e.M(e1, ..., eN)Method invocation: e.M(e1, ..., eN)
  • Delegataufruf:e(e1, ..., eN)Delegate invocation:e(e1, ..., eN)
  • Der Elementzugriff: e[e1, ..., eN]Element access: e[e1, ..., eN]
  • Erstellen von Objekten: new C(e1, ..., eN)Object creation: new C(e1, ..., eN)
  • Überladen von Unäroperatoren: +, -, !, ~, ++, --, true, falseOverloaded unary operators: +, -, !, ~, ++, --, true, false
  • Binäre Operatoren überladen: +, -, *, /, %, &, &&, |, ||, ??, ^, << , >>, ==,!=, >, <, >=, <=Overloaded binary operators: +, -, *, /, %, &, &&, |, ||, ??, ^, <<, >>, ==,!=, >, <, >=, <=
  • Zuweisungsoperatoren: =, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=Assignment operators: =, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=
  • Implizite und explizite KonvertierungenImplicit and explicit conversions

Wenn Sie keine dynamischen Ausdrücke beteiligt sind, standardmäßig c# statische Bindung, was bedeutet, dass die Typen während der Kompilierung der enthaltenen Ausdrücke in den Prozess 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 einer der enthaltenen Ausdrücke in den oben aufgeführten Vorgängen eines dynamischen Ausdrucks ist, ist jedoch, 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.

Bindung-timeBinding-time

Statische Bindung erfolgt zum Zeitpunkt der Kompilierung, während dynamische Bindung zur Laufzeit stattfindet.Static binding takes place at compile-time, whereas dynamic binding takes place at run-time. In den folgenden Abschnitten der Begriff Bindung Kompilierzeit bezieht sich entweder während der Kompilierung oder zur Laufzeit, je nachdem, wann die Bindung erfolgt.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 Konzepte der statische und dynamische Bindung und der Bindung 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 statisch gebunden sind: die Überladung von Console.WriteLine wird ausgewählt, basierend auf dem Zeitpunkt der Kompilierung von deren Argument.The first two calls are statically bound: the overload of Console.WriteLine is picked based on the compile-time type of their argument. Daher ist die Bindung-die Zeit während der Kompilierung.Thus, the binding-time is compile-time.

Der dritte Aufruf dynamisch gebunden ist: die Überladung von Console.WriteLine wird ausgewählt, basierend auf dem Laufzeit-Typ des Arguments.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 eines dynamischen Ausdrucks – der Kompilierzeittyp dynamic.This happens because the argument is a dynamic expression -- its compile-time type is dynamic. Daher ist die Bindung und die Uhrzeit für die dritte Aufruf zur Laufzeit.Thus, the binding-time for the third call is run-time.

Dynamische BindungDynamic binding

Die dynamische Bindung dient zum Zulassen von C#-Programme für die Interaktion mit dynamische Objekte, d. h. Objekte, die nicht die üblichen Regeln der C# folgen-Typsystem.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 verschiedenen Systemen werden, oder sie möglicherweise Objekte, die programmgesteuert einrichten, um ihre eigene Bindung-Semantik für verschiedene Vorgänge zu implementieren sind.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 eine eigene Semantik implementiert, ist die Implementierung definiert.The mechanism by which a dynamic object implements its own semantics is implementation defined. Eine bestimmte Schnittstelle – erneut Implementierung definiert – wird durch dynamische Objekte für die c#-Laufzeit zu signalisieren, dass sie spezielle Semantik haben implementiert.A given interface -- again implementation defined -- is implemented by dynamic objects to signal to the C# run-time that they have special semantics. Daher, wenn Vorgänge für ein dynamisches Objekt dynamisch gebunden sind, haben ihre eigene Bindung-Semantik, anstatt die C# -Code wie in diesem Dokument angegeben.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.

Während der Zweck der dynamischen Bindung ist um interoperation mit dynamischen Objekten zu ermöglichen, ermöglicht c# dynamische Bindung für alle Objekte, ob sie dynamisch oder nicht sind.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 nahtlosere Integration der dynamische Objekte, wie die Ergebnisse der Vorgänge auf diesen können selbst keine dynamische Objekte, aber immer noch von einem Typ, der dem Programmierer zum Zeitpunkt der Kompilierung nicht bekannt sind.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. Dynamische Bindung können fehleranfällige Reflection basierender Code entfernen, selbst, wenn Sie keine beteiligten Objekte dynamische Objekte sind.Also dynamic binding can help eliminate error-prone reflection-based code even when no objects involved are dynamic objects.

In den folgenden Abschnitten beschreiben für jedes Konstrukt in der Sprache, genau Wenn dynamische Bindung übernommen wird, was zur Kompilierzeit – Wenn--wird angewendet, und welche die während der Kompilierung Result und Expression-Klassifizierung 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 einzelnen AusdrückenTypes of constituent expressions

Wenn ein Vorgang statisch gebunden ist, gilt der Typ eines einzelnen Ausdrucks (z. B. einen Empfänger, ein Argument, einen Index oder ein Operand) immer der Kompilierzeit-Typ dieses Ausdrucks sein.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 ist, wird der Typ eines einzelnen Ausdrucks auf unterschiedliche Weise abhängig vom Zeitpunkt der Kompilierung der enthaltenen Ausdruck 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:

  • Einen einzelnen Ausdruck Kompilierzeittyp dynamic gilt den Typ des tatsächlichen Werts haben die Auswertung des Ausdrucks, zur LaufzeitA constituent expression of compile-time type dynamic is considered to have the type of the actual value that the expression evaluates to at runtime
  • Gilt als ein einzelnen Ausdruck, dessen Typ während der Kompilierung ein Typparameter ist, den Typ verfügen, die der Type-Parameter zur Laufzeit gebunden istA 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 gilt der enthaltenen Ausdruck der Kompilierzeit-Typ aufweisen.Otherwise the constituent expression is considered to have its compile-time type.

OperatorenOperators

Ausdrücke bestehen aus Operanden und Operatoren.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äroperatoren verwenden einen Operanden, und verwenden Sie entweder Präfix-Notation (z. B. --x) oder postfix-Notation (z. B. x++).The unary operators take one operand and use either prefix notation (such as --x) or postfix notation (such as x++).
  • Binäre Operatoren.Binary operators. Die binären Operatoren nehmen zwei Operanden, und alle Infix-Notation verwenden (z. B. x + y).The binary operators take two operands and all use infix notation (such as x + y).
  • ternärer operatorTernary operator. Nur ein ternärer Operator, ?:, vorhanden ist; er übernimmt drei Operanden und 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 richtet sich nach der Rangfolge und Assoziativität der Operatoren (Operatorrangfolge und Assoziativität) .The order of evaluation of operators in an expression is determined by the precedence and associativity of the operators (Operator precedence and associativity).

Die Operanden in einem Ausdruck werden von links nach rechts ausgewertet.Operands in an expression are evaluated from left to right. Z. B. in F(i) + G(i++) * H(i), Methode F wird aufgerufen, mit der alte Wert des i, then-Methode G wird aufgerufen, mit dem alten Wert der i, und schließlich-Methode H wird aufgerufen, mit dem neuen Wert der 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. Dadurch wird unabhängig vom Operatorrangfolge.This is separate from and unrelated to operator precedence.

Bestimmte Operatoren können werden überladen.Certain operators can be overloaded. Überladen von Operatoren ermöglicht eine benutzerdefinierte operatorimplementierungen für Vorgänge, bei denen ein angegeben werden, oder beide der Operanden sind von einer benutzerdefinierten Klasse oder Struktur-Typ (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, bestimmt 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. Beispiel: der Ausdruck x + y * z wird als ausgewertet, x + (y * z) da die * Operator hat Vorrang vor der Binärdatei + 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 von einem Operator wird durch die Definition ihrer zugeordneten Grammatik Produktion eingerichtet.The precedence of an operator is established by the definition of its associated grammar production. Z. B. eine Additive_expression besteht aus einer Sequenz von Multiplicative_expressions getrennt durch + oder - Operatoren, wodurch die + und - Operatoren niedrigere Priorität als die *, /, und % Operatoren.For example, an additive_expression consists of a sequence of multiplicative_expressions separated by + or - operators, thus giving the + and - operators lower precedence than the *, /, and % operators.

In der folgende Tabelle sind alle Operatoren in der Reihenfolge der Rangfolge von oben nach unten zusammengefasst:The following table summarizes all operators in order of precedence from highest to lowest:

BereichSection KategorieCategory OperatorenOperators
Primary expressions (Primäre Ausdrücke)Primary expressions PrimärPrimary x.y f(x) a[x] x++ x-- new typeof default checked unchecked delegatex.y f(x) a[x] x++ x-- new typeof default checked unchecked delegate
Unary operators (Unäre Operatoren)Unary operators UnärUnary + - ! ~ ++x --x (T)x+ - ! ~ ++x --x (T)x
Arithmetic operators (Arithmetische Operatoren)Arithmetic operators MultiplikativMultiplicative * / %* / %
Arithmetic operators (Arithmetische Operatoren)Arithmetic operators AdditivAdditive + -+ -
Shift operators (Schiebeoperatoren)Shift operators ShiftShift << >><< >>
Relational and type-testing operators (Relationale und Typtestoperatoren)Relational and type-testing operators Relational und TyptestRelational and type testing < > <= >= is as< > <= >= is as
Relational and type-testing operators (Relationale und Typtestoperatoren)Relational and type-testing operators GleichheitEquality == !=== !=
Logical operators (Logische Operatoren)Logical operators Logisches ANDLogical AND &
Logical operators (Logische Operatoren)Logical operators Logisches XORLogical XOR ^
Logical operators (Logische Operatoren)Logical operators Logisches ORLogical OR |
Conditional logical operators (Bedingte logische Operatoren)Conditional logical operators Bedingtes ANDConditional AND &&
Conditional logical operators (Bedingte logische Operatoren)Conditional logical operators Bedingtes ORConditional OR ||
The null coalescing operator (Der NULL-Sammeloperator)The null coalescing operator NULL-SammeloperatorNull coalescing ??
Conditional operator (Bedingte Operatoren)Conditional operator BedingtConditional ?:
Zuweisungsoperatoren, anonyme FunktionsausdrückeAssignment operators, Anonymous function expressions Zuweisungs- und Lambda-AusdrückeAssignment and lambda expression = *= /= %= += -= <<= >>= &= ^= |= =>= *= /= %= += -= <<= >>= &= ^= |= =>

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 Zuweisungsoperatoren und der null-Sammeloperator, alle binären Operatoren sind linksassoziativ, was 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 Zuweisungsoperatoren, die null-Sammeloperator und der bedingte Operator (?:) sind rechtsassoziativ, was bedeutet, dass Vorgänge, die 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 als x = (y = z) ausgewertet.For example, x = y = z is evaluated as x = (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 sind Implementierungen vordefiniert, die in jedem Ausdruck automatisch 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 dazu eingeleitet werden operator Deklarationen in Klassen und Strukturen (Operatoren).In addition to the predefined implementations, user-defined implementations can be introduced by including operator declarations in classes and structs (Operators). Benutzerdefinierte Implementierungen haben immer Vorrang vor vordefinierte operatorimplementierungen: Nur bei der keine Implementierungen der entsprechenden benutzerdefinierten Operator wird vorhanden sind die vordefinierten operatorimplementierungen berücksichtigt werden wie in beschrieben, unäroperator überladungsauflösung und binärer Operator-Überladung Auflösung.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 überladbarer Unäroperatoren sind:The overloadable unary operators are:

+   -   !   ~   ++   --   true   false

Obwohl true und false nicht explizit in Ausdrücken verwendet werden (und sind daher nicht in der Rangfolgentabelle in enthalten Operatorrangfolge und Assoziativität), diese werden als Operatoren betrachtet, da sie sich befinden in mehrere ausdruckskontexten aufgerufen: boolesche Ausdrücke (boolesche Ausdrücke) und im Zusammenhang mit der bedingten Ausdrücke (Bedingungsoperator), und bedingte logische Operatoren (bedingten logischen 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 Überladbare binäre 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, Memberzugriff, Methodenaufruf zu überladen oder =, &&, ||, ??, ?:, =>, checked, unchecked, new, typeof, default, as, und is Operatoren.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. Angenommen, eine Überladung des Operators * ist auch eine Überladung des Operators *=.For example, an overload of operator * is also an overload of operator *=. Dies wird weiter in Verbundzuweisung.This is described further in Compound assignment. Beachten Sie, dass der Zuweisungsoperator selbst (=) kann nicht überladen werden.Note that the assignment operator itself (=) cannot be overloaded. Eine Zuweisung immer führt eine einfache bitweise Kopie eines Werts in einer Variablen an.An assignment always performs a simple bit-wise copy of a value into a variable.

Wandeln Sie die Vorgänge, z. B. (T)x, werden durch die Bereitstellung von benutzerdefinierten Konvertierungen überladen (benutzerdefinierte Konvertierungen).Cast operations, such as (T)x, are overloaded by providing user-defined conversions (User-defined conversions).

Element zuzugreifen, z. B. a[x], einen überladbaren Operators wird nicht berücksichtigt.Element access, such as a[x], is not considered an overloadable operator. Benutzerdefinierte Indizierung wird jedoch unterstützt über Indexer (Indexer).Instead, user-defined indexing is supported through indexers (Indexers).

In Ausdrücken werden Operatoren mithilfe der Operatornotation und in Deklarationen, Operatoren sind verwiesen funktionale Notation verwenden.In expressions, operators are referenced using operator notation, and in declarations, operators are referenced using functional notation. Die folgende Tabelle zeigt die Beziehung zwischen den Operator und funktionalen Notationen für unären und binären Operatoren.The following table shows the relationship between operator and functional notations for unary and binary operators. In den ersten Eintrag Op kennzeichnet alle überladbarer unärer Präfix-Operator.In the first entry, op denotes any overloadable unary prefix operator. In den zweiten Eintrag Op kennzeichnet das Postfix unäre ++ und -- Operatoren.In the second entry, op denotes the unary postfix ++ and -- operators. Im dritten Eintrag Op kennzeichnet alle überladbaren 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)

Eine benutzerdefinierte Operatordeklarationen erfordern immer mit mindestens einer der Parameter des Typs Klasse oder Struktur sein, die sich die Operatordeklaration 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, für einen benutzerdefinierten Operator auf die gleiche Signatur wie einen vordefinierten Operator haben.Thus, it is not possible for a user-defined operator to have the same signature as a predefined operator.

Benutzerdefinierte Deklarationen können nicht der Syntax, die Rangfolge oder die Assoziativität von einem Operator geändert werden.User-defined operator declarations cannot modify the syntax, precedence, or associativity of an operator. Z. B. die / -Operators ist immer ein binärer Operator, immer wurde die rangfolgenebene angegeben Operatorrangfolge und Assoziativität, und ist immer linksassoziativ.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.

Es ist, zwar möglich, dass ein benutzerdefinierter Operator eine Berechnung ausführen, die es pleases sind Implementierungen, die Ergebnisse nicht zu erzeugen, die intuitiv erwartet werden dringend abgeraten.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. Zum Beispiel eine Implementierung von operator == sollten die beiden Operanden hinsichtlich ihrer Gleichheit und Zurückgeben eines entsprechenden bool Ergebnis.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 primärausdrücke über bedingten logischen Operatoren Geben Sie die vordefinierte Implementierungen von Operatoren und alle zusätzlichen Regeln, die angewendet werden zu jedem Operator.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. Stellen Sie die Beschreibungen der Begriffe verwenden überladungsauflösung für unäroperator, binärer Operator überladungsauflösung, und numerische heraufstufung, Definitionen sind finden Sie in den folgenden Abschnitten.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.

Überladungsauflösung für Unären operatorUnary operator overload resolution

Ein Vorgang des Formulars op x oder x op, wobei op ein überladbarer unärer Operator, und x ist ein Ausdruck vom Typ 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 Kandidaten benutzerdefinierten Operatoren, die mit der gebotenen X für den Vorgang operator op(x) wird bestimmt, wobei die Regeln der Candidate benutzerdefinierte Operatoren.The set of candidate user-defined operators provided by X for the operation operator op(x) is determined using the rules of Candidate user-defined operators.
  • Wenn der Satz von Kandidaten benutzerdefinierte Operatoren nicht leer ist, wird dies die 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 die vordefinierten unären operator op Implementierungen, einschließlich deren angehobene Forms, werden der Satz von Kandidaten-Operatoren für den Vorgang.Otherwise, the predefined unary operator op implementations, including their lifted forms, become the set of candidate operators for the operation. Die vordefinierte Implementierung eines bestimmten Operators werden in der Beschreibung des Operators angegeben (primärausdrücke und unäre Operatoren).The predefined implementations of a given operator are specified in the description of the operator (Primary expressions and Unary operators).
  • Die Regeln der überladungsauflösung des Überladungsauflösung gelten für den Satz von Kandidaten-Operatoren, um die beste Operator in Bezug auf die Argumentliste auszuwählen (x), und dieser Operator wird das Ergebnis der Überladung der Auflösungsvorgang.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. Überladungsauflösung keinen einzelnen bewährte Operator auswählen, tritt ein Fehler während der Bindung.If overload resolution fails to select a single best operator, a binding-time error occurs.

Binärer Operator Auflösung von funktionsüberladungenBinary operator overload resolution

Ein Vorgang des Formulars x op y, wobei op ist ein Überladbarer binärer Operator x ist ein Ausdruck vom Typ X, und y ist ein Ausdruck vom Typ 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 Kandidaten benutzerdefinierten Operatoren, die mit der gebotenen X und Y für den Vorgang operator op(x,y) bestimmt ist.The set of candidate user-defined operators provided by X and Y for the operation operator op(x,y) is determined. Der Satz besteht aus der Union der Kandidat Operatoren gebotenen X und die Candidate-Operatoren, die von bereitgestellte Y, jeweils festgelegt, wobei die Regeln der Candidate benutzerdefinierte Operatoren.The set consists of the union of the candidate operators provided by X and the candidate operators provided by Y, each determined using the rules of Candidate user-defined operators. Wenn X und Y denselben Typ aufweisen, oder wenn X und Y über einen gemeinsamen Basistyp abgeleitet werden, und klicken Sie dann gemeinsam genutzte potentielle Operatoren nur einmal in der kombinierten Gruppe vorkommen.If X and Y are the same type, or if X and Y are derived from a common base type, then shared candidate operators only occur in the combined set once.
  • Wenn der Satz von Kandidaten benutzerdefinierte Operatoren nicht leer ist, wird dies die 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 die vordefinierten Binärdatei operator op Implementierungen, einschließlich deren angehobene Forms, werden der Satz von Kandidaten-Operatoren für den Vorgang.Otherwise, the predefined binary operator op implementations, including their lifted forms, become the set of candidate operators for the operation. Die vordefinierte Implementierung eines bestimmten Operators werden in der Beschreibung des Operators angegeben (arithmetische Operatoren über bedingten logischen Operatoren).The predefined implementations of a given operator are specified in the description of the operator (Arithmetic operators through Conditional logical operators). Für vordefinierte für Enumerationen und Delegaten-Operatoren sind Operatoren die nur berücksichtigt die durch eine Enumeration oder Delegat-Typ, der der Bindung-Time-Typ, der einer der Operanden ist definierten.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 der überladungsauflösung des Überladungsauflösung gelten für den Satz von Kandidaten-Operatoren, um die beste Operator in Bezug auf die Argumentliste auszuwählen (x,y), und dieser Operator wird das Ergebnis der Überladung der Auflösungsvorgang.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. Überladungsauflösung keinen einzelnen bewährte Operator auswählen, tritt ein Fehler während der Bindung.If overload resolution fails to select a single best operator, a binding-time error occurs.

Kandidat benutzerdefinierte OperatorenCandidate user-defined operators

Bei einem vorgegebenen Typ T und einen Vorgang operator op(A), wobei op ist ein überladbaren Operators und A ist eine Argumentliste, die den Satz von Kandidaten benutzerdefinierten Operatoren, die von bereitgestellte T für operator op(A) richtet sich wie folgt: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 type T0. Wenn T ist ein NULL-Werte zulässt, T0 ist die zugrunde liegenden Typ und andernfalls T0 gleich T.If T is a nullable type, T0 is its underlying type, otherwise T0 is equal to T.
  • Für alle operator op Deklarationen in T0 und alle Arten von solcher Operatoren, aufgehoben wird, wenn mindestens ein Operator anwendbar ist (Anwendbarer Funktionsmember) in Bezug auf die Argumentliste A, klicken Sie dann den Satz von Kandidat Operatoren besteht aus solchen entsprechenden Operatoren in T0.For all operator op declarations in T0 and all lifted forms of such operators, if at least one operator is applicable (Applicable function member) with respect to the argument list A, then the set of candidate operators consists of all such applicable operators in T0.
  • Andernfalls gilt: Wenn T0 ist object, der Satz von Kandidaten-Operatoren ist leer.Otherwise, if T0 is object, the set of candidate operators is empty.
  • Andernfalls der Satz von Kandidaten Standardabfrageoperatoren gebotenen T0 ist ein Satz von Kandidaten-Operatoren, die durch die direkte Basisklasse bereitgestellt T0, oder die effektive Basisklasse T0 Wenn T0 ein Parameter vom Typ ist.Otherwise, the set of candidate operators provided by T0 is the set of candidate operators provided by the direct base class of T0, or the effective base class of T0 if T0 is a type parameter.

Numerische heraufstufungenNumeric promotions

Numerische heraufstufung besteht aus automatisch bestimmte implizite Konvertierungen von Operanden der unären und binären numerischen Operatoren für Sie ausgeführt.Numeric promotion consists of automatically performing certain implicit conversions of the operands of the predefined unary and binary numeric operators. Numerische heraufstufung ist nicht auf, eine unterschiedliche Methode, sondern vielmehr eine Auswirkung der Auflösung von funktionsüberladungen auf die vordefinierten Operatoren angewendet.Numeric promotion is not a distinct mechanism, but rather an effect of applying overload resolution to the predefined operators. Numerische heraufstufung wirkt speziell Auswertung von benutzerdefinierten Operatoren, sich nicht auch benutzerdefinierte Operatoren weisen ähnliche Auswirkungen implementiert werden können.Numeric promotion specifically does not affect evaluation of user-defined operators, although user-defined operators can be implemented to exhibit similar effects.

Ein Beispiel für numerische heraufstufung, sollten Sie die vordefinierte Implementierungen der Binärdatei * Operator: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 überladungsauflösung (Auflösen der Überladung) gelten für diesen Satz von Operatoren, der Effekt ist, die Operandentypen auswählen, das erste der Operatoren für die implizite Konvertierungen 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. Z. B. für den Vorgang b * s, wobei b ist eine byte und s ist eine short, überladen Sie die Lösung wählt operator *(int,int) als bester Operator.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. Daher das wird also b und s werden in konvertiert int, und der Typ des Ergebnisses ist int.Thus, the effect is that b and s are converted to int, and the type of the result is int. Ebenso für den Vorgang i * d, wobei i ist ein int und d ist eine double, überladen Sie die Lösung wählt operator *(double,double) als bester Operator.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 numerischen heraufstufungenUnary numeric promotions

Unäre numerische heraufstufung tritt auf, für den Operanden des vordefinierten +, -, und ~ unäre Operatoren.Unary numeric promotion occurs for the operands of the predefined +, -, and ~ unary operators. Unäre numerische heraufstufung besteht nur aus der Konvertierung von Operanden des Typs sbyte, byte, short, ushort, oder char eingeben int.Unary numeric promotion simply consists of converting operands of type sbyte, byte, short, ushort, or char to type int. Darüber hinaus für den unären - Operator, Unäre numerische heraufstufung konvertiert Operanden vom Typ uint eingeben long.Additionally, for the unary - operator, unary numeric promotion converts operands of type uint to type long.

Binäre numerische heraufstufungenBinary numeric promotions

Binäre numerische heraufstufung tritt auf, für den Operanden des vordefinierten +, -, *, /, %, &, |, ^, ==, !=, >, <, >=, und <= binären Operatoren.Binary numeric promotion occurs for the operands of the predefined +, -, *, /, %, &, |, ^, ==, !=, >, <, >=, and <= binary operators. Binäre numerische heraufstufung konvertiert beide Operanden implizit in einen gemeinsamen Typ, der bei der nicht-relationalen Operatoren der 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. Binäre numerische heraufstufung besteht aus der Anwendung der folgenden Regeln, in der Reihenfolge, die sie hier angezeigt werden:Binary numeric promotion consists of applying the following rules, in the order they appear here:

  • Wenn ein Operand vom Typ decimal, der andere Operand wird in den Typ konvertiert decimal, oder es sich bei ein Fehler während der Datenbindung tritt auf, wenn der andere Operand vom Typ float oder double.If either operand is of type decimal, the other operand is converted to type decimal, or a binding-time error occurs if the other operand is of type float or double.
  • Andernfalls, wenn ein Operand vom Typ double, der andere Operand wird in den Typ konvertiert double.Otherwise, if either operand is of type double, the other operand is converted to type double.
  • Andernfalls, wenn ein Operand vom Typ float, der andere Operand wird in den Typ konvertiert float.Otherwise, if either operand is of type float, the other operand is converted to type float.
  • Andernfalls, wenn ein Operand vom Typ ulong, der andere Operand wird in den Typ konvertiert ulong, oder es sich bei ein Fehler während der Datenbindung tritt auf, wenn der andere Operand vom Typ sbyte, short, int, oder long.Otherwise, if either operand is of type ulong, the other operand is converted to type ulong, or a binding-time error occurs if the other operand is of type sbyte, short, int, or long.
  • Andernfalls, wenn ein Operand vom Typ long, der andere Operand wird in den Typ konvertiert long.Otherwise, if either operand is of type long, the other operand is converted to type long.
  • Andernfalls, wenn ein Operand vom Typ uint und der andere Operand ist vom Typ sbyte, short, oder int, beide Operanden sind in den Typ konvertiert long.Otherwise, if either operand is of type uint and the other operand is of type sbyte, short, or int, both operands are converted to type long.
  • Andernfalls, wenn ein Operand vom Typ uint, der andere Operand wird in den Typ konvertiert uint.Otherwise, if either operand is of type uint, the other operand is converted to type uint.
  • Andernfalls werden beide Operanden Typ konvertiert int.Otherwise, both operands are converted to type int.

Beachten Sie, dass die erste Regel keine Vorgänge lässt nicht zu, die Mischen der decimal Geben Sie mit der double und float Typen.Note that the first rule disallows any operations that mix the decimal type with the double and float types. Die Regel ergibt sich aus der Tatsache, die es keine impliziten Konvertierungen zwischen gibt den decimal Typ und die double und float Typen.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, dass ein Operand vom Typ ulong bei der andere Operand ist, der einen ganzzahligen Typ mit Vorzeichen.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 ist, dass kein ganzzahliger Typ, der vorhanden ist kann das gesamte Spektrum darstellen ulong sowie die ganzzahligen Typen mit Vorzeichen.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 Cast-Ausdruck verwendet werden, zu einer der Operanden explizit in einen Typ zu konvertieren, die mit der andere Operand 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 während der Datenbindung tritt auf, weil eine decimal kann nicht multipliziert eine double.a binding-time error occurs because a decimal cannot be multiplied by a double. Der Fehler wurde behoben, durch explizite Konvertierung der zweite Operand decimalwie folgt: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);
}

Transformierten OperatorenLifted operators

Operatoren angehoben zulassen von vordefinierten und benutzerdefinierten Operatoren, die Vorgänge an nicht auf NULL festlegbare Werttypen auch mit NULL-Werte zulassen Forms dieser Typen verwendet werden soll.Lifted operators permit predefined and user-defined operators that operate on non-nullable value types to also be used with nullable forms of those types. Transformierten Operatoren bestehen aus vordefinierten und benutzerdefinierten Operatoren, die 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äroperatorenFor the unary operators

    +  ++  -  --  !  ~
    

    eine angehobene Form eines Operators ist vorhanden, wenn die Operanden und Ergebnis beide nicht auf NULL festlegbare Werttypen sind.a lifted form of an operator exists if the operand and result types are both non-nullable value types. Die transformierten Form wird durch Hinzufügen eines einzelnen erstellt ? Modifizierer, um die Typen von Operanden und Ergebnis.The lifted form is constructed by adding a single ? modifier to the operand and result types. Der transformierten Operator erzeugt einen null-Wert, wenn der Operand null ist.The lifted operator produces a null value if the operand is null. Der transformierten Operator hingegen entpackt der Operand, der zugrunde liegenden-Operator angewendet und bindet 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

    +  -  *  /  %  &  |  ^  <<  >>
    

    eine angehobene Form eines Operators ist vorhanden, wenn die Operanden und Ergebnis alle nicht auf NULL festlegbare Werttypen sind.a lifted form of an operator exists if the operand and result types are all non-nullable value types. Die transformierten Form wird durch Hinzufügen eines einzelnen erstellt ? Modifizierer für jeden Operanden und Ergebnis.The lifted form is constructed by adding a single ? modifier to each operand and result type. Der transformierten Operator erzeugt einen null-Wert, wenn eine oder beide Operanden null sind (eine Ausnahme wird die & und | Operatoren mit den bool? eingeben, wie in beschrieben Boolesche logische Operatoren).The lifted operator produces a null value if one or both operands are null (an exception being the & and | operators of the bool? type, as described in Boolean logical operators). Andernfalls der transformierten Operator entpackt die Operanden der zugrunde liegenden-Operator angewendet und dient als Wrapper für das Ergebnis.Otherwise, the lifted operator unwraps the operands, applies the underlying operator, and wraps the result.

  • Für die GleichheitsoperatorenFor the equality operators

    ==  !=
    

    eine angehobene Form der Bediener vorhanden ist, wenn die Operandentypen sind nicht auf NULL festlegbare Werttypen und ist der Ergebnistyp bool.a lifted form of an operator exists if the operand types are both non-nullable value types and if the result type is bool. Die transformierten Form wird durch Hinzufügen eines einzelnen erstellt ? Modifizierer für die einzelnen Operanden.The lifted form is constructed by adding a single ? modifier to each operand type. Der transformierten Operator betrachtet, zwei null-Werte identisch sind, und ein null-Wert auf einen beliebigen nicht-Null-Wert ungleich.The lifted operator considers two null values equal, and a null value unequal to any non-null value. Wenn beide Operanden ungleich Null sind, wird der transformierten-Operator entpackt die Operanden und wendet den zugrunde liegenden Operator zum Erzeugen der bool Ergebnis.If both operands are non-null, the lifted operator unwraps the operands and applies the underlying operator to produce the bool result.

  • Für die relationalen OperatorenFor the relational operators

    <  >  <=  >=
    

    eine angehobene Form der Bediener vorhanden ist, wenn die Operandentypen sind nicht auf NULL festlegbare Werttypen und ist der Ergebnistyp bool.a lifted form of an operator exists if the operand types are both non-nullable value types and if the result type is bool. Die transformierten Form wird durch Hinzufügen eines einzelnen erstellt ? Modifizierer für die einzelnen Operanden.The lifted form is constructed by adding a single ? modifier to each operand type. Die transformierten Operator gibt den Wert false Wenn einer oder beide der Operanden null sind.The lifted operator produces the value false if one or both operands are null. Andernfalls den transformierten Operator entpackt die Operanden und gilt den zugrunde liegenden Operator erzeugt die bool Ergebnis.Otherwise, the lifted operator unwraps the operands and applies the underlying operator to produce the bool result.

Suche nach MembernMember lookup

Eine Suche nach Membern ist der 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 Suche nach Membern kann auftreten, als Teil der Auswertung einer Simple_name (einfache Namen) oder ein Member_access (Memberzugriff) in ein -Ausdruck.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 tritt ein, wenn die Primary_expression von einem Invocation_expression ( Methodenaufrufe), gilt der Member aufgerufen werden.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 Konstanten, Felder oder Eigenschaften entweder einen Delegattyp handelt (Delegaten) oder den Typ dynamic (der dynamische Typ), und klicken Sie dann das Element wird als bezeichnet aufrufbare.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.

Suche nach Membern berücksichtigt nicht nur den Namen der ein Element, sondern auch die Anzahl von Typparametern, die das Element und gibt an, ob der Member zugegriffen werden.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 Zwecke der Suche nach Membern generische Methoden und geschachtelten generischen Typen haben die Anzahl von Typparametern, die in ihren jeweiligen Deklarationen angegeben, und alle anderen Elemente 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 Suche nach Membern des Namens eines N mit K  Typ von Parametern 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, eine Reihe von zugängliche Member, die mit dem Namen N bestimmt wird:First, a set of accessible members named N is determined:
    • Wenn T Typparameter ist ein, und klicken Sie dann die Gruppe der Union der Sätze von zugängliche Member, die mit dem Namen ist N in jedem der Typen, die als sekundäre Einschränkung oder primary-Einschränkung angegeben (Geben Sie die Einschränkungen für Typparameter) für  T, sowie die zugängliche Member, die mit dem Namen N in object.If T is a type parameter, then the set is the union of the sets of accessible members named N in each of the types specified as a primary constraint or secondary constraint (Type parameter constraints) for T, along with the set of accessible members named N in object.
    • Andernfalls der Satz besteht aus allen zugegriffen werden kann (Memberzugriff) Elemente, die mit dem Namen N in T, einschließlich der geerbte Member und den zugängliche Member mit dem Namen N in object.Otherwise, the set consists of all accessible (Member access) members named N in T, including inherited members and the accessible members named N in object. Wenn T ein konstruierter Typ ist, wird die Menge der Elemente wird abgerufen, indem Typargumente ersetzen, wie in beschrieben Mitglieder der konstruierte Typen.If T is a constructed type, the set of members is obtained by substituting type arguments as described in Members of constructed types. Elemente, die enthalten eine override Modifizierer aus der Gruppe ausgeschlossen werden.Members that include an override modifier are excluded from the set.
  • Als Nächstes If K ist 0 (null), alle geschachtelten Typen, deren Deklarationen enthalten die Typparameter, werden entfernt.Next, if K is zero, all nested types whose declarations include type parameters are removed. Wenn K nicht gleich NULL ist, alle Elemente mit einer anderen Anzahl von Parametern entfernt werden, Typ.If K is not zero, all members with a different number of type parameters are removed. Hinweis: Wenn K ist NULL, Methoden mit einem Typ, die Parameter nicht werden, da durch die Herleitung Typ entfernt werden (Typrückschluss) möglicherweise die Typargumente abzuleiten.Note that when K is zero, methods having type parameters are not removed, since the type inference process (Type inference) might be able to infer the type arguments.
  • Weiter, wenn der Member ist aufgerufen, allen nicht-aufrufbare Mitglieder aus dem Satz entfernt werden.Next, if the member is invoked, all non-invocable members are removed from the set.
  • Als Nächstes werden die Elemente, die durch andere Member ausgeblendet werden aus der Gruppe entfernt.Next, members that are hidden by other members are removed from the set. Für jedes Element S.M in der Gruppe, in denen S ist der Typ, in dem das Element M deklariert ist, werden die folgenden Regeln angewendet:For every member S.M in the set, where S is the type in which the member M is declared, the following rules are applied:
    • Wenn M ist eine Konstante, ein Feld, Eigenschaft, Ereignis oder -Enumerationsmember, alle Elemente in dem Basistyp deklariert S aus der Gruppe entfernt werden.If M is a constant, field, property, event, or enumeration member, then all members declared in a base type of S are removed from the set.
    • Wenn M ist eine Typdeklaration, dann alle nicht-Typen, die deklariert in einem Basistyp von S werden aus der Gruppe, entfernt und alle Typdeklarationen sind mit der gleichen Anzahl von Typparametern als M , die in dem Basistyp deklariert S werden entfernt aus dem Satz.If M is a type declaration, then all non-types declared in a base type of S are removed from the set, and all type declarations with the same number of type parameters as M declared in a base type of S are removed from the set.
    • Wenn M ist eine Methode, alle Nichtmethode-Member in dem Basistyp deklariert S aus der Gruppe entfernt werden.If M is a method, then all non-method members declared in a base type of S are removed from the set.
  • Als Nächstes werden Schnittstellenmember, die von der Klasse, Elemente ausgeblendet werden aus dem Satz entfernt werden.Next, interface members that are hidden by class members are removed from the set. Dieser Schritt ist nur wirksam, wenn T Typparameter und T hat sowohl eine effektive Basisklasse außer object und eine effektive nicht leere-Schnittstelle, die festgelegt (Geben Sie die Einschränkungen für Typparameter).This step only has an effect if T is a type parameter and T has both an effective base class other than object and a non-empty effective interface set (Type parameter constraints). Für jedes Element S.M in der Gruppe, in denen S ist der Typ, in dem das Element M deklariert ist, werden die folgenden Regeln angewendet werden, wenn S ist eine Deklaration der Klasse nicht object:For every member S.M in the set, where S is the type in which the member M is declared, the following rules are applied if S is a class declaration other than object:
    • Wenn M ist eine Konstante, ein Feld, Eigenschaft, Ereignis, Enumerationsmember oder Typdeklaration, und klicken Sie dann alle Member, die in der Schnittstellendeklaration einer deklariert, die aus dem Satz entfernt werden.If M 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 ist eine Methode, alle nicht-Method-Elemente, die in der Schnittstellendeklaration einer deklariert entfernt werden, aus dem Satz und alle Methoden, mit der gleichen Signatur wie M deklariert in einer Schnittstelle Deklaration aus dem Satz entfernt werden.If M 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 as M declared in an interface declaration are removed from the set.
  • Dass werden ausgeblendete Elemente entfernt, wird schließlich das Ergebnis der Suche bestimmt werden:Finally, having removed hidden members, the result of the lookup is determined:
    • Wenn die Gruppe ein einzelnes Element, die keine Methode ist besteht, 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, wenn der Satz nur Methoden enthält, ist diese Gruppe von Methoden das Ergebnis der Suche.Otherwise, if the set contains only methods, then this group of methods is the result of the lookup.
    • Andernfalls die Suche ist nicht eindeutig, und beim Auftreten eines Laufzeitfehlers-Bindung.Otherwise, the lookup is ambiguous, and a binding-time error occurs.

Für Member-Suchvorgänge in andere Typen als Parameter vom Typ und die Schnittstellen und Elementsuchvorgänge in Schnittstellen, die ausschließlich mit einfacher Vererbung (jede Schnittstelle in der Vererbungskette weist genau Null oder eine direkte Basisschnittstelle), wird die Suche nach Regeln einfach abgeleitet, die Member ausblenden Basis Member mit demselben Namen bzw. derselben Signatur.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. Diese Suchvorgänge mit einfacher Vererbung sind stets eindeutig.Such single-inheritance lookups are never ambiguous. Die Mehrdeutigkeiten, der aus Element-Suchvorgängen in mehrere Vererbungen Schnittstellen möglicherweise auftreten können, werden in beschrieben Schnittstelle Memberzugriff.The ambiguities that can possibly arise from member lookups in multiple-inheritance interfaces are described in Interface member access.

BasistypenBase types

Zum Zweck der Suche nach Membern, einen Typ T gilt folgenden Basistypen haben:For purposes of member lookup, a type T is considered to have the following base types:

  • Wenn T ist object, klicken Sie dann T keinen Basistyp hat.If T is object, then T has no base type.
  • Wenn T ist ein Enum_type, der Basistypen des T Klassentypen sind System.Enum, System.ValueType, und object.If T is an enum_type, the base types of T are the class types System.Enum, System.ValueType, and object.
  • Wenn T ist eine Struct_type, der Basistypen des T Klassentypen sind System.ValueType und object.If T is a struct_type, the base types of T are the class types System.ValueType and object.
  • Wenn T ist eine Class_type, der Basistypen des T sind die Basisklassen von T, einschließlich des Klassentyps object.If T is a class_type, the base types of T are the base classes of T, including the class type object.
  • Wenn T ist ein Interface_type, der Basistypen des T sind die Basisschnittstellen von T und den Klassentyp object.If T is an interface_type, the base types of T are the base interfaces of T and the class type object.
  • Wenn T ist ein Array_type, der Basistypen des T Klassentypen sind System.Array und object.If T is an array_type, the base types of T are the class types System.Array and object.
  • Wenn T ist eine Delegate_type, der Basistypen des T Klassentypen sind System.Delegate und object.If T is a delegate_type, the base types of T are the class types System.Delegate and object.

FunktionsmemberFunction members

Funktionsmember sind Elemente, die ausführbaren Anweisungen enthalten.Function members are members that contain executable statements. Funktionsmember sind immer Member von Typen und Member von Namespaces nicht möglich.Function members are always members of types and cannot be members of namespaces. C# -Code 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 von Destruktoren und statische Konstruktoren (die explizit nicht aufgerufen werden können), werden die Anweisungen im Funktionsmember über Funktionsaufrufe-Element 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 eigentliche Syntax für das Schreiben von einem Funktionsaufruf für das Element abhängig ist, auf die Memberkategorie bestimmte Funktion.The actual syntax for writing a function member invocation depends on the particular function member category.

Die Argumentliste (Argumentlisten) eines Elements für die Funktion bietet Aufruf tatsächliche Werte oder Variablenverweise für die Parameter, der das Funktionselement.The argument list (Argument lists) of a function member invocation provides actual values or variable references for the parameters of the function member.

Aufrufe von generischen Methoden können es sich um den Typrückschluss, um zu bestimmen, den Satz der Argumente des Typs der Methode zu übergebenden einsetzen.Invocations of generic methods may employ type inference to determine the set of type arguments to pass to the method. Dieser Prozess wird hier beschrieben Typrückschluss.This process is described in Type inference.

Aufrufe von Methoden, Indexer, Operatoren und Instanzkonstruktoren nutzen die Auflösung von funktionsüberladungen ermitteln, welche verschiedenen möglichen Funktionsmember aufrufen.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 hier beschrieben Überladungsauflösung.This process is described in Overload resolution.

Nachdem eine bestimmte Funktionsmember zum Zeitpunkt der Bindung identifiziert wurde, möglicherweise über die Auflösung von funktionsüberladungen, der tatsächliche Laufzeit-Prozess des Aufrufs der Funktionsmember der Member wird beschrieben in Überprüfungen zur Kompilierzeit der dynamischen überladungsauflösung.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.

Die folgende Tabelle enthält die Verarbeitung, die findet in Konstrukten, die im Zusammenhang mit den sechs Kategorien Funktionsmember, 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, x, y, und value klassifizierte Ausdrücke als Variablen oder Werte, T gibt einen Ausdruck, der als Typ klassifiziert F ist der einfache Name einer Methode, und klicken Sie auf P ist der einfache Name einer Eigenschaft.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) Überladungsauflösung wird angewendet, um die beste Methode wählen F in der enthaltenden Klasse oder Struktur.Overload resolution is applied to select the best method F in the containing class or struct. Die Methode wird aufgerufen, mit der Argumentliste (x,y).The method is invoked with the argument list (x,y). Wenn die Methode nicht static, ist der Instanzausdruck this.If the method is not static, the instance expression is this.
T.F(x,y) Überladungsauflösung wird angewendet, um die beste Methode wählen F in der Klasse oder Struktur T.Overload resolution is applied to select the best method F in the class or struct T. Ein Fehler während der Datenbindung tritt auf, wenn die Methode nicht static.A binding-time error occurs if the method is not static. Die Methode wird aufgerufen, mit der Argumentliste (x,y).The method is invoked with the argument list (x,y).
e.F(x,y) Überladungsauflösung wird angewendet, um die beste Methode F wählen Sie die Klasse, Struktur oder Schnittstelle, die durch den Typ des angegebenen e.Overload resolution is applied to select the best method F in the class, struct, or interface given by the type of e. Ein Fehler während der Datenbindung tritt auf, wenn die Methode static.A binding-time error occurs if the method is static. Die Methode wird aufgerufen, mit dem Instanzausdruck e und deren Argumentliste (x,y).The method is invoked with the instance expression e and the argument list (x,y).
EigenschaftenzugriffProperty access P Die 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 Fehler während der Kompilierung tritt auf, wenn P ist lesegeschützt.A compile-time error occurs if P is write-only. Wenn P nicht static, ist der Instanzausdruck this.If P is not static, the instance expression is this.
P = value Die set -Accessor der Eigenschaft P in der enthaltenden Klasse oder Struktur wird mit der Argumentliste aufgerufen (value).The set accessor of the property P in the containing class or struct is invoked with the argument list (value). Ein Fehler während der Kompilierung tritt auf, wenn P ist schreibgeschützt.A compile-time error occurs if P is read-only. Wenn P nicht static, ist der Instanzausdruck this.If P is not static, the instance expression is this.
T.P Die get -Accessor der Eigenschaft P in der Klasse oder Struktur T aufgerufen wird.The get accessor of the property P in the class or struct T is invoked. Ein Fehler während der Kompilierung tritt auf, wenn P nicht static oder, wenn P ist lesegeschützt.A compile-time error occurs if P is not static or if P is write-only.
T.P = value Die set -Accessor der Eigenschaft P in der Klasse oder Struktur T wird aufgerufen, mit der Argumentliste (value).The set accessor of the property P in the class or struct T is invoked with the argument list (value). Ein Fehler während der Kompilierung tritt auf, wenn P nicht static oder, wenn P ist schreibgeschützt.A compile-time error occurs if P is not static or if P is read-only.
e.P Die get -Accessor der Eigenschaft P in der Klasse, Struktur oder Schnittstelle, die durch den Typ des angegebenen e wird aufgerufen, mit dem Instanzausdruck 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 während der Datenbindung tritt auf, wenn P ist static oder, wenn P ist lesegeschützt.A binding-time error occurs if P is static or if P is write-only.
e.P = value Die set -Accessor der Eigenschaft P in der Klasse, Struktur oder Schnittstelle, die durch den Typ des angegebenen e wird aufgerufen, mit dem Instanzausdruck e und deren Argumentliste (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 während der Datenbindung tritt auf, wenn P ist static oder, wenn P ist schreibgeschützt.A binding-time error occurs if P is static or if P is read-only.
EreigniszugriffEvent access E += value Die 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 ist nicht statisch ist, der Instanzausdruck gibt this.If E is not static, the instance expression is this.
E -= value Die 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 ist nicht statisch ist, der Instanzausdruck gibt this.If E is not static, the instance expression is this.
T.E += value Die add Accessor des Ereignisses E in der Klasse oder Struktur T aufgerufen wird.The add accessor of the event E in the class or struct T is invoked. Ein Fehler während der Datenbindung tritt auf, wenn E ist nicht statisch.A binding-time error occurs if E is not static.
T.E -= value Die remove Accessor des Ereignisses E in der Klasse oder Struktur T aufgerufen wird.The remove accessor of the event E in the class or struct T is invoked. Ein Fehler während der Datenbindung tritt auf, wenn E ist nicht statisch.A binding-time error occurs if E is not static.
e.E += value Die add Accessor des Ereignisses E in der Klasse, Struktur oder Schnittstelle, die durch den Typ des angegebenen e wird aufgerufen, mit dem Instanzausdruck 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 während der Datenbindung tritt auf, wenn E ist statisch.A binding-time error occurs if E is static.
e.E -= value Die remove Accessor des Ereignisses E in der Klasse, Struktur oder Schnittstelle, die durch den Typ des angegebenen e wird aufgerufen, mit dem Instanzausdruck 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 während der Datenbindung tritt auf, wenn E ist statisch.A binding-time error occurs if E is static.
IndexerzugriffIndexer access e[x,y] Auflösung von funktionsüberladungen wird angewendet, um den besten Indexer in der-Klasse, Struktur oder Schnittstelle erhalten durch den Typ des e auszuwählen.Overload resolution is applied to select the best indexer in the class, struct, or interface given by the type of e. Die get Accessor des Indexers aufgerufen, mit dem Instanzausdruck e und deren Argumentliste (x,y).The get accessor of the indexer is invoked with the instance expression e and the argument list (x,y). Ein Fehler während der Datenbindung tritt auf, wenn der Indexer nur Schreibzugriff ist.A binding-time error occurs if the indexer is write-only.
e[x,y] = value Auflösung von funktionsüberladungen zur angewendet wird, wählen Sie den besten Indexer in der Klasse, Struktur oder Schnittstelle, die durch den Typ des angegebenen e.Overload resolution is applied to select the best indexer in the class, struct, or interface given by the type of e. Die set Accessor des Indexers aufgerufen, mit dem Instanzausdruck e und deren Argumentliste (x,y,value).The set accessor of the indexer is invoked with the instance expression e and the argument list (x,y,value). Ein Fehler während der Datenbindung tritt auf, wenn der Indexer schreibgeschützt ist.A binding-time error occurs if the indexer is read-only.
Operator-AufrufOperator invocation -x Auflösung von funktionsüberladungen zur angewendet wird, wählen Sie den besten unäroperator in der Klasse oder Struktur, die durch den Typ des angegebenen 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 aufgerufen, mit der Argumentliste (x).The selected operator is invoked with the argument list (x).
x + y Auflösung von funktionsüberladungen zur angewendet wird, wählen Sie den am besten binären Operator in Klassen oder Strukturen, die von den Typen der angegebenen x und 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 aufgerufen, mit der Argumentliste (x,y).The selected operator is invoked with the argument list (x,y).
Instanz-KonstruktoraufrufInstance constructor invocation new T(x,y) Überladungsauflösung wird angewendet, um den besten Instanzkonstruktor wählen Sie in der Klasse oder Struktur T.Overload resolution is applied to select the best instance constructor in the class or struct T. Der Instanzkonstruktor wird aufgerufen, mit der Argumentliste (x,y).The instance constructor is invoked with the argument list (x,y).

ArgumentlistenArgument lists

Jede Funktion Member und Delegataufruf enthält eine Argumentliste, die tatsächlichen Werte oder Variablenverweise für die Parameter, der das Funktionselement 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 Aufrufs der Funktion Mitglied hängt davon ab, auf die Memberkategorie Funktion:The syntax for specifying the argument list of a function member invocation depends on the function member category:

  • Z. B. Konstruktoren, Methoden, Indexer und Delegaten, die Argumente angegeben werden als eine Argument_listwie unten beschrieben.For instance constructors, methods, indexers and delegates, the arguments are specified as an argument_list, as described below. Für Indexer können beim Aufrufen der set -Accessor, die Argumentliste darüber hinaus enthält den Ausdruck, der als der Rechte Operand des Zuweisungsoperators angegeben.For indexers, when invoking the set accessor, the argument list additionally includes the expression specified as the right operand of the assignment operator.
  • Informationen zu Eigenschaften, die Argumentliste ist leer, beim Aufrufen der get Accessor und besteht aus den Ausdruck, der als der Rechte Operand des Zuweisungsoperators angegeben wird, beim Aufrufen der set Accessor.For properties, the argument list is empty when invoking the get accessor, and consists of the expression specified as the right operand of the assignment operator when invoking the set accessor.
  • Für Ereignisse, die Argumentliste des als der Rechte Operand des angegebenen Ausdrucks besteht aus den += oder -= Operator.For events, the argument list consists of the expression specified as the right operand of the += or -= operator.
  • Für benutzerdefinierte Operatoren besteht aus die Argumentliste den einzigen Operanden des unären Operators oder 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), Ereignisse (Ereignisse), und benutzerdefinierte Operatoren (Operatoren) werden immer als Parameter übergeben ( -Wertparameter).The arguments of properties (Properties), events (Events), and user-defined operators (Operators) are always passed as value parameters (Value parameters). Die Argumente von Indexern (Indexer) werden immer als Parameter übergeben (-Wertparameter) oder Parameterarrays (Parameterarrays).The arguments of indexers (Indexers) are always passed as value parameters (Value parameters) or parameter arrays (Parameter arrays). Referenz und Ausgabeparameter werden für diese Kategorien Funktionsmember nicht unterstützt.Reference and output parameters are not supported for these categories of function members.

Die Argumente für einen Instanz-Konstruktor, Methode, Indexer oder Delegat Aufruf angegeben werden, als ein Argument_list: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 Arguments, die durch Kommas getrennt.An argument_list consists of one or more arguments, 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 einer Argument_name wird als bezeichnet ein benanntes Argument, während ein Argument ohne eine Argument_name ist eine Positionsargument.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 positionelle Argumente nach der ein benanntes Argument in angezeigt werden ein Argument_list.It is an error for a positional argument to appear after a named argument in an argument_list.

Die Argument_value kann einen der folgenden Formen annehmen:The argument_value can take one of the following forms:

  • Ein Ausdruck, der angibt, der das Argument als ein Value-Parameter übergeben wird (-Wertparameter).An expression, indicating that the argument is passed as a value parameter (Value parameters).
  • Das Schlüsselwort ref gefolgt von einem Variable_reference (Variablenverweise), der angibt, der das Argument als Verweisparameter übergeben wird (Verweisparameter ).The keyword ref followed by a variable_reference (Variable references), indicating that the argument is passed as a reference parameter (Reference parameters). Eine Variable definitiv zugewiesen werden muss (definitive Zuweisung), bevor es als Verweisparameter übergeben werden kann.A variable must be definitely assigned (Definite assignment) before it can be passed as a reference parameter. Das Schlüsselwort out gefolgt von einem Variable_reference (Variablenverweise), der angibt, der das Argument als Output-Parameter übergeben wird (Ausgabeparameter).The keyword out followed by a variable_reference (Variable references), indicating that the argument is passed as an output parameter (Output parameters). Gilt als eine Variable definitiv zugewiesen (definitive Zuweisung) nach einem Member-Funktionsaufruf, in 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.

Entsprechenden ParameterCorresponding parameters

Für jedes Argument in einer Argumentliste es muss ein entsprechender Parameter in der Funktionsmember der Member oder der Delegat 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 Parameterliste, die in der folgenden verwendet wird wie folgt bestimmt:The parameter list used in the following is determined as follows:

  • Virtuelle Methoden und Indexer, die in Klassen definiert die Parameterliste wird aus der Deklaration der spezifischste ausgewählt oder außer Kraft setzen, der das Funktionselement, beginnend mit den statischen Typ des Empfängers, und ihre Basisklassen zu durchsuchen.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 Schnittstellenmethoden und Indexer die Liste ausgewählt ist die spezifischste Definition des Elements, beginnen mit dem Schnittstellentyp und das Durchsuchen von Basisschnittstellen bilden.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 unique-Parameter-Liste gefunden wird, wird eine Parameterliste kann nicht zugegriffen werden Namen und keine optionalen Parameter erstellt wird, sodass Aufrufe nicht benannte Parameter verwenden oder optionale Argumente auslassen.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.
  • Für partielle Methoden wird die Liste der definierenden Deklaration der partiellen Methode Parameter verwendet.For partial methods, the parameter list of the defining partial method declaration is used.
  • Ist es nur eine einzelner Parameter-Liste, die verwendet wird, für alle anderen Funktionsmember und Delegaten.For all other function members and delegates there is only a single parameter list, which is the one used.

Die Position des Arguments oder Parameter ist als die Anzahl der Argumente oder Parameter in der Argumentliste oder Parameterliste vorhergehenden definiert.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 die Argumente der Funktion Mitglied werden wie folgt festgelegt:The corresponding parameters for function member arguments are established as follows:

  • Argumente in der Argument_list Instanzkonstruktoren, Methoden, Indexer und Delegaten:Arguments in the argument_list of instance constructors, methods, indexers and delegates:
    • Dieser Parameter entspricht ein Positionsargument, in ein fixed-Parameter an der gleichen Position in der Parameterliste auftritt.A positional argument where a fixed parameter occurs at the same position in the parameter list corresponds to that parameter.
    • Positionelle Argumente eines Members der Funktion mit einem Parameterarray, das aufgerufen wird, in seiner normalen Form entspricht das Parameterarray, die an der gleichen Position in der Parameterliste erfolgen 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.
    • Positionelle Argumente eines Members der Funktion mit einem Parameterarray, das aufgerufen wird, in der erweiterten Form, in denen keine festen Parameter an der gleichen Position in der Parameterliste auftritt, entspricht einem Element im Parameterarray.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 der Parameter mit dem gleichen Namen in der Parameterliste.A named argument corresponds to the parameter of the same name in the parameter list.
    • Für Indexer können beim Aufrufen der set -Accessor, der Ausdruck angegeben, wie der Rechte Operand des Zuweisungsoperators impliziter entspricht value Parameter, der die set Zugriffsmethoden-Deklaration.For indexers, when invoking the set accessor, the expression specified as the right operand of the assignment operator corresponds to the implicit value parameter of the set accessor declaration.
  • Informationen zu Eigenschaften, die beim Aufrufen der get Accessor gibt es keine Argumente sind.For properties, when invoking the get accessor there are no arguments. Beim Aufrufen der set -Accessor, der Ausdruck angegeben, wie der Rechte Operand des Zuweisungsoperators impliziter entspricht value Parameter, der die set Zugriffsmethoden-Deklaration.When invoking the set accessor, the expression specified as the right operand of the assignment operator corresponds to the implicit value parameter of the set accessor declaration.
  • Der einzige Parameter der Operatordeklaration entspricht der einzelne Operanden aus, für den benutzerdefinierten unäre Operatoren (einschließlich Konvertierungen).For user-defined unary operators (including conversions), the single operand corresponds to the single parameter of the operator declaration.
  • Für eine benutzerdefinierte binäre Operatoren der linke Operand entspricht des ersten Parameters, und der Rechte Operand des zweiten Parameters der Operator-Deklaration entspricht.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.

Laufzeitauswertung von ArgumentenlistenRun-time evaluation of argument lists

Bei der Verarbeitung zur Laufzeit eine Member-Funktionsaufruf (Überprüfungen zur Kompilierzeit der dynamischen überladungsauflösung), die Ausdrücke oder Variablenverweise einer Argumentliste werden in der Reihenfolge von links nach rechts ausgewertet, als Die folgende: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:

  • Für eine Value-Parameter der Argumentausdruck ausgewertet und eine implizite Konvertierung (implizite Konvertierungen) an den entsprechenden Parameter ausgeführt wird.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 der Anfangswert des Value-Parameters in der Aufruf an.The resulting value becomes the initial value of the value parameter in the function member invocation.
  • Für einen Verweis oder Ausgabe-Parameter der Variable Verweis ausgewertet wird und der daraus resultierende Speicherort der Speicherort, der durch den Parameter im Funktionsaufruf Element 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. Der Variablenverweis als ein Verweis oder Ausgabe-Parameter ist ein Arrayelement einen Reference_type, eine laufzeitüberprüfung ausgeführt, um sicherzustellen, dass der Elementtyp des Arrays in den Typ des Parameters 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 diese Überprüfung fehlschlägt, eine System.ArrayTypeMismatchException ausgelöst.If this check fails, a System.ArrayTypeMismatchException is thrown.

Methoden, Indexer und Instanzkonstruktoren deklarieren, können der am weitesten rechts befindlichen-Parameter ein Parameterarray sein (Parameterarrays).Methods, indexers, and instance constructors may declare their right-most parameter to be a parameter array (Parameter arrays). Solche Funktionsmember werden aufgerufen, entweder in ihrer normalen Form oder in ihre erweiterte Form, die je nach geltenden (Anwendbarer 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 Parameterarray in seiner normalen Form aufgerufen wird, muss das Argument für das Parameterarray erhält einen einzelnen Ausdruck, der implizit konvertiert werden kann (implizite Konvertierungen) in den Parameter-Arraytyp.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 Parameterarray genau wie ein Value-Parameter.In this case, the parameter array acts precisely like a value parameter.
  • Wenn ein Funktionsmember mit einem Parameterarray in erweiterter Form aufgerufen wird, muss der Aufruf NULL oder mehr positionelle Argumente für das Parameterarray, wobei jedes Argument ist ein Ausdruck, der implizit konvertiert werden angeben (implizite Konvertierungen), die den Elementtyp des Parameterarrays.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 der Aufruf erstellt eine Instanz des Parameterarraytyps mit einer Länge, die Anzahl von Argumenten entspricht, initialisiert die Elemente der Arrayinstanz mit den Werten des angegebenen Arguments und verwendet die neu erstellte Array-Instanz als die tatsächliche 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, die 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) zulassen den Wert eines Arraytyps A[] sollen einen Verweis auf eine Instanz des Arraytyps B[], sofern eine implizite verweiskonvertierung von vorhanden ist B zu 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, wenn ein Arrayelement einen Reference_type übergeben als Verweis oder Ausgabe, wird eine laufzeitüberprüfung erforderlich, um sicherzustellen, dass der tatsächliche Elementtyp des Arrays, des Parameters entspricht.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, dass eine System.ArrayTypeMismatchException ausgelöst, weil der tatsächliche Elementtyp des 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 Parameterarray in erweiterter Form aufgerufen wird, wird der Aufruf verarbeitet, als ob ein Ausdruck zur Arrayerstellung mit einem Arrayinitialisierer (Array-Ausdrücke für die Arrayerstellung) eingefügt wurde, um die Erweiterte Parameter.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. Z. B. im Falle folgender DeklarationFor example, given the declaration

void F(int x, int y, params object[] args);

die folgenden Aufrufe, der die erweiterte 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 überein mitcorrespond 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 angegeben, für das Parameterarray vorhanden sind.In particular, note that an empty array is created when there are zero arguments given for the parameter array.

Wenn ein Funktionsmember mit entsprechenden optionalen Parametern Argumente ausgelassen werden, werden die Standardargumente von der Members-Funktionsdeklaration implizit übergeben.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 ihrer Auswertung nicht die Auswertungsreihenfolge der restlichen Argumente.Because these are always constant, their evaluation will not impact the evaluation order of the remaining arguments.

TyprückschlussType inference

Wenn eine generische Methode aufgerufen wird, ohne Angabe von Typargumenten, eine Typrückschluss Prozess versucht, die 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 Vorhandensein des Typrückschlusses können eine komfortablere Syntax zum Aufrufen einer generischen Methode verwendet werden soll, und ermöglicht es den Programmierer, vermeiden Sie redundante Informationen angeben.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. Betrachten Sie z. B. die Deklaration der Methode ein: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, rufen Sie die Choose Methode ohne explizite Angabe ein Argument vom Typ: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>

Mithilfe des Typrückschlusses die Typargumente int und string werden aus den Argumenten der Methode bestimmt.Through type inference, the type arguments int and string are determined from the arguments to the method.

Der Typrückschluss tritt als Teil der Bindung-Time-Verarbeitung eines Methodenaufrufs (Methodenaufrufe) und erfolgt vor dem Schritt zur überladungsauflösung des Aufrufs.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 Methode, die Gruppe in einem Methodenaufruf angegeben ist und keine Typargumente werden als Teil des Methodenaufrufs angegeben, wird ein Typrückschluss auf jede generische Methode in der Methodengruppe 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 Typrückschluss erfolgreich ist, werden die abgeleiteten Typargumente verwendet, um die Typen der Argumente für die nachfolgenden überladungsauflö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 der Auflösung von funktionsüberladungen eine generische Methode wie das aufzurufende auswählt, werden dann die abgeleiteten Typargumente als die 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 Typrückschluss für eine bestimmte Methode fehlschlägt, diese Methode an der überladungsauflösung nicht teilnehmen.If type inference for a particular method fails, that method does not participate in overload resolution. Der Ausfall des Typrückschlusses an und für sich selbst, bewirkt einen Fehler während der Bindung nicht.The failure of type inference, in and of itself, does not cause a binding-time error. Allerdings führt es häufig zu einem Fehler während der Bindung bei der Auflösung von funktionsüberladungen funktioniert nicht mehr alle entsprechenden Methoden zu finden.However, it often leads to a binding-time error when overload resolution then fails to find any applicable methods.

Wenn die angegebene Anzahl von Argumenten anders als die Anzahl von Parametern in der Methode ist, klicken Sie dann Typrückschluss schlägt sofort fehl.If the supplied number of arguments is different than the number of parameters in the method, then inference immediately fails. Andernfalls wird angenommen Sie, dass die generische Methode die folgende Signatur:Otherwise, assume that the generic method has the following signature:

Tr M<X1,...,Xn>(T1 x1, ..., Tm xm)

Durch einen Methodenaufruf des Formulars M(E1...Em) die Aufgabe des Typrückschlusses besteht darin, eindeutige Typargumente finden S1...Sn für jeden der Typparameter X1...Xn , damit der Aufruf 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.

Bei der Ableitung der einzelnen Typparameter Xi ist entweder festen auf einen bestimmten Typ Si oder unfixed mit einem zugeordneten Satz Grenzen.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 Grenzen ist eine Art T.Each of the bounds is some type T. Zunächst jede Variable vom Typ Xi ist mit einem leeren Satz von Grenzen unfixed.Initially each type variable Xi is unfixed with an empty set of bounds.

Typrückschluss erfolgt in mehreren Phasen.Type inference takes place in phases. Jede Phase versucht, die Typargumente für weitere basierten auf die Ergebnisse der vorherigen Phase Variablen abzuleiten.Each phase will try to infer type arguments for more type variables based on the findings of the previous phase. In der erste Phase macht einige anfängliche Rückschlüsse ziehen, der den angegebenen Begrenzungen, während die zweite Phase Typvariablen auf bestimmte Typen korrigiert und weiter Grenzen leitet.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 möglicherweise werden eine Anzahl von Malen wiederholt.The second phase may have to be repeated a number of times.

Hinweis: Typ erfolgt Typrückschluss nicht nur, wenn eine generische Methode aufgerufen wird.Note: Type inference takes place not only when a generic method is called. Typrückschluss für die Konvertierung von Methodengruppen finden Sie im Typrückschluss für die Konvertierung von Methodengruppen und suchen den besten common-Typ, der einen Satz von Ausdrücken finden Sie im Suchen des beste allgemeine Typs einer Gruppe Ausdrücke.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 jede der Methodenargumente Ei:For each of the method arguments Ei:

  • Wenn Ei ist eine anonyme Funktion, ein expliziter Parameter Typrückschluss (expliziter Parameter Typrückschlüsse) besteht aus Ei auf TiIf Ei is an anonymous function, an explicit parameter type inference (Explicit parameter type inferences) is made from Ei to Ti
  • Andernfalls gilt: Wenn Ei weist einen Typ U und xi ist ein Werteparameter ein untere Begrenzung Typrückschluss erfolgt aus U zu Ti.Otherwise, if Ei has a type U and xi is a value parameter then a lower-bound inference is made from U to Ti.
  • Andernfalls gilt: Wenn Ei weist einen Typ U und xi ist eine ref oder out Parameter ein genauer Typrückschluss erfolgt aus U zu Ti.Otherwise, if Ei has a type U and xi is a ref or out parameter then an exact inference is made from U to Ti.
  • Andernfalls erfolgt kein Rückschluss für dieses Argument.Otherwise, no inference is made for this argument.

Die zweite phaseThe second phase

In der zweite Phase wird wie folgt aus:The second phase proceeds as follows:

  • Alle unfixed Variablen des Typs Xi der nicht richten sich nach (Abhängigkeit) alle Xj haben eine feste (Festsetzung von).All unfixed type variables Xi which do not depend on (Dependence) any Xj are fixed (Fixing).
  • Wenn kein solcher Typvariablen vorhanden sind, alle unfixed Variablen des Typs Xi sind festen für die alle der folgenden enthalten:If no such type variables exist, all unfixed type variables Xi are fixed for which all of the following hold:
    • Es ist mindestens ein Typvariable Xj das hängt vom XiThere is at least one type variable Xj that depends on Xi
    • Xi verfügt über ein nicht leerer Satz von GrenzenXi has a non-empty set of bounds
  • Wenn kein solcher Typvariablen vorhanden sind und es immer noch gibt unfixed Variablen des Typs, geben der Typrückschluss schlägt fehl.If no such type variables exist and there are still unfixed type variables, type inference fails.
  • Andernfalls, wenn keine weiteren unfixed Variablen vom Typ vorhanden ist, wird ein Typrückschluss erfolgreich ausgeführt wird.Otherwise, if no further unfixed type variables exist, type inference succeeds.
  • Andernfalls für alle Argumente Ei mit entsprechenden Parametertyps Ti , in denen die Ausgabetypen (Ausgabetypen) enthalten unfixed Variablen vom Typ Xj jedoch Eingabetypen (Eingabetypen) ist dies kein Ausgabe Typrückschluss (Typrückschlüsse Ausgabe ) erfolgt aus Ei zu Ti.Otherwise, for all arguments Ei with corresponding parameter type Ti where the output types (Output types) contain unfixed type variables Xj but the input types (Input types) do not, an output type inference (Output type inferences) is made from Ei to Ti. Anschließend wird die zweite Phase wiederholt.Then the second phase is repeated.

EingabetypenInput types

Wenn E ist eine Methodengruppe oder anonyme Funktion von implizit typisierten und T ist ein Delegat, Typ oder Typ für die Ausdrucksbaumstruktur und die Parametertypen der T sind Eingabetypen von E mit 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 ist einer Methodengruppe oder einer anonymen Funktion und T ist ein Delegat, Typ oder Typ für die Ausdrucksbaumstruktur und den Rückgabetyp der T ist ein Ausgabetyp der E mit 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.

AbhängigkeitDependence

Ein unfixed Variablen vom Typ Xi hängt direkt von eine Variable unfixed vom Typ Xj If für einige Argument Ek mit Typ Tk Xj Tritt auf, eine Eingabetyp von Ek mit Typ Tk und Xi tritt auf, eine Ausgabetyp von Ek mit Typ 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 Xi Wenn Xj hängt direkt von Xi oder, wenn Xi hängt direkt von Xk und Xk hängt 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" transitiv, aber keine reflexive Abschluss von "hängt direkt von".Thus "depends on" is the transitive but not reflexive closure of "depends directly on".

Ausgabe TyprückschlüsseOutput type inferences

Ein Ausgabe Typrückschluss erfolgt aus eines Ausdrucks E zu ein T auf folgende Weise:An output type inference is made from an expression E to a type T in the following way:

  • Wenn E ist eine anonyme Funktion hergeleiteten Rückgabetyp U (abgeleiteter Rückgabetyp) und T ist ein Delegat oder Typ für die Ausdrucksbaumstruktur mit Rückgabetyp Tb, klicken Sie dann eine untere Begrenzung Typrückschluss (untere Begrenzung Rückschlüsse) erfolgt aus U zu Tb.If E is an anonymous function with inferred return type U (Inferred return type) and T is a delegate type or expression tree type with return type Tb, then a lower-bound inference (Lower-bound inferences) is made from U to Tb.
  • Andernfalls gilt: Wenn E ist eine Methodengruppe und T ist ein Delegat oder Typ mit den Parametertypen für die Ausdrucksbaumstruktur T1...Tk und den Rückgabetyp Tb, und die überladungsauflösung von E mit den Typen T1...Tk ergibt eine einzige Methode, mit dem Rückgabetyp U, ein untere Begrenzung Typrückschluss erfolgt aus U zu Tb.Otherwise, if E is a method group and T is a delegate type or expression tree type with parameter types T1...Tk and return type Tb, and overload resolution of E with the types T1...Tk yields a single method with return type U, then a lower-bound inference is made from U to Tb.
  • Andernfalls gilt: Wenn E ist ein Ausdruck mit Typ U, ein untere Begrenzung Typrückschluss erfolgt aus U zu T.Otherwise, if E is an expression with type U, then a lower-bound inference is made from U to T.
  • Andernfalls werden keine Rückschlüsse vorgenommen.Otherwise, no inferences are made.

Expliziter Parameter TyprückschlüsseExplicit parameter type inferences

Ein expliziter Parameter Typrückschluss erfolgt aus eines Ausdrucks E zu ein T auf folgende Weise:An explicit parameter type inference is made from an expression E to a type T in the following way:

  • Wenn E ist eine explizit typisierte anonyme Funktion mit den Parametertypen U1...Uk und T ist ein Delegat oder Typ mit den Parametertypen für die Ausdrucksbaumstruktur V1...Vk klicken Sie dann für jeden Ui ein genaue Typrückschluss (genauer Rückschlüsse) erfolgt aus Ui zu entsprechenden Vi.If E is an explicitly typed anonymous function with parameter types U1...Uk and T is a delegate type or expression tree type with parameter types V1...Vk then for each Ui an exact inference (Exact inferences) is made from Ui to the corresponding Vi.

Genaue RückschlüsseExact inferences

Ein genauer Typrückschluss aus ein U zu ein V erfolgt wie folgt:An exact inference from a type U to a type V is made as follows:

  • Wenn V ist eines der der unfixed Xi dann U hinzugefügt wird, auf den Satz der genauen Grenzen für Xi.If V is one of the unfixed Xi then U is added to the set of exact bounds for Xi.

  • Andernfalls legt V1...Vk und U1...Uk werden bestimmt, indem Sie überprüfen, ob eine der folgenden Fälle zutrifft:Otherwise, sets V1...Vk and U1...Uk are determined by checking if any of the following cases apply:

    • V ist ein Arraytyp V1[...] und U ist ein Arraytyp U1[...] von den gleichen RangV is an array type V1[...] and U is an array type U1[...] of the same rank
    • V Der Typ V1? und U ist der Typ U1?V is the type V1? and U is the type U1?
    • V wird von ein konstruierter Typ C<V1...Vk>und U ein konstruierter Typ ist C<U1...Uk>V is a constructed type C<V1...Vk>and U is a constructed type C<U1...Uk>

    Wenn es sich bei jedem dieser Fälle wenden Sie dann eine genauer Typrückschluss erfolgt aus jedes Ui zu der entsprechenden Vi.If any of these cases apply then an exact inference is made from each Ui to the corresponding Vi.

  • Andernfalls werden keine Rückschlüsse vorgenommen.Otherwise no inferences are made.

Untere Begrenzung RückschlüsseLower-bound inferences

Ein untere Begrenzung Typrückschluss aus ein U zu ein V erfolgt wie folgt:A lower-bound inference from a type U to a type V is made as follows:

  • Wenn V ist eines der der unfixed Xi dann U hinzugefügt wird, auf die unteren Grenzen Xi.If V is one of the unfixed Xi then U is added to the set of lower bounds for Xi.

  • Andernfalls gilt: Wenn V ist der Typ V1?und U ist der Typ U1? eine untere Grenze Rückschluss aus erfolgt U1 zu V1.Otherwise, if V is the type V1?and U is the type U1? then a lower bound inference is made from U1 to V1.

  • Andernfalls legt U1...Uk und V1...Vk werden bestimmt, indem Sie überprüfen, ob eine der folgenden Fälle zutrifft:Otherwise, sets U1...Uk and V1...Vk are determined by checking if any of the following cases apply:

    • V ist ein Arraytyp V1[...] und U ist ein Arraytyp U1[...] (oder ein Typparameter, dessen effektive Basistyp ist U1[...]) von den gleichen RangV is an array type V1[...] and U is an array type U1[...] (or a type parameter whose effective base type is U1[...]) of the same rank

    • V ist eine der IEnumerable<V1>, ICollection<V1> oder IList<V1> und U ist ein eindimensionales Array U1[](oder ein Typparameter, dessen effektive Basistyp ist U1[])V is one of IEnumerable<V1>, ICollection<V1> or IList<V1> and U is a one-dimensional array type U1[](or a type parameter whose effective base type is U1[])

    • V ist ein konstruierter Typ der Klasse, Struktur, Schnittstelle oder Delegaten C<V1...Vk> und es ist ein eindeutiger Typ C<U1...Uk> so, dass U (oder, wenn Sie U ist ein Typparameter, effektive Basisklasse oder ein Mitglied der effektive Satz) ist mit dieser identisch (direkt oder indirekt) erbt, oder implementiert (direkt oder indirekt) C<U1...Uk>.V is a constructed class, struct, interface or delegate type C<V1...Vk> and there is a unique type C<U1...Uk> such that U (or, if U 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 Einschränkung "Eindeutigkeit" bedeutet, dass in der Groß-/Kleinschreibung Schnittstelle C<T> {} class U: C<X>, C<Y> {}, erfolgt kein Rückschluss beim Ableiten von U zu C<T> da U1 möglicherweise X oder Y.)(The "uniqueness" restriction means that in the case interface C<T> {} class U: C<X>, C<Y> {}, then no inference is made when inferring from U to C<T> because U1 could be X or Y.)

    Wenn eine dieser Fälle zutrifft, ein Typrückschluss erfolgt aus jedes Ui zu entsprechenden Vi wie folgt:If any of these cases apply then an inference is made from each Ui to the corresponding Vi as follows:

    • Wenn Ui ist ein Verweistyp ist nicht bekannt wird eine genauer Typrückschluss erfolgtIf Ui is not known to be a reference type then an exact inference is made
    • Andernfalls gilt: Wenn U ist ein Arraytyp wird eine untere Begrenzung Typrückschluss erfolgtOtherwise, if U is an array type then a lower-bound inference is made
    • Andernfalls gilt: Wenn V ist C<V1...Vk> und klicken Sie dann die i-th-Typparameter der Rückschluss abhängt C:Otherwise, if V is C<V1...Vk> then inference depends on the i-th type parameter of C:
      • Wenn es kovariant ist ein untere Begrenzung Typrückschluss erfolgt.If it is covariant then a lower-bound inference is made.
      • Wenn es sich um kontravariant ist ein Obergrenze Typrückschluss erfolgt.If it is contravariant then an upper-bound inference is made.
      • Wenn er unveränderlich ist ein genauer Typrückschluss erfolgt.If it is invariant then an exact inference is made.
  • Andernfalls werden keine Rückschlüsse vorgenommen.Otherwise, no inferences are made.

Obere Grenze RückschlüsseUpper-bound inferences

Ein Obergrenze Typrückschluss aus ein U zu ein V erfolgt wie folgt:An upper-bound inference from a type U to a type V is made as follows:

  • Wenn V ist eines der der unfixed Xi dann U hinzugefügt wird, auf die oberen Grenzen Xi.If V is one of the unfixed Xi then U is added to the set of upper bounds for Xi.

  • Andernfalls legt V1...Vk und U1...Uk werden bestimmt, indem Sie überprüfen, ob eine der folgenden Fälle zutrifft:Otherwise, sets V1...Vk and U1...Uk are determined by checking if any of the following cases apply:

    • U ist ein Arraytyp U1[...] und V ist ein Arraytyp V1[...] von den gleichen RangU is an array type U1[...] and V is an array type V1[...] of the same rank

    • U ist eine der IEnumerable<Ue>, ICollection<Ue> oder IList<Ue> und V ist ein eindimensionales Array-Typ Ve[]U is one of IEnumerable<Ue>, ICollection<Ue> or IList<Ue> and V is a one-dimensional array type Ve[]

    • U Der Typ U1? und V ist der Typ V1?U is the type U1? and V is the type V1?

    • U ist der konstruierten Klasse, Struktur, Schnittstelle oder ein Delegattyp C<U1...Uk> und V wird von einer Klasse, Struktur, Schnittstellen oder Delegate-Typ, der mit erbt (direkt oder indirekt) identisch ist oder implementiert (direkt oder indirekt) ein eindeutiger Typ C<V1...Vk>U is constructed class, struct, interface or delegate type C<U1...Uk> and V is a class, struct, interface or delegate type which is identical to, inherits from (directly or indirectly), or implements (directly or indirectly) a unique type C<V1...Vk>

      (Die Einschränkung "Eindeutigkeit" bedeutet, dass bei wir interface C<T>{} class V<Z>: C<X<Z>>, C<Y<Z>>{}, erfolgt kein Rückschluss beim Ableiten von C<U1> zu V<Q>.(The "uniqueness" restriction means that if we have interface C<T>{} class V<Z>: C<X<Z>>, C<Y<Z>>{}, then no inference is made when inferring from C<U1> to V<Q>. Rückschlüsse erfolgen keine U1 entweder X<Q> oder Y<Q>.)Inferences are not made from U1 to either X<Q> or Y<Q>.)

    Wenn eine dieser Fälle zutrifft, ein Typrückschluss erfolgt aus jedes Ui zu entsprechenden Vi wie folgt:If any of these cases apply then an inference is made from each Ui to the corresponding Vi as follows:

    • Wenn Ui ist ein Verweistyp ist nicht bekannt wird eine genauer Typrückschluss erfolgtIf Ui is not known to be a reference type then an exact inference is made
    • Andernfalls gilt: Wenn V ist ein Arraytyp wird eine Obergrenze Typrückschluss erfolgtOtherwise, if V is an array type then an upper-bound inference is made
    • Andernfalls gilt: Wenn U ist C<U1...Uk> und klicken Sie dann die i-th-Typparameter der Rückschluss abhängt C:Otherwise, if U is C<U1...Uk> then inference depends on the i-th type parameter of C:
      • Wenn es kovariant ist ein Obergrenze Typrückschluss erfolgt.If it is covariant then an upper-bound inference is made.
      • Wenn es sich um kontravariant ist ein untere Begrenzung Typrückschluss erfolgt.If it is contravariant then a lower-bound inference is made.
      • Wenn er unveränderlich ist ein genauer Typrückschluss erfolgt.If it is invariant then an exact inference is made.
  • Andernfalls werden keine Rückschlüsse vorgenommen.Otherwise, no inferences are made.

Beheben vonFixing

Ein unfixed Variablen vom Typ Xi ist mit einem Satz von Grenzen festen wie folgt:An unfixed type variable Xi with a set of bounds is fixed as follows:

  • Der Satz von potenzieller Typen Uj als Satz aller Typen in den Satz von Grenzen für beginnt Xi.The set of candidate types Uj starts out as the set of all types in the set of bounds for Xi.
  • Klicken Sie dann untersuchen wir jede Grenze für Xi wiederum: Für jede genau gebundene U von Xi alle Typen Uj die sind nicht identisch mit U werden aus dem Satz von Kandidaten entfernt.We then examine each bound for Xi in turn: For each exact bound U of Xi all types Uj which are not identical to U are removed from the candidate set. Für jede untere Grenze U von Xi alle Typen Uj ist auf die dort nicht eine implizite Konvertierung von U werden aus dem Satz von Kandidaten entfernt.For each lower bound U of Xi all types Uj to which there is not an implicit conversion from U are removed from the candidate set. Für jede Obergrenze U von Xi alle Typen Uj wird die dort nicht eine implizite Konvertierung in U werden aus dem Satz von Kandidaten entfernt.For each upper bound U of Xi all types Uj from which there is not an implicit conversion to U are removed from the candidate set.
  • If zu den Typen der verbleibenden Candidate Uj es ist ein eindeutiger Typ V von dem es eine implizite Konvertierung auf alle anderen möglichen Typen, klicken Sie dann Xi ist fest in V.If among the remaining candidate types Uj there is a unique type V from which there is an implicit conversion to all the other candidate types, then Xi is fixed to V.
  • Andernfalls schlägt die Typrückschluss fehl.Otherwise, type inference fails.

Abgeleiteter RückgabetypInferred return type

Die hergeleiteten Rückgabetyp von einer anonymen Funktion F wird während der typauflösung inferenz und die Überladung verwendet.The inferred return type of an anonymous function F is used during type inference and overload resolution. Der hergeleitete Rückgabetyp kann nur für eine anonyme Funktion, in denen alle Parameter, den Typen bekannt sind, entweder weil sie explizit angegeben sind, über eine anonyme Funktion Konvertierung bereitgestellt oder abgeleitet wird, während der Typrückschluss in einer einschließenden generischen, ermittelt werden Methodenaufruf.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.

Die abgeleitet Ergebnistyp wird wie folgt bestimmt:The inferred result type is determined as follows:

  • Wenn der Text der F ist ein Ausdruck , bei dem ein Typ, und klicken Sie dann auf die hergeleiteten Rückgabetyp des F ist der Typ dieses Ausdrucks.If the body of F is an expression that has a type, then the inferred result type of F is the type of that expression.
  • Wenn der Text der F ist eine Block und der Satz von Ausdrücken im Block return -Anweisungen verfügt auch über einen bewährten gemeinsamen Typ T (Suchen nach den besten common-Typ, der einen Satz von Ausdrücken), klicken Sie dann die hergeleiteten Rückgabetyp des F ist T.If the body of F is a block and the set of expressions in the block's return statements has a best common type T (Finding the best common type of a set of expressions), then the inferred result type of F is T.
  • Andernfalls kann kein Ergebnistyp abgeleitet werden, für die F.Otherwise, a result type cannot be inferred for F.

Die Rückgabetyp abgeleitet wird wie folgt bestimmt:The inferred return type is determined as follows:

  • Wenn F ist asynchron und der Text der F ist entweder ein Ausdruck als "nothing" klassifiziert sind (ausdrucksklassifizierungen), oder einen Anweisungsblock, die keine return-Anweisungen, in dem Ausdrücke haben, die hergeleiteten Rückgabetyp ist System.Threading.Tasks.TaskIf F is async and the body of F is either an expression classified as nothing (Expression classifications), or a statement block where no return statements have expressions, the inferred return type is System.Threading.Tasks.Task
  • Wenn F Async, verfügt über eine abgeleitete Ergebnistyp T, die hergeleiteten Rückgabetyp ist System.Threading.Tasks.Task<T>.If F is async and has an inferred result type T, the inferred return type is System.Threading.Tasks.Task<T>.
  • Wenn F nicht asynchronen, verfügt über eine abgeleitete Ergebnistyp T, die hergeleiteten Rückgabetyp ist T.If F is non-async and has an inferred result type T, the inferred return type is T.
  • Andernfalls kann kein Rückgabetyp abgeleitet werden, für die F.Otherwise a return type cannot be inferred for F.

Betrachten Sie als ein Beispiel für den Typrückschluss, die im Zusammenhang mit anonymen Funktionen, die Select Erweiterungsmethode deklariert wird, der System.Linq.Enumerable Klasse: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 die System.Linq Namespace importiert wurde, mit einer using -Klausel, und erhalten Sie eine Klasse Customer mit eine Name Eigenschaft vom Typ string, Select Methode kann verwendet werden, um die Namen der eine Liste der Kunden auswä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 (Erweiterung Methodenaufrufe) der Select verarbeitet wird, durch den Aufruf zu Aufruf einer statischen Methode umschreiben: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 Sie nicht explizit Typargumente angegeben wurden, werden den Typrückschluss die Typargumente abzuleiten.Since type arguments were not explicitly specified, type inference is used to infer the type arguments. Zuerst die customers Argument bezieht sich auf die source Parameter Ableiten von T sein Customer.First, the customers argument is related to the source parameter, inferring T to be Customer. Mithilfe der anonymen Funktion geben Sie dann oben beschriebenen Rückschlussprozess c erhält den Typ Customer, und der Ausdruck c.Name bezieht sich auf den Rückgabetyp der selector Parameter Ableiten von S seinstring.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 ist der Aufruf entsprichtThus, 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 folgende Beispiel wird veranschaulicht, wie anonyme Funktionstyp Typrückschluss ermöglicht die Typinformationen für "flow zwischen Argumenten im Aufruf einer generischen Methode".The following example demonstrates how anonymous function type inference allows type information to "flow" between arguments in a generic method invocation. Betrachten Sie die Methode ein:Given the method:

static Z F<X,Y,Z>(X value, Func<X,Y> f1, Func<Y,Z> f2) {
    return f2(f1(value));
}

Der Typrückschluss für den Aufruf:Type inference for the invocation:

double seconds = F("1:15:30", s => TimeSpan.Parse(s), t => t.TotalSeconds);

wird wie folgt: Zunächst wird das Argument "1:15:30" bezieht sich auf die value Parameter Ableiten von X sein string.proceeds as follows: First, the argument "1:15:30" is related to the value parameter, inferring X to be string. Klicken Sie dann, den Parameter der ersten anonymen Funktion s, erhält den abgeleiteten Typ string, und der Ausdruck TimeSpan.Parse(s) bezieht sich auf den Rückgabetyp der f1, ableiten von Y sein 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. Abschließend den Parameter der zweiten anonyme Funktion t, erhält den abgeleiteten Typ System.TimeSpan, und der Ausdruck t.TotalSeconds bezieht sich auf den Rückgabetyp der f2, ableiten von Z sein 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 Aufrufs, vom Typ double.Thus, the result of the invocation is of type double.

Typrückschluss für die Konvertierung von MethodengruppenType inference for conversion of method groups

Ähnlich wie Aufrufe der Methoden, Typrückschluss muss auch angewendet, wenn eine Methodengruppe M einer generischen Methode mit einem bestimmten Delegattyp konvertiert D (Gruppe 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). Wenn eine MethodeGiven a method

Tr M<X1...Xn>(T1 x1 ... Tm xm)

und die Methodengruppe M zugewiesen wird, in den Delegattyp D die Aufgabe des Typrückschlusses besteht darin, finden Sie Typargumente S1...Sn , damit 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>

kompatibel ist (delegieren Deklarationen) mit D.becomes compatible (Delegate declarations) with D.

Im Gegensatz zum Typ Typrückschluss für generische Methodenaufrufen, in diesem Fall stehen nur Argument Typen, kein Argument Ausdrücke.Unlike the type inference algorithm for generic method calls, in this case there are only argument types, no argument expressions. Vor allem keine anonymen Funktionen vorhanden sind und daher keine Notwendigkeit, mehrere Phasen der Typrückschluss.In particular, there are no anonymous functions and hence no need for multiple phases of inference.

Stattdessen alle Xi gelten unfixed, und ein untere Begrenzung Typrückschluss erfolgt aus jeder Argumenttyp Uj von D zu entsprechenden Parametertyps Tj von 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. If für eines der Xi keine Grenzen gefunden, der Typrückschluss schlägt fehl.If for any of the Xi no bounds were found, type inference fails. Andernfalls alle Xi sind behoben entsprechenden Si, die das Ergebnis des Typrückschlusses sind.Otherwise, all Xi are fixed to corresponding Si, which are the result of type inference.

Suchen den besten common-Typ, der einen Satz von AusdrückenFinding the best common type of a set of expressions

In einigen Fällen muss kein 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 die Elementtypen eines implizit typisierte Arrays und die Rückgabetypen der anonymen Funktionen mit Block Stellen auf diese Weise gefunden werden.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 anhand eines Satzes von Ausdrücken E1...Em dieser Rückschluss muss dem Aufruf einer MethodeIntuitively, given a set of expressions E1...Em this inference should be equivalent to calling a method

Tr M<X>(X x1 ... X xm)

mit der Ei als Argumente.with the Ei as arguments.

Genauer gesagt: die Ableitung beginnt mit einem unfixed Variablen vom Typ X.More precisely, the inference starts out with an unfixed type variable X. Ausgabe Typrückschlüsse werden durchgeführt, aus jedes Ei zu X.Output type inferences are then made from each Ei to X. Zum Schluss X ist festen und geben Sie bei erfolgreicher Ausführung der resultierenden S ist der resultierende bewährte gemeinsame 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 keine solche S vorhanden ist, die Ausdrücke besitzen kein optimaler Typ für die allgemeine.If no such S exists, the expressions have no best common type.

Auflösung von funktionsüberladungenOverload resolution

Überladungsauflösung ist eine Bindung-Time-Mechanismus für die Auswahl der am besten geeigneten Funktionsmembers angegebenen Argumentliste und einen Satz von möglichen Funktionsmembern aufrufen.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. Wählt die überladungsauflösung die Funktionsmember der Member in den folgenden unterschiedlichen Kontexten in C# -Code aufrufen:Overload resolution selects the function member to invoke in the following distinct contexts within C#:

Alle diese Kontexte definiert den Satz von möglichen Funktionsmembern und die Liste der Argumente in ihre eigenen Methoden, 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. Der Satz von Kandidaten für einen Methodenaufruf enthält z. B. keine markierte Methoden override (Membersuche), und Methoden in einer Basisklasse sind nicht Kandidaten, wenn es sich bei einer beliebigen Methode in einer abgeleiteten Klasse gilt ( 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).

Nach der möglichen Funktionsmembern und deren Argumentliste identifiziert wurden, ist die Auswahl der am besten geeigneten 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:

  • Die am besten, die den Satz von anwendbaren möglichen Funktionsmembern wird angegeben, Funktion die Member, Satz befindet.Given the set of applicable candidate function members, the best function member in that set is located. Wenn der Satz nur einen Funktionsmember enthält, ist dieser Funktionsmember die am besten geeigneten Funktionsmembers.If the set contains only one function member, then that function member is the best function member. Andernfalls ist die am besten geeigneten Funktionsmembers Funktionsmember, das besser als andere Funktionsmember hinsichtlich der angegebenen Argumentliste, vorausgesetzt, dass jeder Funktionsmember verglichen wird, für alle Mitglieder anderer Funktion mit den Regeln in Geeigneterer Funktionsmember.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, das besser als andere Funktionsmember vorhanden ist, klicken Sie dann der Element-Funktionsaufruf ist mehrdeutig, und beim Auftreten eines Laufzeitfehlers-Bindung.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.

Die folgenden Abschnitte definieren die genauen Bedeutungen der Begriffe anwendbarer Funktionsmember und geeigneterer Funktionsmember.The following sections define the exact meanings of the terms applicable function member and better function member.

Anwendbarer FunktionsmemberApplicable function member

Ein Funktionsmember gilt eine anwendbarer Funktionsmember in Bezug auf eine Argumentliste A wenn Folgendes zutrifft: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 im A entspricht einem Parameter in der Funktionsmemberdeklaration Siehe entsprechende Parameter, und alle Parameter, der kein Argument entspricht, ist ein optionaler Parameter.Each argument in A 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 im A, den Modus des Arguments für die Parameterübergabe (d. h. Wert ref, oder out) ist identisch mit dem Parameter übergebenden Modus des entsprechenden Parameters undFor each argument in A, the parameter passing mode of the argument (i.e., value, ref, or out) is identical to the parameter passing mode of the corresponding parameter, and
    • für eine Value-Parameter oder ein Parameterarray, eine implizite Konvertierung (implizite Konvertierungen) aus dem Argument vorhanden ist, in den Typ des entsprechenden Parameters 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
    • für eine ref oder out Parameter, der der Typ des Arguments ist identisch mit den Typ des entsprechenden Parameters.for a ref or out parameter, the type of the argument is identical to the type of the corresponding parameter. Schließlich eine ref oder out Parameter ist ein Alias für das übergebene Argument.After all, a ref or out parameter is an alias for the argument passed.

Für eine Funktionselement, das ein Parameterarray enthält, wenn der Funktionsmember anhand der obigen Regeln gilt, gilt in angewendet werden. die Normalform.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. Ist ein Funktionselement, das ein Parameterarray enthält nicht anwendbar, in seiner normalen Form, das Funktionselement kann stattdessen fallen in die erweitert Formular: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:

  • Diese erweiterte Form wird erstellt, indem Sie ersetzt das Parameterarray in der Funktionsmemberdeklaration mit 0 (null) oder ein array, z. B. weitere Parameter der Wert des Elementtyps des Parameters, die Anzahl der Argumente in der Argumentliste A entspricht die Summe Anzahl von Parametern.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 list A matches the total number of parameters. Wenn A weniger Argumente als die Anzahl der festen Parameter in der Funktionsmemberdeklaration enthält, ist die erweiterte Form der Funktionsmember der Member kann nicht erstellt werden und ist somit nicht verwendbar.If A 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 diese erweiterte Form anwendbar, wenn Sie für jedes Argument im A den Parameter übergebenden Modus des Arguments ist identisch mit dem Parameter übergebenden Modus des entsprechenden Parameters undOtherwise, the expanded form is applicable if for each argument in A the parameter passing mode of the argument is identical to the parameter passing mode of the corresponding parameter, and
    • für einen festen Wert-Parameter oder eine Value-Parameter, die durch die Erweiterung, die eine implizite Konvertierung erzeugt (implizite Konvertierungen) vorhanden ist aus dem Typ des Arguments in den Typ des entsprechenden Parameters oderfor 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
    • für eine ref oder out Parameter, der der Typ des Arguments ist identisch mit den Typ des entsprechenden Parameters.for a ref or out parameter, the type of the argument is identical to the type of the corresponding parameter.

Geeigneterer FunktionsmemberBetter function member

Im Rahmen den geeignetere Funktionsmember festlegen wird eine reduzierte Argumentliste A erstellt, enthält nur die Argumentausdrücken selbst in der Reihenfolge, die 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.

Parameterlisten für jeden die Candidate-Funktion, die Mitglieder auf folgende Weise erstellt werden:Parameter lists for each of the candidate function members are constructed in the following way:

  • Diese erweiterte Form wird verwendet, wenn das Funktionselement betrifft nur die erweiterte Form wurde.The expanded form is used if the function member was applicable only in the expanded form.
  • Optionale Parameter ohne entsprechenden Argumente werden aus der Liste entfernt.Optional parameters with no corresponding arguments are removed from the parameter list
  • Die Parameter sind neu angeordnet, damit sie an der gleichen 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.

Eine Argumentliste A mit einem Satz von Argumentausdrücken {E1, E2, ..., En} und zwei anwendbaren Funktionsmembern Mp und Mq mit Parametertypen {P1, P2, ..., Pn} und {Q1, Q2, ..., Qn}, Mp definiert eine geeigneterer Funktionsmember als Mq WennGiven 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

  • für jedes Argument, das die implizite Konvertierung von Ex zu Qx ist nicht besser als die implizite Konvertierung von Ex zu Px, undfor each argument, the implicit conversion from Ex to Qx is not better than the implicit conversion from Ex to Px, and
  • für mindestens ein Argument, um die Konvertierung von Ex zu Px ist besser als die Konvertierung von Ex zu Qx.for at least one argument, the conversion from Ex to Px is better than the conversion from Ex to Qx.

Beim Ausführen dieser Evaluierung Wenn Mp oder Mq gilt in der erweiterten Form dann Px oder Qx bezieht sich auf einen Parameter in die erweiterte 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 der Typparameter Sequenzen {P1, P2, ..., Pn} und {Q1, Q2, ..., Qn} äquivalent sind (d. h. jede Pi verfügt über eine identitätskonvertierung in den entsprechenden Qi), die folgenden Regeln für die aktuelle Verbindung angewendet werden, in der Reihenfolge, um zu bestimmen, desto besser Funktionsmember.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 ist eine nicht generische Methode und Mq ist eine generische Methode Mp ist besser als Mq.If Mp is a non-generic method and Mq is a generic method, then Mp is better than Mq.
  • Andernfalls gilt: Wenn Mp gilt in seiner normalen Form und Mq verfügt über eine params array und gilt nur in der erweiterten Form dann Mp ist besser als Mq.Otherwise, if Mp is applicable in its normal form and Mq has a params array and is applicable only in its expanded form, then Mp is better than Mq.
  • Andernfalls gilt: Wenn Mp verfügt über mehrere deklarierte Parameter als Mq, klicken Sie dann Mp ist besser als Mq.Otherwise, if Mp has more declared parameters than Mq, then Mp is better than Mq. Dies kann auftreten, wenn beide Methoden haben params Arrays und sind nur in ihre erweiterte Formate angewendet.This can occur if both methods have params arrays and are applicable only in their expanded forms.
  • Andernfalls Wenn alle Parameter der Mp ein entsprechenden Arguments haben, während die Standardargumente für mindestens ein optionaler Parameter in ersetzt werden müssen Mq dann Mp ist besser als Mq.Otherwise if all parameters of Mp have a corresponding argument whereas default arguments need to be substituted for at least one optional parameter in Mq then Mp is better than Mq.
  • Andernfalls gilt: Wenn Mp hat spezifische Parametertypen als Mq, klicken Sie dann Mp ist besser als Mq.Otherwise, if Mp has more specific parameter types than Mq, then Mp is better than Mq. Lassen Sie {R1, R2, ..., Rn} und {S1, S2, ..., Sn} die nicht instanziierte und nicht erweiterten Parametertypen darstellen Mp und Mq.Let {R1, R2, ..., Rn} and {S1, S2, ..., Sn} represent the uninstantiated and unexpanded parameter types of Mp and Mq. Mpdie Parametertypen sind präziser als Mqdes If, für jeden Parameter Rx ist nicht als weniger spezifischen Sx, und für mindestens ein Parameter Rx sind präziser als Sx:Mp's parameter types are more specific than Mq's if, for each parameter, Rx is not less specific than Sx, and, for at least one parameter, Rx is more specific than Sx:
    • Ein Typparameter ist weniger spezifisch als Nichttyp-Parameter.A type parameter is less specific than a non-type parameter.
    • Rekursiv, bezieht sich ein konstruierter Typ mehr als einen anderen konstruierten Typ (mit derselben Anzahl von Typargumenten), wenn mindestens eine Typargument spezifischere ist und keine 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 einen anderen Arraytyp (mit derselben Anzahl von Dimensionen), wenn der Typ des Elements der ersten spezifischer als der Elementtyp der zweiten ist.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.
  • Andernfalls ist, wenn ein Element ein Operator nicht aufgehoben ist, und die andere ein transformierten Operator ist, die nicht transformiert eine 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 keine Funktionsmember besser.Otherwise, neither function member is better.

Bessere Konvertierung von AusdruckBetter conversion from expression

Erhalten eine implizite Konvertierung C1 , der von einem Ausdruck konvertiert E auf einen Typ T1, und eine implizite Konvertierung C2 , der von einem Ausdruck konvertiert E auf einen Typ T2, C1 ist eine bessere Konvertierung als C2 Wenn E entspricht nicht genau T2 und mindestens eine der folgenden 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:

-Ausdruck genau entsprechen.Exactly matching Expression

Erhält einen Ausdruck E und einen Typ T, E genau Übereinstimmungen T , wenn eine der folgenden enthält:Given an expression E and a type T, E exactly matches T if one of the following holds:

  • E weist einen Typ S, und eine identitätskonvertierung vorhanden ist, von S auf TE has a type S, and an identity conversion exists from S to T
  • E ist eine anonyme Funktion, T ist entweder ein Delegattyp D oder ein Typ für die Ausdrucksbaumstruktur Expression<D> und eine der folgenden enthält:E is an anonymous function, T is either a delegate type D or an expression tree type Expression<D> and one of the following holds:
    • Einem hergeleiteten Rückgabetyp X vorhanden ist, für die E im Rahmen der Liste der Parameter D (abgeleiteter Rückgabetyp), und eine identitätskonvertierung vorhanden ist, von X in den Rückgabetyp der DAn inferred return type X exists for E in the context of the parameter list of D (Inferred return type), and an identity conversion exists from X to the return type of D
    • Entweder E ist nicht asynchronen und D hat einen Rückgabetyp Y oder E ist asynchron und D hat einen Rückgabetyp Task<Y>, und eine der folgenden enthält:Either E is non-async and D has a return type Y or E is async and D has a return type Task<Y>, and one of the following holds:
      • Der Text der E ist ein Ausdruck, die genau übereinstimmt YThe body of E is an expression that exactly matches Y
      • Der Text der E ist ein Anweisungsblock, in dem alle return-Anweisung gibt einen Ausdruck, die genau übereinstimmt zurück, YThe body of E is a statement block where every return statement returns an expression that exactly matches Y

Bessere Konvertierung-ZielBetter conversion target

Erhalten zwei verschiedene Arten T1 und T2, T1 ist eine bessere Konvertierung Ziel als T2 Wenn keine implizite Konvertierung von T2 zu T1 vorhanden ist, und mindestens eine der folgenden 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 zu T2 vorhanden istAn implicit conversion from T1 to T2 exists
  • T1 ist entweder ein Delegattyp D1 oder ein Typ für die Ausdrucksbaumstruktur Expression<D1>, T2 ist entweder ein Delegattyp D2 oder ein Typ für die Ausdrucksbaumstruktur Expression<D2>, D1 hat einen Rückgabetyp S1 und eines der folgenden enthält:T1 is either a delegate type D1 or an expression tree type Expression<D1>, T2 is either a delegate type D2 or an expression tree type Expression<D2>, D1 has a return type S1 and one of the following holds:
    • D2 ist die "void" zurückgebenD2 is void returning
    • D2 hat einen Rückgabetyp S2, und S1 ist eine bessere Konvertierung Ziel als S2D2 has a return type S2, and S1 is a better conversion target than S2
  • T1 ist Task<S1>, T2 ist Task<S2>, und S1 ist eine bessere Konvertierung Ziel als S2T1 is Task<S1>, T2 is Task<S2>, and S1 is a better conversion target than S2
  • T1 ist S1 oder S1? , in denen S1 ist ein ganzzahliger Typ mit Vorzeichen, und T2 ist S2 oder S2? , in denen S2 ein Integraltyp ohne Vorzeichen ist.T1 is S1 or S1? where S1 is a signed integral type, and T2 is S2 or S2? where S2 is an unsigned integral type. Dies gilt insbesondere in folgenden Fällen:Specifically:
    • S1 ist sbyte und S2 ist byte, ushort, uint, oder ulongS1 is sbyte and S2 is byte, ushort, uint, or ulong
    • S1 ist short und S2 ist ushort, uint, oder ulongS1 is short and S2 is ushort, uint, or ulong
    • S1 ist int und S2 ist uint, oder ulongS1 is int and S2 is uint, or ulong
    • S1 ist long und S2 ist ulongS1 is long and S2 is ulong

In der generischen Klassen überladenOverloading in generic classes

Während Signaturen, die gemäß der Deklaration eindeutig und sein müssen ist es möglich, dass die Ersetzung der Argumente des Typs 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 aktuelle Tie Regeln der überladungsauflösung, die oben genannten das spezifischste Element auswählen.In such cases, the tie-breaking rules of overload resolution above will pick the most specific member.

Die folgenden Beispiele zeigen die Überladungen, die gültige und ungültige nach dieser Regel 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);
}

Überprüfungen zur Kompilierzeit der dynamischen überladungsauflösungCompile-time checking of dynamic overload resolution

Für die meisten dynamisch gebundene Vorgänge ist der Satz von möglichen Kandidaten für die Auflösung zum Zeitpunkt der Kompilierung unbekannt.For most dynamically bound operations the set of possible candidates for resolution is unknown at compile-time. In bestimmten Fällen ist jedoch der Satz von Kandidaten zum Zeitpunkt der Kompilierung bekannt:In certain cases, however the candidate set is known at compile-time:

  • Aufrufen statischer Methoden, mit dem dynamische ArgumenteStatic method calls with dynamic arguments
  • Instanz-Methodenaufrufen, in denen der Empfänger keine dynamischen Ausdruck istInstance method calls where the receiver is not a dynamic expression
  • Indexer-Aufrufe, in denen der Empfänger keine dynamischen Ausdruck istIndexer calls where the receiver is not a dynamic expression
  • Ruft der Konstruktor mit dem dynamische ArgumenteConstructor calls with dynamic arguments

In diesen Fällen wird eine begrenzte Überprüfung der während der Kompilierung ausgeführt, bei jedem Kandidaten aus, um festzustellen, ob diese möglicherweise zur Laufzeit anwenden könnten. Diese Überprüfung umfasst die folgenden Schritte aus: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:

  • Partielle Typrückschluss: Jeder Typ Argument, das nicht direkt oder indirekt auf ein Argument vom Typ abhängt dynamic abgeleitet wird, wobei die Regeln der Typrückschluss.Partial type inference: Any type argument that does not depend directly or indirectly on an argument of type dynamic is inferred using the rules of Type inference. Die verbleibenden Typargumente sind unbekannt.The remaining type arguments are unknown.
  • Partielle anwendbarkeitsprüfung: Anwendbarkeit wird überprüft, gemäß Anwendbarer Funktionsmember, aber der Parameter, deren Typen unbekannt sind, werden ignoriert.Partial applicability check: Applicability is checked according to Applicable function member, but ignoring parameters whose types are unknown.
  • Wenn kein Kandidat dieser Test erfolgreich ist, tritt ein Fehler während der Kompilierung.If no candidate passes this test, a compile-time error occurs.

Member-FunktionsaufrufFunction member invocation

Dieser Abschnitt beschreibt den Prozess, der erfolgt zur Laufzeit eine bestimmte Funktionsmember aufgerufen werden soll.This section describes the process that takes place at run-time to invoke a particular function member. Es wird vorausgesetzt, dass ein Bindung-Time-Prozess bereits das bestimmte Element um aufzurufen, möglicherweise durch Anwenden der überladungsauflösung, um einen Satz von möglichen Funktionsmembern festgestellt hat.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.

Rahmen, den Aufrufvorgang beschreiben sind Funktionsmember in zwei Kategorien unterteilt:For purposes of describing the invocation process, function members are divided into two categories:

  • Mitglieder der statische Funktion.Static function members. Dies sind Instanzkonstruktoren, statische Methoden, statische Eigenschaftenaccessoren und benutzerdefinierten 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.
  • Instanzmember-Funktion.Instance function members. Dies sind Instanzmethoden, Instanz-Eigenschaftenaccessoren und Indexeraccessoren.These are instance methods, instance property accessors, and indexer accessors. Instanzmember-Funktion sind entweder nicht virtuell oder virtuell sein, und Sie werden immer in einer bestimmten Instanz aufgerufen.Instance function members are either non-virtual or virtual, and are always invoked on a particular instance. Die Instanz wird berechnet, indem ein Instanzenausdruck, und es wird innerhalb der Funktionsmember der Member als zugegriffen werden this (diesen Zugriff).The instance is computed by an instance expression, and it becomes accessible within the function member as this (This access).

Die laufzeitverarbeitung der einen Funktionsaufruf für das Element besteht aus den folgenden Schritten, in denen M ist das Funktionselement und, falls M ist ein Instanzmember E ist die Instanzausdruck: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 ist eine statische Funktion-Element:If M is a static function member:

    • Die Argumentliste ausgewertet wird, wie in beschrieben Argumentlisten.The argument list is evaluated as described in Argument lists.
    • M wird aufgerufen.M is invoked.
  • Wenn M wird in ein Instanzmember der Funktion deklariert eine Value_type:If M is an instance function member declared in a value_type:

    • E wird ausgewertet.E is evaluated. Wenn diese Evaluierungsversion auf eine Ausnahme auslöst, werden dann keine weiteren Schritte ausgeführt werden.If this evaluation causes an exception, then no further steps are executed.
    • Wenn E wird nicht als eine Variable, und klicken Sie dann auf eine temporäre lokale Variable vom klassifiziert ETyp erstellt wird und der Wert der E diese Variable zugewiesen wird.If E is not classified as a variable, then a temporary local variable of E's type is created and the value of E is assigned to that variable. E als ein Verweis auf diese temporäre lokale Variable wird dann neu klassifiziert werden.E is then reclassified as a reference to that temporary local variable. Die temporäre Variable ist als this in M, aber nicht auf andere Weise.The temporary variable is accessible as this within M, but not in any other way. Daher nur, wenn E ist eine Variable "true" ist es möglich, dass der Aufrufer die Änderungen zu prüfen, M stellt this.Thus, only when E is a true variable is it possible for the caller to observe the changes that M makes to this.
    • Die Argumentliste ausgewertet wird, wie in beschrieben Argumentlisten.The argument list is evaluated as described in Argument lists.
    • M wird aufgerufen.M is invoked. Die Variable verweist E wird die Variable verweist this.The variable referenced by E becomes the variable referenced by this.
  • Wenn M wird in ein Instanzmember der Funktion deklariert eine Reference_type:If M is an instance function member declared in a reference_type:

    • E wird ausgewertet.E is evaluated. Wenn diese Evaluierungsversion auf eine Ausnahme auslöst, werden dann keine weiteren Schritte ausgeführt werden.If this evaluation causes an exception, then no further steps are executed.
    • Die Argumentliste ausgewertet wird, wie in beschrieben Argumentlisten.The argument list is evaluated as described in Argument lists.
    • Wenn der Typ des E ist eine Value_type, einer Boxing-Konvertierung (Boxing-Konvertierung) ausgeführt wird, um konvertieren E eingeben object, und E gilt Der Typ object in den folgenden Schritten.If the type of E is a value_type, a boxing conversion (Boxing conversions) is performed to convert E to type object, and E is considered to be of type object in the following steps. In diesem Fall M möglicherweise nur ein Mitglied System.Object.In this case, M could only be a member of System.Object.
    • Der Wert des E wird überprüft, um gültig sein.The value of E is checked to be valid. Wenn der Wert des E ist null, System.NullReferenceException wird ausgelöst, und keine weiteren Schritte ausgeführt werden.If the value of E is null, a System.NullReferenceException is thrown and no further steps are executed.
    • Die Implementierung des Schnittstellenmembers Funktion aufrufen, wird bestimmt:The function member implementation to invoke is determined:
      • Wenn der Typ der Bindung-Time E ist eine Schnittstelle, der aufzurufenden Funktionsmember ist die Implementierung der M bereitgestellt, die von der Run-Time-Typ der Instanz verweist E.If the binding-time type of E is an interface, the function member to invoke is the implementation of M provided by the run-time type of the instance referenced by E. Diese Funktionsmember richtet sich nach Anwenden der Standardregeln für Schnittstellen-Zuordnung (schnittstellenzuordnung) um zu bestimmen, die Implementierung der M bereitgestellt, die von der Run-Time-Typ der Instanz verweist E.This function member is determined by applying the interface mapping rules (Interface mapping) to determine the implementation of M provided by the run-time type of the instance referenced by E.
      • Andernfalls gilt: Wenn M gehört eine virtuelle Funktion, der aufzurufenden Funktionsmember ist die Implementierung der M bereitgestellt, die von der Run-Time-Typ der Instanz verweist E.Otherwise, if M is a virtual function member, the function member to invoke is the implementation of M provided by the run-time type of the instance referenced by E. Dieser Funktionsmember richtet sich nach Anwenden der Regeln für die Bestimmung der am weitesten abgeleiteten Implementierung (virtuelle Methoden) der M in Bezug auf die Run-Time-Typ der Instanz verweist E.This function member is determined by applying the rules for determining the most derived implementation (Virtual methods) of M with respect to the run-time type of the instance referenced by E.
      • Andernfalls M nicht virtuelle Funktion angehört, und wird von der aufzurufenden Funktionsmember M selbst.Otherwise, M is a non-virtual function member, and the function member to invoke is M itself.
    • Wird aufgerufen, die Implementierung des Schnittstellenmembers Funktion im vorherigen Schritt bestimmt.The function member implementation determined in the step above is invoked. Das Objekt, das auf E wird das Objekt, das auf this.The object referenced by E becomes the object referenced by this.

Aufrufe in geschachtelten InstanzenInvocations on boxed instances

Ein Funktionsmember implementiert eine Value_type kann über eine geschachtelte Instanz, die aufgerufen werden Value_type in den folgenden Situationen:A function member implemented in a value_type can be invoked through a boxed instance of that value_type in the following situations:

  • Wenn der Funktionsmember der Member ist ein override einer Methode geerbt von Typ object und wird durch einen Instanzausdruck des Typs aufgerufen object.When the function member is an override of a method inherited from type object and is invoked through an instance expression of type object.
  • Wenn der Funktionsmember der Member ist eine Implementierung eines Schnittstellenmembers-Funktion und wird aufgerufen, durch einen Instanzausdruck, der eine Interface_type.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 der Member über einen Delegaten aufgerufen wird.When the function member is invoked through a delegate.

In diesen Fällen gilt eine Variable enthält die geschachtelte Instanz die Value_type, und diese Variable wird die Variable verweist this innerhalb von der Members-Funktionsaufruf.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. Insbesondere bedeutet dies, dass wenn ein Funktionsmember für eine geschachtelte Instanz aufgerufen wird, für den Funktionsmember "zum Ändern des Werts in die geschachtelte Instanz enthalten 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ärausdrücke umfassen 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
    ;

Ausdrücke (primär) aufgeteilt sind Array_creation_expressions und Primary_no_array_creation_expressions.Primary expressions are divided between array_creation_expressions and primary_no_array_creation_expressions. Zum Behandeln von Arrayerstellungsausdruck – auf diese Weise, anstatt sie zusammen mit anderen einfachen Ausdruck Formulare auflisten ermöglicht es, die die Grammatik, die möglicherweise irreführende Code wie z. B. zu unterbindenTreating 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];

die andernfalls als interpretiert werden sollenwhich would otherwise be interpreted as

object o = (new int[3])[1];

LiteraleLiterals

Ein Primary_expression besteht aus einem literal (Literale) als Wert klassifiziert wird.A primary_expression that consists of a literal (Literals) is classified as a value.

Interpolierte ZeichenfolgenInterpolated strings

Ein Interpolated_string_expression besteht aus einem $ anmelden, gefolgt von einer regulären oder wörtliche Zeichenfolge, die Literale, bei dem Löcher, getrennt durch { und }, setzen Sie Ausdrücke und Formatierung Spezifikationen.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 Ausdruck eine interpolierte Zeichenfolge ist das Ergebnis einer Interpolated_string_literal , hat wurde unterteilt in einzelne Token, wie in beschrieben interpolierte Zeichenfolgenliterale.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)+
    ;

Die Constant_expression eine Interpolation benötigen eine implizite Konvertierung in 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 konvertiert wird System.IFormattable oder System.FormattableString mit eine implizite interpolierte Zeichenfolge-Konvertierung (implizite interpolierte zeichenfolgenkonvertierungen), des interpolierten Zeichenfolgenausdrucks Typ verfügt.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 ist es den Typ string.Otherwise, it has the type string.

Wenn der Typ einer interpolierten Zeichenfolge System.IFormattable oder System.FormattableString, die Bedeutung ist, einen Aufruf von 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, die Bedeutung des Ausdrucks ist ein Aufruf string.Format.If the type is string, the meaning of the expression is a call to string.Format. In beiden Fällen besteht aus die Argumentliste des Aufrufs ein Formatzeichenfolgenliteral mit Platzhalter für jede Interpolation, und ein Argument für die einzelnen Ausdrücke, die Platzhalter 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.

Das Formatzeichenfolgenliteral wie folgt erstellt wird, in denen N ist die Anzahl von Interpolationen in die Interpolated_string_expression: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 Interpolated_verbatim_string_whole folgt die $ anmelden, und klicken Sie dann das Format-Zeichenfolgenliteral, das Token ist.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 aus den Formatzeichenfolgenliteral:Otherwise, the format string literal consists of:
    • Erste die Interpolated_regular_string_start oder Interpolated_verbatim_string_startFirst the interpolated_regular_string_start or interpolated_verbatim_string_start
    • Klicken Sie dann für jede Zahl I aus 0 zu N-1:Then for each number I from 0 to N-1:
      • Die dezimale Darstellung IThe decimal representation of I
      • Wenn danach der entsprechenden Interpolation verfügt über eine Constant_expression, , (Komma) gefolgt von der dezimale Darstellung des Werts der Constant_expressionThen, if the corresponding interpolation has a constant_expression, a , (comma) followed by the decimal representation of the value of the constant_expression
      • Die Interpolated_regular_string_mid, Interpolated_regular_string_end, Interpolated_verbatim_string_mid oder Interpolated_ Verbatim_string_end unmittelbar nach der entsprechenden Interpolation.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 nachfolgende Argumente werden einfach die Ausdrücke aus der Interpolationen (sofern vorhanden), in der Reihenfolge.The subsequent arguments are simply the expressions from the interpolations (if any), in order.

TODO: Beispiele.TODO: examples.

Einfache NamenSimple names

Ein Simple_name eines Bezeichners steht, optional gefolgt von einer Liste der Typargumente besteht aus:A simple_name consists of an identifier, optionally followed by a type argument list:

simple_name
    : identifier type_argument_list?
    ;

Ein Simple_name ist entweder der Form I oder des Formulars I<A1,...,Ak>, wobei I ist eine einmalige Kennung und <A1,...,Ak> ist eine optionale Type_argument_list.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 kein Type_argument_list wird angegeben, sollten Sie K 0 (null).When no type_argument_list is specified, consider K to be zero. Die Simple_name ausgewertet und wie folgt klassifiziert:The simple_name is evaluated and classified as follows:

  • Wenn K ist 0 (null) und die Simple_name Teil einer Block und, wenn die Blockdes (oder einer einschließenden Blockdes) lokalen Variablendeklaration-Speicherplatz (Deklarationen) enthält lokale Variablen, Parameter oder Konstante mit dem Namen I, und klicken Sie dann die Simple_name bezieht sich auf dieser lokalen Variablen verwenden, Parameter oder Konstanten und wird als eine Variable oder einem Wert klassifiziert.If K 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 name I, then the simple_name refers to that local variable, parameter or constant and is classified as a variable or value.

  • Wenn K ist 0 (null) und die Simple_name erscheint im Text der Deklaration einer generischen Methode und wenn dieser Deklaration einen Typparameter mit dem Namen enthält I, und klicken Sie dann die Simple_namebezieht sich auf den Typparameter.If K is zero and the simple_name appears within the body of a generic method declaration and if that declaration includes a type parameter with name I, then the simple_name refers to that type parameter.

  • Für jeden Instanztyp andernfalls T (den Instanztyp), beginnend mit dem Instanztyp der Deklaration des unmittelbar einschließenden und mit dem Instanztyp jeden einschließenden Klasse oder Struktur Deklaration (sofern vorhanden):Otherwise, for each instance type T (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 ist 0 (null) und die Deklaration von T enthält einen Typparameter mit dem Namen I, und klicken Sie dann die Simple_name bezieht sich auf den Typparameter.If K is zero and the declaration of T includes a type parameter with name I, then the simple_name refers to that type parameter.
    • Andernfalls, wenn eine Suche nach Membern (Membersuche) der I in T mit K  Typargumente eine Übereinstimmung ergibt:Otherwise, if a member lookup (Member lookup) of I in T with K type arguments produces a match:
      • Wenn T ist die Instanztyp des unmittelbar umschließende Klasse oder Struktur und die Suche nach identifiziert einen oder mehrere Methoden, die das Ergebnis ist eine Methodengruppe mit einem zugeordneten Instanzausdruck von this.If T 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 of this. Wenn eine Liste der Typargumente angegeben wurde, wird es verwendet eine generische Methode aufzurufen (Methodenaufrufe).If a type argument list was specified, it is used in calling a generic method (Method invocations).
      • Andernfalls gilt: Wenn T der Instanztyp der unmittelbar umschließende Klasse oder Struktur-Typ ist, wenn die Suche auf einen Instanzmember identifiziert und der Verweis innerhalb eines Texts der Instanzkonstruktor, eine Instanzmethode oder einem Instanzaccessor auftritt, die Ergebnis ist identisch mit Memberzugriff (Memberzugriff) des Formulars this.I.Otherwise, if T 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 form this.I. Dies kann nur, wenn K ist 0 (null).This can only happen when K is zero.
      • Andernfalls das Ergebnis ist identisch mit Memberzugriff (Memberzugriff) des Formulars T.I oder T.I<A1,...,Ak>.Otherwise, the result is the same as a member access (Member access) of the form T.I or T.I<A1,...,Ak>. In diesem Fall es ist ein Fehler während der Bindung für die Simple_name zum Verweisen auf ein Instanzmember.In this case, it is a binding-time error for the simple_name to refer to an instance member.
  • Für jeden Namespace, andernfalls N, beginnend mit dem Namespace, in dem die Simple_name wird mit jeder einschließenden Namespace (sofern vorhanden) und bis hin zu den globalen Namespace, weiterhin werden die folgenden Schritte aus ausgewertet, bis eine Entität befindet:Otherwise, for each namespace N, 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 ist 0 (null) und I ist der Name eines Namespace im N, klicken Sie dann:If K is zero and I is the name of a namespace in N, then:
      • Wenn der Speicherort, in dem die Simple_name tritt auf, steht eine Namespace-Deklaration für N und die Namespacedeklaration enthält eine Extern_alias_directive oder Using_alias_directive , die den Namen zuordnet I mit einem Namespace oder Typ, der Simple_name ist mehrdeutig und ein Fehler während der Kompilierung auftritt.If the location where the simple_name occurs is enclosed by a namespace declaration for N and the namespace declaration contains an extern_alias_directive or using_alias_directive that associates the name I with a namespace or type, then the simple_name is ambiguous and a compile-time error occurs.
      • Andernfalls die Simple_name verweist auf den Namespace mit dem Namen I in N.Otherwise, the simple_name refers to the namespace named I in N.
    • Andernfalls gilt: Wenn N enthält einen zugreifbarer Typ, der mit Namen I und K  Typparameter, klicken Sie dann:Otherwise, if N contains an accessible type having name I and K type parameters, then:
      • Wenn K ist 0 (null) und den Speicherort, in denen die Simple_name tritt auf, wird durch eine Namespacedeklaration zur eingeschlossen N und die Namespacedeklaration enthält eine Extern_alias_directiveoder Using_alias_directive , die den Namen zuordnet I mit einem Namespace oder Typ, der Simple_name ist mehrdeutig und ein Fehler während der Kompilierung auftritt.If K is zero and the location where the simple_name occurs is enclosed by a namespace declaration for N and the namespace declaration contains an extern_alias_directive or using_alias_directive that associates the name I with a namespace or type, then the simple_name is ambiguous and a compile-time error occurs.
      • Andernfalls die Namespace_or_type_name verweist auf den Typ mit den Argumenten angegebenen Typs erstellt.Otherwise, the namespace_or_type_name refers to the type constructed with the given type arguments.
    • Andernfalls gilt: Wenn der Speicherort, in dem die Simple_name tritt auf, wird durch eine Namespacedeklaration zur eingeschlossen N:Otherwise, if the location where the simple_name occurs is enclosed by a namespace declaration for N:
      • Wenn K ist 0 (null) und die Namespacedeklaration enthält eine Extern_alias_directive oder Using_alias_directive , die den Namen verknüpft I mit einem importierten Namespace oder Der Typ, und klicken Sie dann die Simple_name bezieht sich auf diesen Namespace oder Typ.If K is zero and the namespace declaration contains an extern_alias_directive or using_alias_directive that associates the name I with an imported namespace or type, then the simple_name refers to that namespace or type.
      • Andernfalls, wenn die Deklarationen für Namespaces und importiert die Using_namespace_directives und Using_static_directives der Namespacedeklaration enthalten genau ein zugreifbarer Typ oder ohne Erweiterung statischen Member mit Namen I und K  Typparameter, und klicken Sie dann die Simple_name bezieht sich auf den Typ oder Member, die mit den Argumenten angegebenen Typs erstellt.Otherwise, if the namespaces and type declarations imported by the using_namespace_directives and using_static_directives of the namespace declaration contain exactly one accessible type or non-extension static member having name I and K type parameters, then the simple_name refers to that type or member constructed with the given type arguments.
      • Andernfalls, wenn die Namespaces und Typen von importiert die Using_namespace_directives der Namespacedeklaration enthalten mehr als ein zugreifbarer Typ oder nicht-Erweiterungsmethode statischen Member mit Namen I und K  Typparameter, und klicken Sie dann die Simple_name ist mehrdeutig und ein Fehler auftritt.Otherwise, if the namespaces and types imported by the using_namespace_directives of the namespace declaration contain more than one accessible type or non-extension-method static member having name I and K type parameters, then the simple_name is ambiguous and an error occurs.

    Beachten Sie, dass dieser gesamte Schritt genau mit dem entsprechenden Schritt bei der Verarbeitung von parallelen ist eine Namespace_or_type_name (Namespace und Typnamen).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).

  • Andernfalls die Simple_name ist nicht definiert und ein Fehler während der Kompilierung auftritt.Otherwise, the simple_name is undefined and a compile-time error occurs.

Ausdrücke in KlammernParenthesized expressions

Ein Parenthesized_expression besteht aus einem Ausdruck in Klammern eingeschlossen.A parenthesized_expression consists of an expression enclosed in parentheses.

parenthesized_expression
    : '(' expression ')'
    ;

Ein Parenthesized_expression wird ausgewertet, durch die Auswertung der Ausdruck innerhalb der Klammern.A parenthesized_expression is evaluated by evaluating the expression within the parentheses. Wenn die Ausdruck innerhalb der Klammern gibt an einen Namespace oder Typ, ein Fehler während der Kompilierung auftritt.If the expression within the parentheses denotes a namespace or type, a compile-time error occurs. Andernfalls das Ergebnis der Parenthesized_expression ist das Ergebnis der Auswertung der enthaltenen Ausdruck.Otherwise, the result of the parenthesized_expression is the result of the evaluation of the contained expression.

MemberzugriffMember access

Ein Member_access besteht aus einem Primary_expression, Predefined_type, oder ein 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 definiert, Namespace Alias Qualifiers.The qualified_alias_member production is defined in Namespace alias qualifiers.

Ein Member_access ist entweder der Form E.I oder des Formulars E.I<A1, ..., Ak>, wobei E ist ein primärer Ausdruck, I ist eine einmalige Kennung und <A1, ..., Ak> ist eine optionale Type_argument_list.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 kein Type_argument_list wird angegeben, sollten Sie K 0 (null).When no type_argument_list is specified, consider K to be zero.

Ein Member_access mit einem Primary_expression des Typs dynamic dynamisch gebunden ist (dynamische Bindung).A member_access with a primary_expression of type dynamic is dynamically bound (Dynamic binding). In diesem Fall der Compiler den Memberzugriff als Eigenschaftszugriff vom Typ klassifiziert dynamic.In this case the compiler classifies the member access as a property access of type dynamic. Den Regeln unten, um zu bestimmen, die Bedeutung von der Member_access gelten dann zur Laufzeit, der Kompilierzeittyp von der Laufzeit-Typinformationen anstelle 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 Klassifizierung Laufzeit zu einer Methodengruppe führt, und klicken Sie dann der Memberzugriff muss die Primary_expression von einer Invocation_expression.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 ausgewertet und wie folgt klassifiziert:The member_access is evaluated and classified as follows:

  • Wenn K ist 0 (null) und E ist ein Namespace und E enthält einen geschachtelten Namespace mit dem Namen I, lautet das Ergebnis dieses Namespace.If K is zero and E is a namespace and E contains a nested namespace with name I, then the result is that namespace.
  • Andernfalls gilt: Wenn E ist ein Namespace und E enthält einen zugreifbarer Typ, der mit Namen I und K  Typparameter, und klicken Sie dann das Ergebnis dieses Typs mit den Argumenten angegebenen Typs erstellt wird.Otherwise, if E is a namespace and E contains an accessible type having name I and K type parameters, then the result is that type constructed with the given type arguments.
  • Wenn E ist eine Predefined_type oder Primary_expression als Typ klassifiziert werden, wenn E ist es sich nicht um ein Typparameter, und wenn eine Suche nach Membern (Membersuche) der I in E mit K  Typparameter erzeugt eine Übereinstimmung, E.I ausgewertet und wie folgt klassifiziert:If E is a predefined_type or a primary_expression classified as a type, if E is not a type parameter, and if a member lookup (Member lookup) of I in E with K type parameters produces a match, then E.I is evaluated and classified as follows:
    • Wenn I identifiziert einen Typ, lautet das Ergebnis dieses Typs mit den Argumenten angegebenen Typs erstellt.If I identifies a type, then the result is that type constructed with the given type arguments.
    • Wenn I eine oder mehrere Methoden, identifiziert, und klicken Sie dann das Ergebnis einer Methodengruppe ohne zugeordneten Instanzausdruck ist.If I identifies one or more methods, then the result is a method group with no associated instance expression. Wenn eine Liste der Typargumente angegeben wurde, wird es verwendet eine generische Methode aufzurufen (Methodenaufrufe).If a type argument list was specified, it is used in calling a generic method (Method invocations).
    • Wenn I identifiziert eine static -Eigenschaft, und klicken Sie dann auf das Ergebnis ist ein Eigenschaftenzugriff ohne zugeordneten Instanzausdruck.If I identifies a static property, then the result is a property access with no associated instance expression.
    • Wenn I identifiziert eine static Feld:If I identifies a static field:
      • Wenn das Feld readonly der Verweis findet im statischen Konstruktor der Klasse oder Struktur, die in der das Feld deklariert wird, und das Ergebnis ist ein Wert, d. h. der Wert des statischen Felds I in E.If the field is readonly 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 field I in E.
      • Andernfalls ist das Ergebnis einer Variablen, d. h. das statische Feld I in E.Otherwise, the result is a variable, namely the static field I in E.
    • Wenn I identifiziert eine static Ereignis:If I identifies a static event:
      • Im Falle der Verweis innerhalb der Klasse oder Struktur, die in der das Ereignis deklariert ist, und das Ereignis deklariert wurde, ohne Event_accessor_declarations (Ereignisse), klicken Sie dann E.I genau verarbeitet wird als ob I wurden von ein statischen 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), then E.I is processed exactly as if I were a static field.
      • Andernfalls ist das Ergebnis ein Ereigniszugriff ohne zugeordneten Instanzausdruck.Otherwise, the result is an event access with no associated instance expression.
    • Wenn I eine Konstante ist, identifiziert, und klicken Sie dann das Ergebnis ein Wert, nämlich den Wert dieser Konstanten ist.If I identifies a constant, then the result is a value, namely the value of that constant.
    • Wenn I einen Enumerationsmember identifiziert, und klicken Sie dann das Ergebnis ein Wert, nämlich der Wert dieses Elements der Enumeration ist.If I identifies an enumeration member, then the result is a value, namely the value of that enumeration member.
    • Andernfalls E.I ist ein ungültiger Memberverweis, und ein Fehler während der Kompilierung auftritt.Otherwise, E.I is an invalid member reference, and a compile-time error occurs.
  • Wenn E ist ein Zugriff auf Eigenschaften, Indexerzugriff, Variable oder -Wert, dessen Typ von T, und eine Suche nach Membern (Membersuche) der I in T mit K  Typargumente erzeugt eine Übereinstimmung, E.I ausgewertet und wie folgt klassifiziert:If E is a property access, indexer access, variable, or value, the type of which is T, and a member lookup (Member lookup) of I in T with K type arguments produces a match, then E.I is evaluated and classified as follows:
    • Wenn zunächst E ist eine Eigenschaft oder Indexerzugriff, und klicken Sie dann den Wert der Eigenschaft oder Indexerzugriff abgerufen (Werte Ausdrücke) und E ist, die als Wert neu klassifiziert.First, if E is a property or indexer access, then the value of the property or indexer access is obtained (Values of expressions) and E is reclassified as a value.
    • Wenn I eine oder mehrere Methoden, identifiziert, ist das Ergebnis einer Methodengruppe mit einem zugeordneten Instanzausdruck von E.If I identifies one or more methods, then the result is a method group with an associated instance expression of E. Wenn eine Liste der Typargumente angegeben wurde, wird es verwendet eine generische Methode aufzurufen (Methodenaufrufe).If a type argument list was specified, it is used in calling a generic method (Method invocations).
    • Wenn I identifiziert eine Instance-EigenschaftIf I identifies an instance property,
      • Wenn E ist this, I identifiziert eine automatisch implementierte Eigenschaft (automatisch implementierten Eigenschaften) ohne einen Setter und der Verweis erfolgt innerhalb eines Instanzkonstruktors für einen Klassen-oder Strukturtyp T, lautet das Ergebnis einer Variablen, d. h. das ausgeblendete Unterstützungsfeld für den Auto-Eigenschaft vom I in der Instanz von T von bestimmten this.If E is this, 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 type T, then the result is a variable, namely the hidden backing field for the auto-property given by I in the instance of T given by this.
      • Andernfalls ist das Ergebnis ein Eigenschaftszugriff mit einem zugeordneten Instanzausdruck von E.Otherwise, the result is a property access with an associated instance expression of E.
    • Wenn T ist eine Class_type und I identifiziert ein Instanzenfeld, Class_type:If T is a class_type and I identifies an instance field of that class_type:
      • Wenn der Wert des E ist null, ein System.NullReferenceException ausgelöst.If the value of E is null, then a System.NullReferenceException is thrown.
      • Wenn das Feld ist, andernfalls readonly der Verweis findet keinen Instanzenkonstruktor der Klasse in der das Feld deklariert wird, und das Ergebnis ist ein Wert, nämlich der Wert des Felds I in das Objekt, das auf E.Otherwise, if the field is readonly 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 field I in the object referenced by E.
      • Andernfalls ist das Ergebnis einer Variablen, d. h. das Feld I in das Objekt, das auf E.Otherwise, the result is a variable, namely the field I in the object referenced by E.
    • Wenn T ist eine Struct_type und I identifiziert ein Instanzenfeld, Struct_type:If T is a struct_type and I identifies an instance field of that struct_type:
      • Wenn E ist ein Wert, oder wenn das Feld readonly der Verweis findet keinen Instanzenkonstruktor der Struktur in der das Feld deklariert wird, und das Ergebnis ist ein Wert, nämlich der Wert des Felds I in der Strukturinstanz, die vom  E.If E is a value, or if the field is readonly 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 field I in the struct instance given by E.
      • Andernfalls ist das Ergebnis einer Variablen, d. h. das Feld I in der Strukturinstanz, die vom E.Otherwise, the result is a variable, namely the field I in the struct instance given by E.
    • Wenn I bezeichnet ein Instanzereignis:If I identifies an instance event:
      • Im Falle der Verweis innerhalb der Klasse oder Struktur, die in der das Ereignis deklariert ist, und das Ereignis deklariert wurde, ohne Event_accessor_declarations (Ereignisse), und der Verweis findet nicht statt, als die linke Seite des eine += oder -= Operator an, klicken Sie dann E.I verarbeitet wird, genau wie I wurde 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, then E.I is processed exactly as if I was an instance field.
      • Das Ergebnis ist, andernfalls ein Ereigniszugriff mit einem zugeordneten Instanzausdruck von E.Otherwise, the result is an event access with an associated instance expression of E.
  • Es wird versucht, andernfalls verarbeitet E.I als ein Aufruf der Erweiterungsmethode (Erweiterung Methodenaufrufe).Otherwise, an attempt is made to process E.I as an extension method invocation (Extension method invocations). Wenn dies fehlschlägt, E.I ist ein ungültiger Memberverweis, und beim Auftreten eines Laufzeitfehlers-Bindung.If this fails, E.I is an invalid member reference, and a binding-time error occurs.

Identische einfache Namen und TypIdentical simple names and type names

In ein Memberzugriff des Formulars E.I, wenn E ist ein einzelner Bezeichner, und wenn die Bedeutung der E als eine Simple_name (einfache Namen) ist eine Konstante, Feld, Eigenschaft lokale Variable oder Parameter mit den gleichen Typ wie die Bedeutung der E als eine Type_name (Namespace und Typnamen), und klicken Sie dann beide Bedeutungen von E sind 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 zwei möglichen Bedeutungen der E.I sind nie mehrdeutig, da I muss unbedingt ein Member des Typs E in beiden Fällen.The two possible meanings of E.I are never ambiguous, since I must necessarily be a member of the type E in both cases. Das heißt, die Regel einfach ermöglicht Zugriff auf die statische Member und geschachtelte Typen von E , in denen ein Fehler während der Kompilierung würde andernfalls aufgetreten.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. Zum 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 Produktionen für Simple_name (einfache Namen) und Member_access (Memberzugriff) erhalten, allerdings haben Mehrdeutigkeiten in Anstieg der Grammatik für Ausdrücke.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));

interpretiert werden konnte, wie ein Aufruf von F mit zwei Argumenten G < A und B > (7).could be interpreted as a call to F with two arguments, G < A and B > (7). Alternativ dazu, wie ein Aufruf von interpretiert werden konnte F mit einem Argument, das einen Aufruf einer generischen Methode ist G mit zwei Typargumente und eine reguläre Argument.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 Folge von Token (in Kontext) kann als analysiert werden eine Simple_name (einfache Namen), Member_access (Memberzugriff), oder Pointer_member_access (Zeigermemberzugriff) endet mit einem Type_argument_list (Typargumente), wird die Token, die direkt nach dem schließenden > Token wird 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 einer derIf it is one of

(  )  ]  }  :  ;  ,  .  ?  ==  !=  |  ^

die Type_argument_list wird beibehalten, als Teil der Simple_name, Member_access oder Pointer_member_access sowie 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 die Type_argument_list ist nicht als Teil der Simple_name, Member_access oder Pointer_member_access, auch wenn es keine andere mögliche Analyse der Sequenz von Token.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 nicht angewendet, bei der Analyse einer Type_argument_list in einem Namespace_or_type_name (Namespace und Typnamen).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 nach dieser Regel interpretiert werden als Aufruf an F mit einem Argument, das einen Aufruf einer generischen Methode ist G mit zwei Typargumente und eine reguläre-Argument.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);

Jede interpretiert als Aufruf an F mit zwei Argumenten.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, der größer als-Operator, und unäre plus -Operator, interpretiert werden, als wäre die Anweisung geschrieben worden x = (F < A) > (+y), anstatt als eine Simple_name mit einer 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> interpretiert werden eine Namespace_or_type_name mit einem Type_argument_list.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 dynamisch gebunden ist (dynamische Bindung), wenn mindestens eine der folgenden enthält:An invocation_expression is dynamically bound (Dynamic binding) if at least one of the following holds:

  • Die Primary_expression weist den Typ der Kompilierzeit dynamic.The primary_expression has compile-time type dynamic.
  • Mindestens ein Argument des optionalen Argument_list weist den Typ der Kompilierzeit dynamic und Primary_expression verfügt nicht über einen Delegattyp aufweisen.At least one argument of the optional argument_list has compile-time type dynamic and the primary_expression does not have a delegate type.

In diesem Fall der Compiler klassifiziert die Invocation_expression als ein Wert vom Typ dynamic.In this case the compiler classifies the invocation_expression as a value of type dynamic. Den Regeln unten, um zu bestimmen, die Bedeutung des das Invocation_expression gelten dann zur Laufzeit, der Kompilierzeittyp, der von der Laufzeit-Typinformationen anstelle der Primary_expression und Argumente, die den Zeitpunkt der Kompilierung Typ 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 die Primary_expression hat keinen Kompilierzeittyp dynamic, und klicken Sie dann der Methodenaufruf eine begrenzte Kompilierung Zeit Überprüfung durchgeführt wird, wie in beschrieben Überprüfungen zur Kompilierzeit der dynamischen überladungsauflösung .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.

Die Primary_expression von einer Invocation_expression einer Methodengruppe oder der Wert muss eine Delegate_type.The primary_expression of an invocation_expression must be a method group or a value of a delegate_type. Wenn die Primary_expression eine Methodengruppe wird die Invocation_expression ist der Aufruf einer Methode (Methodenaufrufe).If the primary_expression is a method group, the invocation_expression is a method invocation (Method invocations). Wenn die Primary_expression ist ein Wert, der eine Delegate_type, Invocation_expression einem Delegataufruf aufgerufen wird (AufrufeDelegieren).If the primary_expression is a value of a delegate_type, the invocation_expression is a delegate invocation (Delegate invocations). Wenn die Primary_expression ist weder eine Methodengruppe noch den Wert einer Delegate_type, tritt ein Fehler während der Bindung.If the primary_expression is neither a method group nor a value of a delegate_type, a binding-time error occurs.

Der optionale Argument_list (Argumentlisten) Werte oder Variablenverweise für die Parameter der Methode enthält.The optional argument_list (Argument lists) provides values or variable references for the parameters of the method.

Das Ergebnis der Auswertung einer Invocation_expression wird wie folgt klassifiziert:The result of evaluating an invocation_expression is classified as follows:

  • Wenn die Invocation_expression Ruft eine Methode oder ein Delegat, der gibt void, das Ergebnis ist "nothing".If the invocation_expression invokes a method or delegate that returns void, the result is nothing. Ein Ausdruck, der Klassifizierung als "nothing" nur im Kontext zulässig ist eine Statement_expression (ausdrucksanweisungen) oder als Text einer Lambda_expression(Anonyme Funktionsausdrücke).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 Fehler während der Bindung auf.Otherwise a binding-time error occurs.
  • Andernfalls ist das Ergebnis den Wert der von der Methode oder Delegat zurückgegebene Typ.Otherwise, the result is a value of the type returned by the method or delegate.

MethodenaufrufeMethod invocations

Für den Aufruf einer Methode die Primary_expression von der Invocation_expression muss eine Methodengruppe sein.For a method invocation, the primary_expression of the invocation_expression must be a method group. Die Methodengruppe identifiziert, die eine aufzurufende Methode oder den Satz von überladenen Methoden zur Auswahl einer bestimmten Methode aufrufen.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 Bestimmung der bestimmten Methode aufzurufende wird auf Grundlage des Kontexts bereitgestellt, die von den Typen der Argumente in der Argument_list.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 Bindung-Time-Verarbeitung eines Methodenaufrufs des Formulars M(A), wobei M ist eine Methodengruppe (möglicherweise auch eine Type_argument_list), und A ist eine optionale Argument_ Liste, umfasst die folgenden Schritte aus: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 Methodengruppe zugeordneten M:For each method F associated with the method group M:
    • Wenn F ist nicht generisch, F ist ein Kandidat bei:If F is non-generic, F is a candidate when:
    • Wenn F ist generisch und M verfügt über keine Liste der Typargumente, F ist ein Kandidat bei:If F is generic and M has no type argument list, F is a candidate when:
      • Typrückschluss (Typrückschluss) erfolgreich ist, wird eine Liste der Typargumente für den Aufruf ableiten undType inference (Type inference) succeeds, inferring a list of type arguments for the call, and
      • Sobald die abgeleiteten Typargumente für die entsprechende Methode Typparameter ersetzt werden, erfüllen alle konstruierte Typen in der Parameterliste von F deren Einschränkungen (Einschränkungen erfüllen), und der Parameterliste der F gilt in Bezug auf A (Anwendbarer Funktionsmember).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 of F is applicable with respect to A (Applicable function member).
    • Wenn F ist generisch und M enthält eine Liste der Typargumente, F ist ein Kandidat bei:If F is generic and M includes a type argument list, F is a candidate when:
      • F die gleiche Anzahl von Methodentypparametern aufweist, wie in der Liste der Typargumente, bereitgestellt wurden undF has the same number of method type parameters as were supplied in the type argument list, and
      • Sobald die Typargumente für die entsprechende Methode Typparameter ersetzt werden, erfüllen alle konstruierte Typen in der Parameterliste von F deren Einschränkungen (Einschränkungen erfüllen), und der Liste der Parameter F gilt in Bezug auf A (Anwendbarer Funktionsmember).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 of F is applicable with respect to A (Applicable function member).
  • Die Gruppe der möglichen Methoden werden reduziert, um nur die Methoden aus den am stärksten abgeleiteten Typen enthalten: Für jede Methode C.F in der Gruppe, in denen C ist der Typ, in dem die Methode F deklariert ist, werden alle Methoden deklariert werden, in dem Basistyp C aus der Gruppe entfernt werden.The set of candidate methods is reduced to contain only methods from the most derived types: For each method C.F in the set, where C is the type in which the method F is declared, all methods declared in a base type of C are removed from the set. Darüber hinaus Wenn C ist ein Klassentyp außer object, alle Methoden, die in einen Schnittstellentyp deklariert werden aus der Gruppe entfernt.Furthermore, if C is a class type other than object, all methods declared in an interface type are removed from the set. (Diese zweite Regel hat nur Auswirkungen, wenn die Methodengruppe das Ergebnis einer Suche nach Membern für einen Typparameter mit einer effektiven Klasse als Objekt und eine effektive nicht leere-Schnittstelle festgelegt ist.)(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 die resultierende Menge der möglichen Methoden leer ist, klicken Sie dann auf die folgenden Schritte aus weiteren Verarbeitung abgebrochen werden, und stattdessen wird versucht, den Aufruf als ein Aufruf der Erweiterungsmethode verarbeiten (Erweiterung Methodenaufrufe).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, klicken Sie dann keine anwendbaren Methoden vorhanden, und beim Auftreten eines Laufzeitfehlers-Bindung.If this fails, then no applicable methods exist, and a binding-time error occurs.
  • Die beste Methode, der den Satz von möglichen Methoden wird mit den Regeln der überladungsauflösung des identifiziert Überladungsauflösung.The best method of the set of candidate methods is identified using the overload resolution rules of Overload resolution. Wenn eine einzelne bewährten Methode kann nicht identifiziert werden, der Methodenaufruf ist mehrdeutig, und beim Auftreten eines Laufzeitfehlers-Bindung.If a single best method cannot be identified, the method invocation is ambiguous, and a binding-time error occurs. Bei der Auflösung von funktionsüberladungen durchführen zu können, die Parameter einer generischen Methode gelten nach und Ersetzen Sie dabei die Typargumente (angegeben oder abgeleitet) für die entsprechenden Typparameter der Methode.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.
  • Abschließende Überprüfung von der gewählten bewährte Methode wird ausgeführt:Final validation of the chosen best method is performed:
    • Die Methode wird im Rahmen der Methodengruppe überprüft: Wenn die beste Methode, eine statische Methode handelt, muss die Methodengruppe zurückzuführen sein, aus einer Simple_name oder ein Member_access über einen Typ.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 Methodengruppe zurückzuführen sein, aus einer Simple_name, eine Member_access durch eine Variable oder ein Wert, oder ein Base_access.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 auf "true" ist, tritt ein Fehler während der Bindung.If neither of these requirements is true, a binding-time error occurs.
    • Wenn die bewährte Methode eine generische Methode ist, werden die Typargumente (angegeben oder abgeleitet) für die Einschränkungen überprüft (Einschränkungen erfüllen) für die generische Methode deklariert.If 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 jedes Typargument der entsprechenden Einschränkung(en): für den Typparameter nicht erfüllt, tritt ein Fehler während der Bindung.If any type argument does not satisfy the corresponding constraint(s) on the type parameter, a binding-time error occurs.

Sobald eine Methode ausgewählt und zum Zeitpunkt der Bindung durch die oben genannten Schritte überprüft wurde, wird der tatsächlichen Laufzeit-Aufruf verarbeitet, gemäß den Regeln von der Members-Funktionsaufruf in beschrieben Überprüfungen zur Kompilierzeit der dynamischen überladungsauflösung .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 Auswirkung der oben beschriebenen Regeln intuitivere lautet wie folgt aus: Zum Suchen von bestimmten Methode durch Aufruf einer Methode aufgerufen, beginnen Sie mit der durch Aufruf der Methode angegebenen Typ und entlang der Vererbungskette fortgesetzt, bis mindestens ein anwendbar, zugegriffen werden kann, nicht-Override-Methodendeklaration gefunden werden.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. Klicken Sie dann führen Sie den Typrückschluss, und der überladungsauflösung, auf den Satz von anwendbar, zugegriffen werden kann, nicht-Override-Methoden, die in diesem Typ deklariert, und rufen die Methode so ausgewählt.Then 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 es stattdessen den Aufruf als ein Aufruf der Erweiterungsmethode zu verarbeiten.If no method was found, try instead to process the invocation as an extension method invocation.

Extension-MethodenaufrufeExtension method invocations

In einem Methodenaufruf (Aufrufe in geschachtelten Instanzen) von einem der FormateIn 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 der normale Verarbeitung des Aufrufs keine anwendbaren Methoden findet, wird versucht, das Konstrukt als ein Aufruf der Erweiterungsmethode 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 weist den Typ der Kompilierzeit dynamic, Erweiterungsmethoden werden nicht angewendet.If expr or any of the args has compile-time type dynamic, extension methods will not apply.

Das Ziel besteht darin, mit der besten finden Type_name C, sodass die entsprechenden Aufruf der statischen Methode durchgeführt werden 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 berechtigte wenn:An extension method Ci.Mj is eligible if:

  • Ci ist eine nicht generische und nicht geschachtelten-KlasseCi is a non-generic, non-nested class
  • Der Name des Mj ist BezeichnerThe name of Mj is identifier
  • Mj ist verfügbar und anwendbar, wenn auf die Argumente als statische Methode angewendet werden, wie oben gezeigtMj is accessible and applicable when applied to the arguments as a static method as shown above
  • Eine implizite identitätsänderung, Verweis- oder Boxing-Konvertierung vorhanden ist, von Expr in den Typ des ersten Parameters von Mj.An implicit identity, reference or boxing conversion exists from expr to the type of the first parameter of Mj.

Die Suche nach C wird wie folgt:The search for C proceeds as follows:

  • Beginnend mit der nächsten einschließenden Deklaration des Namespaces anhand jedes einschließenden Namespace-Deklaration und endet mit der enthaltenden Kompilierungseinheit, werden aufeinander folgende Versuche unternommen, um einen möglichen Satz von Erweiterungsmethoden ermitteln: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 Kompilierung Organizational Unit direkt nicht generische Typdeklarationen aus Ci mit berechtigten Erweiterungsmethoden Mj, und klicken Sie dann der Satz von dieser Erweiterungsmethoden die Candidate-Gruppe ist.If the given namespace or compilation unit directly contains non-generic type declarations Ci with eligible extension methods Mj, then the set of those extension methods is the candidate set.
    • Wenn Typen Ci importiert Using_static_declarations und direkt im von importierten Namespaces deklariert Using_namespace_directives in der angegebenen Namespace oder die Kompilierung Einheit direkt enthält Erweiterungsmethoden für berechtigte Mj, und klicken Sie dann der Satz von dieser Erweiterungsmethoden die Candidate-Gruppe ist.If types Ci imported by using_static_declarations and directly declared in namespaces imported by using_namespace_directives in the given namespace or compilation unit directly contain eligible extension methods Mj, then the set of those extension methods is the candidate set.
  • Wenn kein Kandidat festgelegt, die in jeder einschließenden Namespace-Deklaration oder Kompilierung Einheit gefunden wird, tritt ein Fehler während der Kompilierung.If no candidate set is found in any enclosing namespace declaration or compilation unit, a compile-time error occurs.
  • Andernfalls wird die Auflösung von funktionsüberladungen Kandidaten festlegen, wie in beschrieben angewendet (Überladungsauflösung).Otherwise, overload resolution is applied to the candidate set as described in (Overload resolution). Wenn bewährte Methoden gefunden wird, tritt ein Fehler während der Kompilierung.If no single best method is found, a compile-time error occurs.
  • C ist der Typ, in dem die beste Methode als eine Erweiterungsmethode deklariert ist.C is the type within which the best method is declared as an extension method.

Mithilfe von C als Ziel, Aufruf der Methode dann als Aufruf einer statischen Methode verarbeitet (Überprüfungen zur Kompilierzeit der dynamischen überladungsauflö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 vorangehenden Regeln bedeuten, dass es sich bei Instanzmethoden Vorrang vor Erweiterungsmethoden haben, dass Erweiterungsmethoden zur Verfügung, in der inneren Namespacedeklarationen gegenüber den Erweiterungsmethoden in den äußeren Namespace-Deklarationen und die Erweiterung verfügbar Vorrang Methoden, die direkt in einem Namespace deklariert haben Vorrang vor Erweiterungsmethoden, die in diesen gleichen Namespace mit einem importierten Namespace-Anweisung.The 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. Zum 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)
    }
}

Im Beispiel BMethode hat Vorrang vor die erste Erweiterungsmethode, und CMethode hat Vorrang vor beiden Erweiterungsmethoden.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 ist:The output of this example is:

E.F(1)
D.G(2)
C.H(3)

D.G hat Vorrang vor C.G, und E.F hat Vorrang vor beide D.F und C.F.D.G takes precedence over C.G, and E.F takes precedence over both D.F and C.F.

Delegieren von AufrufenDelegate invocations

Für einen Delegataufruf der Primary_expression von der Invocation_expression muss sein Wert eine Delegate_type.For a delegate invocation, the primary_expression of the invocation_expression must be a value of a delegate_type. Darüber hinaus in Betracht ziehen die Delegate_type ein Funktionsmember mit derselben Parameterliste als sein die Delegate_type, wird die Delegate_type muss anwendbar ( Anwendbarer Funktionsmember) in Bezug auf die Argument_list von der Invocation_expression.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 Run-Time-Verarbeitung von einem Delegataufruf des Formulars D(A), wobei D ist eine Primary_expression von einer Delegate_type und A ist eine optionale Argument_list, umfasst die folgenden Schritte aus: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 Evaluierungsversion auf eine Ausnahme auslöst, werden keine weiteren Schritte ausgeführt.If this evaluation causes an exception, no further steps are executed.
  • Der Wert des D wird überprüft, um gültig sein.The value of D is checked to be valid. Wenn der Wert des D ist null, System.NullReferenceException wird ausgelöst, und keine weiteren Schritte ausgeführt werden.If the value of D is null, a System.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. Member Funktionsaufrufen (Überprüfungen zur Kompilierzeit der dynamischen überladungsauflösung) jede der aufrufbaren Entitäten in der Aufrufliste des Delegaten ausgeführt werden.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. Für aufrufbare Entitäten, die aus einer Instanz und eine Instanzmethode besteht ist die Instanz für den Aufruf der Instanz, die in die aufrufbare Entität enthalten sind.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

Ein Element_access besteht aus einer Primary_no_array_creation_expression, gefolgt von einer "[" token, gefolgt von ein Argument_list, gefolgt von einer " ]"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. Die Argument_list besteht aus einem oder mehreren Arguments, die durch Kommas getrennt.The argument_list consists of one or more arguments, separated by commas.

element_access
    : primary_no_array_creation_expression '[' expression_list ']'
    ;

Die Argument_list von einem Element_access darf nicht enthalten ref oder out Argumente.The argument_list of an element_access is not allowed to contain ref or out arguments.

Ein Element_access dynamisch gebunden ist (dynamische Bindung), wenn mindestens eine der folgenden enthält:An element_access is dynamically bound (Dynamic binding) if at least one of the following holds:

  • Die Primary_no_array_creation_expression weist den Typ der Kompilierzeit dynamic.The primary_no_array_creation_expression has compile-time type dynamic.
  • Mindestens ein Ausdruck, der die Argument_list weist den Typ der Kompilierzeit dynamic und Primary_no_array_creation_expression verfügt nicht über einen Arraytyp.At least one expression of the argument_list has compile-time type dynamic and the primary_no_array_creation_expression does not have an array type.

In diesem Fall der Compiler klassifiziert die Element_access als ein Wert vom Typ dynamic.In this case the compiler classifies the element_access as a value of type dynamic. Den Regeln unten, um zu bestimmen, die Bedeutung des das Element_access gelten dann zur Laufzeit, der Kompilierzeittyp, der von der Laufzeit-Typinformationen anstelle der Primary_no_array_creation_expressionund Argument_list Ausdrücke mit der Kompilierzeittyp 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 die Primary_no_array_creation_expression hat keinen Kompilierzeittyp dynamic, und klicken Sie dann den Elementzugriff eine begrenzte Kompilierung Zeit Überprüfung durchgeführt wird, wie in beschrieben Überprüfungen zur Kompilierzeit dynamisch Auflösen der Überladung.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 von eine Element_access ist ein Wert, der eine Array_type, wird die Element_access ist 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 die Primary_no_array_creation_expression muss eine Variable oder den Wert der Klasse, Struktur oder Schnittstellentyp, der einen oder mehrere Indexer-Member, in diesem Fall verfügt die Element_access ist ein Indexzugriff (Indexerzugriff).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

Für ein Arrayzugriff verfügt die Primary_no_array_creation_expression von der Element_access muss sein Wert eine Array_type.For an array access, the primary_no_array_creation_expression of the element_access must be a value of an array_type. Darüber hinaus die Argument_list eines Arrays Zugriff ist nicht zulässig, benannte Argumente enthält. Die Anzahl der Ausdrücke in der Argument_list muss identisch mit den Rang der Array_type, und jeder Ausdruck muss vom Typ int, uint, long, ulong, oder muss implizit in eine oder mehrere der folgenden Typen sein.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 ein Arrayzugriff verfügt, wird eine Variable vom Typ Elements des Arrays, nämlich dem Array-Element, das ausgewählt, indem die Werte der Ausdrücke in der Argument_list.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 Verarbeitung zur Laufzeit ein Arrayzugriff verfügt der Form P[A], wobei P ist eine Primary_no_array_creation_expression von einer Array_type und A ist ein Argument_list, umfasst die folgenden Schritte aus: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 Evaluierungsversion auf eine Ausnahme auslöst, werden keine weiteren Schritte ausgeführt.If this evaluation causes an exception, no further steps are executed.
  • Der Index von Ausdrücken für die 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. Befolgen Sie die Auswertung jedes Ausdrucks Index, eine implizite Konvertierung (implizite Konvertierungen) auf einen der folgenden Typen erfolgt: 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, die für die eine implizite Konvertierung vorhanden ist, wird ausgewählt.The first type in this list for which an implicit conversion exists is chosen. Z. B. wenn der Indexausdruck vom Typ short klicken Sie dann eine implizite Konvertierung in int ausgeführt, da implizite Konvertierungen aus short zu int und short zu long sind möglich.For instance, if the index expression is of type short then an implicit conversion to int is performed, since implicit conversions from short to int and from short to long are possible. Wenn die Auswertung von Ausdruckswerten Index oder die nachfolgenden implizite Konvertierung eine Ausnahme verursacht hat, klicken Sie dann keine weiteren Indexausdrücke werden ausgewertet, und keine weiteren Schritte ausgeführt werden.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 des P wird überprüft, um gültig sein.The value of P is checked to be valid. Wenn der Wert des P ist null, System.NullReferenceException wird ausgelöst, und keine weiteren Schritte ausgeführt werden.If the value of P is null, a System.NullReferenceException is thrown and no further steps are executed.
  • Der Wert der einzelnen Ausdrücke aus der Argument_list aktiviert ist, für die eigentlichen Grenzen jeder Arraydimension der Arrayinstanz verweist P.The value of each expression in the argument_list is checked against the actual bounds of each dimension of the array instance referenced by P. Wenn eine oder mehrere Werte außerhalb des gültigen Bereichs, sind ein System.IndexOutOfRangeException wird ausgelöst, und keine weiteren Schritte ausgeführt werden.If one or more values are out of range, a System.IndexOutOfRangeException is thrown and no further steps are executed.
  • Der Speicherort des Array-Elements vom Index-Ausdrücke wird berechnet, und Hier wird das Ergebnis der Arrayzugriff.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

Indexzugriff die Primary_no_array_creation_expression von der Element_access muss eine Variable oder ein Wert, der eine Klasse, Struktur oder der Schnittstellentyp, und dieser Typ muss eine oder mehrere implementieren Indexer, die in Bezug auf gelten die Argument_list von der Element_access.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 Bindung-Time-Verarbeitung der Indexzugriff des Formulars P[A], wobei P ist eine Primary_no_array_creation_expression der Klasse, Struktur oder Schnittstellentyp T, und A ist ein Argument_list, umfasst die folgenden Schritte aus: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 Satz von Indexern, die von bereitgestellte T erstellt wird.The set of indexers provided by T is constructed. Der Satz besteht aus allen in deklarierten Indexer T oder einem Basistyp von T , die sich nicht override Deklarationen und sind im aktuellen Kontext zugegriffen werden kann (Memberzugriff).The set consists of all indexers declared in T or a base type of T that are not override declarations and are accessible in the current context (Member access).
  • Die Gruppe ist für diesen Indexer, die anwendbar und nicht versteckt sind von anderen Indexern reduziert.The set is reduced to those indexers that are applicable and not hidden by other indexers. Die folgenden Regeln gelten, jeder Indexer S.I in der Gruppe, in denen S ist der Typ, in dem der Indexer I deklariert wird:The following rules are applied to each indexer S.I in the set, where S is the type in which the indexer I is declared:
    • Wenn I ist nicht anwendbar, in Bezug auf A (Anwendbarer Funktionsmember), klicken Sie dann I aus der Gruppe entfernt wird.If I is not applicable with respect to A (Applicable function member), then I is removed from the set.
    • Wenn I gilt in Bezug auf A (Anwendbarer Funktionsmember), in dem Basistyp deklariert alle Indexer S aus der Gruppe entfernt werden.If I is applicable with respect to A (Applicable function member), then all indexers declared in a base type of S are removed from the set.
    • Wenn I gilt in Bezug auf A (Anwendbarer Funktionsmember) und S ist ein Klassentyp außer object, alle in einer Schnittstelle deklarierten Indexer aus der Gruppe entfernt werden.If I is applicable with respect to A (Applicable function member) and S is a class type other than object, all indexers declared in an interface are removed from the set.
  • Wenn die resultierende Menge der Kandidat Indexer leer ist, klicken Sie dann keine anwendbaren Indexer vorhanden, und beim Auftreten eines Laufzeitfehlers-Bindung.If the resulting set of candidate indexers is empty, then no applicable indexers exist, and a binding-time error occurs.
  • Der beste Indexer, der den Satz von Kandidaten Indexer wird mit den Regeln der überladungsauflösung des identifiziert Überladungsauflösung.The best indexer of the set of candidate indexers is identified using the overload resolution rules of Overload resolution. Wenn ein einzelner bewährte Indexer kann nicht identifiziert werden, der Indexer ist nicht eindeutig, und beim Auftreten eines Laufzeitfehlers-Bindung.If a single best indexer cannot be identified, the indexer access is ambiguous, and a binding-time error occurs.
  • Der Index von Ausdrücken für die 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 der Indexerzugriff ist ein Ausdruck, der als Indexzugriff klassifiziert sind.The result of processing the indexer access is an expression classified as an indexer access. Der Indexer Zugriffsausdruck verweist auf den Indexer, der im vorherigen Schritt bestimmt und verfügt über einen zugeordneten Instanzausdruck von P sowie eine Liste zugeordnete Argument A.The indexer access expression references the indexer determined in the step above, and has an associated instance expression of P and an associated argument list of A.

Je nach Kontext, in denen es verwendet wird, verursacht das Indexzugriff Aufrufen des entweder die get-Accessor oder set-Accessor des Indexers.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 Indexzugriff auf das Ziel einer Zuweisung, ist die set-Accessor wird 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 die get-Accessor wird aufgerufen, um den aktuellen Wert zu erhalten (Werte Ausdrücke).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'
    ;

Ein This_access ist zulässig, nur in der Block Instanzkonstruktor, eine Instanzmethode oder einen Instanzaccessor.A this_access is permitted only in the block of an instance constructor, an instance method, or an instance accessor. Es verfügt über eine der folgenden Bedeutungen:It has one of the following meanings:

  • Wenn this werden in einem Primary_expression im Instanzenkonstruktor eine einer Klasse, die sie als Wert klassifiziert wird.When this 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 (den Instanztyp) der Klasse in der ein Fehler auftritt, und der Wert ist ein Verweis auf das Objekt 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 werden in einem Primary_expression innerhalb einer Instanzenmethode oder Instanzaccessor einer Klasse, wird es als Wert klassifiziert.When this 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 (den Instanztyp) der Klasse in der ein Fehler auftritt, und der Wert ist ein Verweis auf das Objekt für die 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 werden in einem Primary_expression innerhalb eines Instanzkonstruktors einer Struktur, wird er als Variable klassifiziert.When this 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 (den Instanztyp) der Struktur klicken Sie in die Nutzung wird, und die Variable verweist auf die Struktur, 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. Die this Variable eines Instanzkonstruktors einer Struktur verhält sich genau wie ein out Parameter des Strukturtyps – insbesondere bedeutet dies, dass die Variable auf jeden Fall in allen Ausführungspfaden der Instanz zugewiesen werden muss Konstruktor.The this variable of an instance constructor of a struct behaves exactly the same as an out 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 werden in einem Primary_expression innerhalb einer Instanzenmethode oder Instanzaccessor einer Struktur, wird er als Variable klassifiziert.When this 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 (den Instanztyp) der Struktur, in dem sich die Verwendung stattfindet.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 ist (Iteratoren), wird die this Variable darstellt, die Struktur für die die Methode oder der Accessor wurde aufgerufen, und verhält sich genauso wie eine ref Parameter des Strukturtyps.If the method or accessor is not an iterator (Iterators), the this variable represents the struct for which the method or accessor was invoked, and behaves exactly the same as a ref parameter of the struct type.
    • Wenn die Methode oder der Accessor ein Iterator ist, der this Variable darstellt, eine Kopie der Struktur für die die Methode oder der Accessor wurde aufgerufen, und verhält sich genau wie ein Value-Parameter des Strukturtyps.If the method or accessor is an iterator, the this 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.

Verwenden von this in einem Primary_expression in einem anderen Kontext als oben aufgeführt ist ein Fehler während der Kompilierung.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, verweisen auf this in einer statischen Methode, eine statische Eigenschaftenaccessor oder in einem Variable_initializer einer Felddeklaration.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.

BasiszugriffBase access

Ein Base_access besteht aus dem reservierten Wort base gefolgt von entweder eine "." Zugriffstoken und ein Bezeichner oder ein Argument_list in eckige Klammern eingeschlossen: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 verwendet, um der Member der Basisklasse zuzugreifen, die von den entsprechend benannten Elemente 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. Ein Base_access ist zulässig, nur in der Block Instanzkonstruktor, eine Instanzmethode oder einen Instanzaccessor.A base_access is permitted only in the block of an instance constructor, an instance method, or an instance accessor. Wenn base.I tritt auf, in einer Klasse oder Struktur I muss ein Member der Basisklasse der Klasse oder Struktur zu kennzeichnen.When base.I occurs in a class or struct, I must denote a member of the base class of that class or struct. Auch wenn base[E] tritt auf, in einer Klasse ein passender Indexer muss vorhanden sein, in der Basisklasse.Likewise, when base[E] occurs in a class, an applicable indexer must exist in the base class.

Zum Zeitpunkt der Bindung Base_access Ausdrücken der Form base.I und base[E] werden ausgewertet, als ob sie geschrieben wurden ((B)this).I und ((B)this)[E], wobei B ist die Basisklasse der Klasse oder eine Struktur, die in dem 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. Daher base.I und base[E] entsprechen this.I und this[E], mit Ausnahme von this als eine Instanz der Basisklasse angezeigt wird.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 verweist auf ein virtuelle Funktion-Element (eine Methode, Eigenschaft, oder Indexer), die Bestimmung der Funktion zur Laufzeit aufzurufenden Member (Überprüfungen zur Kompilierzeit der dynamischen überladungsauflösung ) geändert wird.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 Funktionsmember der Member, die aufgerufen wird, richtet sich nach der Suche nach der am weitesten abgeleiteten Implementierung (virtuelle Methoden) des Funktionsmembers in Bezug auf B (anstelle von in Bezug auf den Laufzeittyp der this, wie üblich in einer nicht-Base Zugriff wäre).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 innerhalb eine override von einer virtual Funktionsmember der Member, eine Base_access kann zum Aufrufen der geerbten Implementierung von der Funktionsmember der Member verwendet werden.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 Funktionselement verweist eine Base_access ist eine abstrakte tritt ein Fehler während der Bindung.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 Postfixinkrement oder Dekrement Operation muss ein Ausdruck, der als eine Variable, einen Eigenschaftenzugriff oder Indexzugriff klassifiziert sein.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 des gleichen Typs als Operand.The result of the operation is a value of the same type as the operand.

Wenn die Primary_expression weist den Typ der Kompilierzeit dynamic und klicken Sie dann der Operator dynamisch gebunden ist (dynamische Bindung), wird die Post_increment_expressionoder Post_decrement_expression weist den Typ der Kompilierzeit dynamic und die folgenden Regeln gelten zur Laufzeit mit dem Laufzeit-Typ, der die Primary_expression.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 einem Postfix erhöhen oder dekrementvorgang ist eine Eigenschaft oder Zugriffs auf Indexer, Eigenschaft oder des Indexers benötigen Sie Folgendes ein get und set Accessor.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 Fehler während der Bindung.If this is not the case, a binding-time error occurs.

Unäroperator der überladungsauflösung (unäroperator überladungsauflösung) wird angewendet, um einen bestimmten Operator-Implementierung auswählen.Unary operator overload resolution (Unary operator overload resolution) is applied to select a specific operator implementation. Vordefinierte ++ und -- Operatoren vorhanden, für die folgenden Typen: sbyte, byte, short, ushort, int, uint, long, ulong, char , float, double, decimal, und alle Enumerationstypen.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 zurückgegeben, den von den Operanden und den vordefinierten 1 hinzugefügt erzeugten Wert -- Operatoren geben einen Wert durch Subtrahieren der Operand 1 zurück.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. In einem checked Kontext, wenn das Ergebnis dieser Addition oder Subtraktion außerhalb des Bereichs des Ergebnistyps ist und der Ergebnistyp ein ganzzahliger Typ oder ein Enumerationstyp ist, eine System.OverflowException 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 Verarbeitung zur Laufzeit ein Postfixinkrement oder dekrementvorgang des Formulars x++ oder x-- umfasst die folgenden Schritte aus:The run-time processing of a postfix increment or decrement operation of the form x++ or x-- consists of the following steps:

  • Wenn x wird als Variable klassifiziert:If x is classified as a variable:
    • x wird ausgewertet, um die Variable zu erstellen.x is evaluated to produce the variable.
    • Der Wert des x gespeichert wird.The value of x is saved.
    • Der ausgewählte Operator wird aufgerufen, mit dem gespeicherten Wert von x als Argument.The selected operator is invoked with the saved value of x as its argument.
    • Der Wert, der vom Operator zurückgegebenen befindet sich in den Speicherort, durch die Auswertung von x.The value returned by the operator is stored in the location given by the evaluation of x.
    • Der gespeicherte Wert des x wird das Ergebnis des Vorgangs.The saved value of x becomes the result of the operation.
  • Wenn x wird als eine Eigenschaft oder der Indexer Zugriff klassifiziert:If x is classified as a property or indexer access:
    • Der Instanzausdruck (Wenn x ist nicht static) und die Argumentliste (Wenn x Indexzugriff ist) zugeordneten x werden ausgewertet, und die Ergebnisse werden in der nachfolgenden verwendet get und set Accessor-Aufrufe.The instance expression (if x is not static) and the argument list (if x is an indexer access) associated with x are evaluated, and the results are used in the subsequent get and set accessor invocations.
    • Die get Accessor x wird aufgerufen, und der zurückgegebene Wert gespeichert wird.The get accessor of x is invoked and the returned value is saved.
    • Der ausgewählte Operator wird aufgerufen, mit dem gespeicherten Wert von x als Argument.The selected operator is invoked with the saved value of x as its argument.
    • Die set Accessor x wird aufgerufen, mit dem Wert, der zurückgegeben wird, durch den Operator als seine value Argument.The set accessor of x is invoked with the value returned by the operator as its value argument.
    • Der gespeicherte Wert des x wird das Ergebnis des Vorgangs.The saved value of x becomes the result of the operation.

Die ++ und -- Operatoren unterstützt auch die Präfix-Notation (Präfix-Inkrement und Dekrement-Operatoren).The ++ and -- operators also support prefix notation (Prefix increment and decrement operators). In der Regel das Ergebnis des x++ oder x-- ist der Wert des x vor dem Vorgang, während das Ergebnis des ++x oder --x ist der Wert des x nach Abschluss des Vorgangs.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 beiden Fällen x selbst hat den gleichen Wert nach Abschluss des Vorgangs.In either case, x itself has the same value after the operation.

Ein operator ++ oder operator -- Implementierung kann mithilfe der Präfix oder Postfix-Notation aufgerufen werden.An operator ++ or operator -- implementation can be invoked using either postfix or prefix notation. Es ist nicht möglich, separate 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

Die 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 Arten von new Ausdrücke:There are three forms of new expressions:

  • Objektausdrücke-Erstellung werden verwendet, um neue Instanzen der Klasse und Werttypen zu erstellen.Object creation expressions are used to create new instances of class types and value types.
  • Array-erstellen-Ausdrücke werden verwendet, zum Erstellen neuer Instanzen von Arraytypen dar.Array creation expressions are used to create new instances of array types.
  • Delegat erstellen Ausdrücke werden verwendet, um neue Instanzen von Delegaten erstellt.Delegate creation expressions are used to create new instances of delegate types.

Die new Operator impliziert die Erstellung einer Instanz eines Typs, aber es ist nicht notwendigerweise, dass dynamische Zuordnung von Arbeitsspeicher.The new operator implies creation of an instance of a type, but does not necessarily imply dynamic allocation of memory. Insbesondere bei Instanzen von Werttypen benötigt keinen zusätzlichen Speicher über die Variablen in der sie sich befinden, und keine dynamischen Zuordnungen auftreten, wenn new wird verwendet, um Instanzen von Werttypen zu erstellen.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.

Objektausdrücke-ErstellungObject creation expressions

Ein Object_creation_expression wird verwendet, um eine neue Instanz der Erstellen einer Class_type oder Value_type.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
    ;

Die Typ von einer Object_creation_expression muss eine Class_type, Value_type oder ein Type_parameter .The type of an object_creation_expression must be a class_type, a value_type or a type_parameter. Die Typ nicht möglich, eine abstract Class_type.The type cannot be an abstract class_type.

Der optionale Argument_list (Argumentlisten) ist nur zulässig, wenn die Typ ist eine Class_type oder Struct_ Typ.The optional argument_list (Argument lists) is permitted only if the type is a class_type or a struct_type.

Ein Objekterstellungsausdruck kann die Liste des Konstruktorarguments weglassen und einschließende Klammern angegeben, dass es sich um ein Objektinitialisierer oder 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. Die Liste des Konstruktorarguments auslassen und durch Einschließen von Klammern ist gleichbedeutend mit der Angabe einer leeren Argumentliste.Omitting the constructor argument list and enclosing parentheses is equivalent to specifying an empty argument list.

Verarbeitung von einer Objekterstellungsausdruck, der einen Objektinitialisierer oder Auflistungsinitialisierer enthält besteht aus den Instanzkonstruktor zuerst zu verarbeiten und wird bei der Verarbeitung der Member oder Element Initialisierungen, die durch den Objektinitialisierer (angegeben Objektinitialisierer) oder einem Auflistungsinitialisierer (Auflistungsinitialisierer).Processing 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 in der optionalen Argument_list weist den Typ der Kompilierzeit dynamic die Object_creation_expression dynamisch gebunden ist (dynamische Bindung) und die folgenden Regeln gelten zur Laufzeit mit dem Laufzeit-Typ, der diese Argumente von der Argument_list Kompilierzeittyp deren 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 die objekterstellung überprüfen eine begrenzte Kompilieren der Zeit vorgenommen, wie in beschrieben Überprüfungen zur Kompilierzeit der dynamischen überladungsauflösung.However, the object creation undergoes a limited compile time check as described in Compile-time checking of dynamic overload resolution.

Die laufzeitverarbeitung der Bindung einer Object_creation_expression des Formulars new T(A), wobei T ist eine Class_type oder Value_type und A ist eine optionale Argument_list, umfasst die folgenden Schritte aus: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 ist eine Value_type und A ist nicht vorhanden:If T is a value_type and A is not present:
    • Die Object_creation_expression ist ein Standard-Konstruktor-Funktionsaufruf.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 gemäß die System.ValueType-Typ.The result of the object_creation_expression is a value of type T, namely the default value for T as defined in The System.ValueType type.
  • Andernfalls gilt: Wenn T ist eine Type_parameter und A ist nicht vorhanden:Otherwise, if T is a type_parameter and A is not present:
    • Wenn kein werttypeinschränkung oder Konstruktoreinschränkung (Geben Sie die Einschränkungen für Typparameter) wurde angegeben T, tritt ein Fehler während der Bindung.If no value type constraint or constructor constraint (Type parameter constraints) has been specified for T, a binding-time error occurs.
    • Das Ergebnis der Object_creation_expression ist ein Wert von der Run-Time-Typ, der der Type-Parameter gebunden wurde, d. h. das Ergebnis von Aufrufen des Standardkonstruktors des 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 Laufzeit-Typ kann es sich um ein Verweistyp oder ein Werttyp sein.The run-time type may be a reference type or a value type.
  • Andernfalls gilt: Wenn T ist eine Class_type oder Struct_type:Otherwise, if T is a class_type or a struct_type:
    • Wenn T ist ein abstract Class_type, ein Fehler während der Kompilierung auftritt.If T is an abstract class_type, a compile-time error occurs.
    • Die Instanzkonstruktor aufrufen wird bestimmt, mit den Regeln der überladungsauflösung des Überladungsauflösung.The instance constructor to invoke is determined using the overload resolution rules of Overload resolution. Der Satz von Kandidaten Instanzkonstruktoren besteht aus allen verfügbaren Instanzkonstruktoren in deklarierten T der gelten in Bezug auf A (Anwendbarer Funktionsmember).The set of candidate instance constructors consists of all accessible instance constructors declared in T which are applicable with respect to A (Applicable function member). Wenn der Satz von Kandidaten Instanzkonstruktoren leer ist, oder ein einzelnen bewährte Instanzenkonstruktor nicht identifiziert werden kann, tritt auf, ein Fehler während der Bindung.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 erzeugt, durch Aufrufen des Instanzkonstruktors im vorherigen Schritt bestimmt.The result of the object_creation_expression is a value of type T, namely the value produced by invoking the instance constructor determined in the step above.
  • Andernfalls die Object_creation_expression ist ungültig, und ein Fehler während der Bindung erfolgt.Otherwise, the object_creation_expression is invalid, and a binding-time error occurs.

Auch wenn die Object_creation_expression dynamisch gebunden, der während der Kompilierung-Typ ist immer noch T.Even if the object_creation_expression is dynamically bound, the compile-time type is still T.

Die Verarbeitung zur Laufzeit eine Object_creation_expression des Formulars new T(A), wobei T ist Class_type oder Struct_type und A ist eine optionale Argument_list, umfasst die folgenden Schritte aus: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 ist eine Class_type:If T is a class_type:
    • Eine neue Instanz der Klasse T zugeordnet ist.A new instance of class T is allocated. Wenn nicht genügend Arbeitsspeicher verfügbar, um die neue Instanz einer System.OutOfMemoryException wird ausgelöst, und keine weiteren Schritte ausgeführt werden.If there is not enough memory available to allocate the new instance, a System.OutOfMemoryException is thrown and no further steps are executed.
    • Alle Felder der neuen Instanz werden auf ihre Standardwerte initialisiert (Standardwerte).All fields of the new instance are initialized to their default values (Default values).
    • Der Instanzkonstruktor wird aufgerufen, gemäß den Regeln von der Members-Funktionsaufruf (Überprüfungen zur Kompilierzeit der dynamischen überladungsauflösung).The instance constructor is invoked according to the rules of function member invocation (Compile-time checking of dynamic overload resolution). Ein Verweis auf das neu zugeordnete Instanz automatisch an die Instanzkonstruktor übergeben wird und die Instanz kann zugegriffen werden aus diesen Konstruktor als 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 as this.
  • Wenn T ist eine Struct_type:If T is a struct_type:
    • Eine Instanz des Typs T wird erstellt, indem Sie eine temporäre lokale Variable zuordnen.An instance of type T is created by allocating a temporary local variable. Seit einem Instanzenkonstruktor der ein Struct_type ist erforderlich, um auf jeden Fall wird jedes Feld der-Instanz erstellt wird, wird keine Initialisierung der temporären Variable muss einen Wert zuzuweisen.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 aufgerufen, gemäß den Regeln von der Members-Funktionsaufruf (Überprüfungen zur Kompilierzeit der dynamischen überladungsauflösung).The instance constructor is invoked according to the rules of function member invocation (Compile-time checking of dynamic overload resolution). Ein Verweis auf das neu zugeordnete Instanz automatisch an die Instanzkonstruktor übergeben wird und die Instanz kann zugegriffen werden aus diesen Konstruktor als 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 as this.

ObjektinitialisiererObject initializers

Ein Objektinitialisierer gibt Werte für NULL oder mehr Felder, Eigenschaften oder indizierte Elemente eines Objekts.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 der Standardmember-Initialisierer, eingeschlossene { und } Token und durch Kommas getrennt.An object initializer consists of a sequence of member initializers, enclosed by { and } tokens and separated by commas. Jede Member_initializer kennzeichnet ein Ziel für die Initialisierung.Each member_initializer designates a target for the initialization. Ein Bezeichner müssen den Namen einer zugänglichen Feld oder -Eigenschaft des Objekts initialisiert wird, während ein Argument_list eingeschlossen in eckigen Klammern müssen die Argumente für einen Indexer zugegriffen werden kann angeben, auf die das Objekt 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 für einen Objektinitialisierer, um mehr als ein Member-Initialisierer für das gleiche Feld oder Eigenschaft enthalten.It is an error for an object initializer to include more than one member initializer for the same field or property.

Jede Initializer_target ist, gefolgt von einem Gleichheitszeichen und entweder ein Ausdruck, einen Objektinitialisierer oder einem 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, für die Ausdrücke in den Objektinitialisierer, um auf das neu erstellte Objekt zu verweisen, die es 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, nach die Gleichheitszeichen auf die gleiche Weise wie eine Zuordnung verarbeitet werden (einfache Zuweisung) an das Ziel.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, nach die Gleichheitszeichen ist eine geschachtelte Objektinitialisierer, 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 das Feld oder die Eigenschaft einen neuen Wert zuzuweisen, werden die Zuweisungen aus dem geschachtelten Objektinitialisierer als Zuweisungen auf Member 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. Geschachtelte Objektinitialisierer können nicht angewendet werden, um Eigenschaften mit einem Werttyp oder schreibgeschützte Felder mit einem Werttyp.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 angibt, einen Auflistungsinitialisierer nach dem Gleichheitszeichen ist eine Initialisierung einer eingebetteten Auflistung.A member initializer that specifies a collection initializer after the equals sign is an initialization of an embedded collection. Anstatt das Feld "Ziel", Eigenschaft oder der Indexer eine neue Sammlung zuzuweisen, werden die Elemente im Initialisierer erhält der Auflistung, die auf das Ziel hinzugefügt.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 eines Auflistungstyps, das die in angegebenen Anforderungen erfüllt sein muss Auflistungsinitialisierer.The target must be of a collection type that satisfies the requirements specified in Collection initializers.

Die Argumente für einen Index Initialisierer werden immer genau einmal ausgewertet.The arguments to an index initializer will always be evaluated exactly once. Also auch wenn die Argumente am Ende niemals verwendet (z. B. aufgrund eines leeren geschachtelten Initialisierers), werden sie für 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 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 erstellt und wie folgt initialisiert werden:An instance of Point can be created and initialized as follows:

Point a = new Point { X = 0, Y = 1 };

Das hat dieselbe Wirkung wie daswhich has the same effect as

Point __a = new Point();
__a.X = 0;
__a.Y = 1; 
Point a = __a;

wo __a ist eine temporäre Variable andernfalls nicht sichtbare und kann nicht zugegriffen werden.where __a is an otherwise invisible and inaccessible temporary variable. Die folgende Klasse stellt ein Rechteck, das aus zwei Punkten erstellt: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 erstellt und wie folgt 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 }
};

Das hat dieselbe Wirkung wie daswhich 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;

wo __r, __p1 und __p2 werden temporäre Variablen, die andernfalls nicht sichtbar und kann nicht zugegriffen werden.where __r, __p1 and __p2 are temporary variables that are otherwise invisible and inaccessible.

Wenn RectangleKonstruktor weist die beiden eingebettet Point InstanzenIf 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 verwendet werden kann, um das eingebettete initialisieren Point Instanzen, anstatt neue Instanzen: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 }
};

Das hat dieselbe Wirkung wie daswhich 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;

Betrachten Sie eine Definition von C, im folgenden Beispiel an: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 diese 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;

wo __cusw. werden generierte Variablen, die nicht sichtbar 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] sind nur ein Mal ausgewertet, und die Argumente für [1,2] einmal ausgewertet werden, auch wenn sie nicht 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 an, die Elemente einer Auflistung.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 Folge von elementinitialisierern, eingeschlossene { und } Token und durch Kommas getrennt.A collection initializer consists of a sequence of element initializers, enclosed by { and } tokens and separated by commas. Jeder Elementinitialisierer gibt ein Element, das initialisierte Objekt hinzugefügt werden, und besteht aus einer Liste von Ausdrücken, die vom eingeschlossen { und } Token und durch Kommas getrennt.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. Einen einzelnen Ausdrücken Elementinitialisierer ohne geschweifte Klammern geschrieben werden kann, jedoch nicht klicken Sie dann ein Zuweisungsausdruck, um Mehrdeutigkeiten zu vermeiden, mit der Standardmember-Initialisierer.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 wird definiert, Ausdruck.The non_assignment_expression production is defined in Expression.

Im folgenden finden ein Beispiel für eine Objekterstellungsausdruck, die einen auflistungs-bzw. Arrayinitialisierers enthält: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 Auflistungsobjekt, das für die ein Auflistungsinitialisierer gilt muss von einem Typ sein, die implementiert System.Collections.IEnumerable oder ein Fehler während der Kompilierung auftritt.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 Element in der Reihenfolge angegeben, wird der Auflistungsinitialisierer Ruft eine Add Methode auf der Ziel-Objekt mit der Liste mit Ausdrücken des elementinitialisierers als Argumentliste normalen Membersuche anwenden und für jeden Aufruf der überladungsauflösung.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. Daher müssen das Objekt eine anwendbare Instanz- oder Erweiterungsmethode-Methode mit dem Namen Add für jedes Elementinitialisierer.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 eine Liste der 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; } }
}

Ein List<Contact> erstellt und wie folgt 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" }
    }
};

Das hat dieselbe Wirkung wie daswhich 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;

wo __clist, __c1 und __c2 werden temporäre Variablen, die andernfalls nicht sichtbar und kann nicht zugegriffen werden.where __clist, __c1 and __c2 are temporary variables that are otherwise invisible and inaccessible.

Arrayausdrücke-ErstellungArray creation expressions

Ein Array_creation_expression wird verwendet, um eine neue Instanz der Erstellen einer Array_type.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 Arrayausdruck für die Erstellung der ersten Form weist eine Arrayinstanz des Typs, das Löschen der einzelnen Ausdrücke aus der Liste mit Ausdrücken 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. Z. B. die Arrayerstellungsausdruck new int[10,20] erzeugt eine Arrayinstanz des Typs int[,], und der Ausdruck zur Arrayerstellung 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 Liste mit Ausdrücken muss vom Typ int, uint, long, oder ulong, oder implizit in eine oder mehrere dieser Typen.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 zugewiesenen Arrayinstanz fest.The value of each expression determines the length of the corresponding dimension in the newly allocated array instance. Da die Länge einer Dimension des Arrays nicht negativ sein muss, ist es ein Fehler während der Kompilierung, damit eine Constant_expression mit einem negativen Wert in der Liste mit Ausdrücken.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.

Mit Ausnahme der in einem unsicheren Kontext (nicht sicheren Kontexten), das Layout des Arrays ist nicht angegeben.Except in an unsafe context (Unsafe contexts), the layout of arrays is unspecified.

Wenn einem Arrayerstellungsausdruck der ersten Form einen Arrayinitialisierer enthält, wird jeder Ausdruck in der Liste mit Ausdrücken muss eine Konstante sein, und der Rang jede Dimension angegebenen Länge durch die Liste der Ausdrücke angegeben, müssen mit denen des Arrayinitialisierers übereinstimmen.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 Arrayerstellungsausdruck der zweite oder dritte Form muss es sich bei der Rang des dem angegebenen Array-Typ oder Rang Bezeichner mit des Arrayinitialisierers übereinstimmen.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 Längen der einzelnen Dimension werden von der Anzahl der Elemente in jedem von der entsprechenden Schachtelungsebenen des Arrayinitialisierers hergeleitet.The individual dimension lengths are inferred from the number of elements in each of the corresponding nesting levels of the array initializer. Daher wird, ist der AusdruckThus, the expression

new int[,] {{0, 1}, {2, 3}, {4, 5}}

genau entspricht.exactly corresponds to

new int[3, 2] {{0, 1}, {2, 3}, {4, 5}}

Die dritte Form einem Arrayerstellungsausdruck wird als bezeichnet ein implizit typisierten Ausdruck zur Arrayerstellung.An array creation expression of the third form is referred to as an implicitly typed array creation expression. Es ähnelt der zweiten Form, mit dem Unterschied, dass der Elementtyp des Arrays nicht explizit jedoch als der am besten verwendete Typ bestimmt angegeben wird, (Suchen nach den besten common-Typ, der einen Satz von Ausdrücken) des Satzes von Ausdrücken im Array Initialisierer.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. Für ein mehrdimensionales Array d. h. eine Where der Rank_specifier enthält mindestens ein Komma, dieser Satz besteht aus allen Ausdrucks finden Sie in geschachtelten Array_initializers.For a multidimensional array, i.e., one where the rank_specifier contains at least one comma, this set comprises all expressions found in nested array_initializers.

Arrayinitialisierer sind unter Array Initializers.Array initializers are described further in Array initializers.

Das Ergebnis der Auswertung von einem Arrayerstellungsausdruck wird als ein Wert, d. h. einen Verweis auf die neu zugewiesene Arrayinstanz klassifiziert.The result of evaluating an array creation expression is classified as a value, namely a reference to the newly allocated array instance. Die Verarbeitung zur Laufzeit von einem Arrayerstellungsausdruck umfasst die folgenden Schritte aus:The run-time processing of an array creation expression consists of the following steps:

  • Der Dimension Länge von Ausdrücken für die 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. Befolgen Sie die Auswertung der einzelnen Ausdrücke, die eine implizite Konvertierung (implizite Konvertierungen) auf einen der folgenden Typen erfolgt: 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, die für die 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 einer nachfolgenden impliziten Konvertierung eine Ausnahme auslöst, klicken Sie dann keine weitere Ausdrücke werden ausgewertet, und keine weiteren Schritte ausgeführt werden.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 Werte für die Längen der Dimension werden wie folgt überprüft werden.The computed values for the dimension lengths are validated as follows. Wenn eine oder mehrere der Werte sind kleiner als 0 (null), eine System.OverflowException wird ausgelöst, und keine weiteren Schritte ausgeführt werden.If one or more of the values are less than zero, a System.OverflowException is thrown and no further steps are executed.
  • Es wird eine Arrayinstanz mit Längen der angegebenen Dimension zugeordnet.An array instance with the given dimension lengths is allocated. Wenn nicht genügend Arbeitsspeicher verfügbar, um die neue Instanz einer System.OutOfMemoryException wird ausgelöst, und keine weiteren Schritte ausgeführt werden.If there is not enough memory available to allocate the new instance, a System.OutOfMemoryException is thrown and no further steps are executed.
  • Alle Elemente der neuen Arrayinstanz werden auf ihre Standardwerte initialisiert (Standardwerte).All elements of the new array instance are initialized to their default values (Default values).
  • Wenn der Ausdruck zur Arrayerstellung einen Arrayinitialisierer enthält, wird jeder Ausdruck im Arrayinitialisierer ausgewertet und das entsprechende Arrayelement 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 erfolgen in der Reihenfolge der Ausdrücke im Arrayinitialisierer geschrieben werden, in anderen Worten: Elemente werden in aufsteigender Indexreihenfolge, mit die Dimension ganz rechts erhöhen zuerst initialisiert.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 zu dem entsprechenden Array-Element eine Ausnahme verursacht hat, klicken Sie dann keine weiteren Elemente initialisiert werden (und die übrigen Elemente werden daher Standardwerte haben).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 Ausdruck zur Arrayerstellung ermöglicht die Instanziierung eines Arrays mit Elementen eines Arraytyps, aber die Elemente dieses 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 wird die AnweisungFor example, the statement

int[][] a = new int[100][];

erstellt ein eindimensionales Array mit 100 Elementen des Typs int[].creates a single-dimensional array with 100 elements of type int[]. Der anfängliche Wert jedes Elements ist null.The initial value of each element is null. Es ist nicht möglich, für die gleiche Arrayerstellungsausdruck Teilarrays aus, und die Anweisung auch instanziierenIt 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 Fehler während der Kompilierung.results in a compile-time error. Die Instanziierung der Teilarrays muss stattdessen manuell, wie im ausgeführt werdenInstantiation 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 mit eine Form "rechteckige", die d. h. untergeordneten Arrays gleicher Länge sind aufweist, ist es effizienter, ein mehrdimensionales Array 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 – eine äußere Array und 100 Teilarrays.In the example above, instantiation of the array of arrays creates 101 objects—one outer array and 100 sub-arrays. Im Gegensatz dazu sindIn contrast,

int[,] = new int[100, 5];

erstellt nur ein einzelnes Objekt, ein zweidimensionales Array, und die Zuweisung in einer einzelnen Anweisung erreicht.creates only a single object, a two-dimensional array, and accomplishes the allocation in a single statement.

Es folgen Beispiele für Ausdrücke für implizit typisierte Arrays erstellen: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 Kompilierungsfehler, da weder int noch string implizit in den anderen, und es kommt nicht am besten geben.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. Ein explizit typisierte Ausdruck zur Arrayerstellung muss verwendet werden in diesem Fall z. B. Angabe des Typs werden object[].An explicitly typed array creation expression must be used in this case, for example specifying the type to be object[]. Eines der Elemente kann auch in einen gemeinsamen Basistyp umgewandelt werden die klicken Sie dann den abgeleitete Elementtyp aufweisen würden.Alternatively, one of the elements can be cast to a common base type, which would then become the inferred element type.

Implizit typisiertes Array erstellen Ausdrücke mit anonyme Objektinitialisierer kombiniert werden können (anonyme Erstellung Objektausdrücke) zum Erstellen anonym typisierte Datenstrukturen.Implicitly typed array creation expressions can be combined with anonymous object initializers (Anonymous object creation expressions) to create anonymously typed data structures. Zum 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" }
    }
};

Delegieren Sie die Erstellung von AusdrückenDelegate creation expressions

Ein Delegate_creation_expression wird verwendet, um eine neue Instanz der Erstellen einer Delegate_type.A delegate_creation_expression is used to create a new instance of a delegate_type.

delegate_creation_expression
    : 'new' delegate_type '(' expression ')'
    ;

Das Argument ein Delegatausdruck für die Erstellung muss eine Methodengruppe, eine anonyme Funktion oder einen Wert, der entweder den Kompilierzeittyp dynamic oder Delegate_type.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 Methodengruppe ist, kennzeichnet es die Methode und eine Instanzmethode, die das Objekt für die Erstellung ein Delegaten.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, die sie direkt die Parameter und den Methodentext, der das Delegatziel definiert ist.If the argument is an anonymous function it directly defines the parameters and method body of the delegate target. Wenn das Argument ein Wert identifiziert eine Delegatinstanz, von dem eine Kopie erstellt ist.If the argument is a value it identifies a delegate instance of which to create a copy.

Wenn die Ausdruck weist den Typ der Kompilierzeit dynamic, Delegate_creation_expression dynamisch gebunden ist (dynamische Bindung), und die folgenden Regeln gelten zur Laufzeit mit dem Laufzeit-Typ, der die Ausdruck.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 gelten die Regeln zum Zeitpunkt der Kompilierung.Otherwise the rules are applied at compile-time.

Die laufzeitverarbeitung der Bindung einer Delegate_creation_expression des Formulars new D(E), wobei D ist eine Delegate_type und E ist ein Ausdruck , umfasst die folgenden Schritte aus: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 Methodengruppe wird der Delegaterstellungsausdruck in die gleiche Weise wie eine Methode gruppenkonvertierung verarbeitet wird (Gruppe Konvertierungen) von E zu D.If E is a method group, the delegate creation expression is processed in the same way as a method group conversion (Method group conversions) from E to D.
  • Wenn E ist eine anonyme Funktion, der Delegaterstellungsausdruck wird verarbeitet, in die gleiche Weise wie eine anonyme Funktion-Konvertierung (anonyme Funktion Konvertierungen) von E zu D.If E is an anonymous function, the delegate creation expression is processed in the same way as an anonymous function conversion (Anonymous function conversions) from E to D.
  • Wenn E ist ein Wert, E kompatibel sein muss (delegieren Deklarationen) mit D, und das Ergebnis ist ein Verweis auf einen neu erstellten Delegaten vom Typ D , verweist auf den gleichen Aufruf als Liste E.If E is a value, E must be compatible (Delegate declarations) with D, and the result is a reference to a newly created delegate of type D that refers to the same invocation list as E. Wenn E ist nicht kompatibel mit D, ein Fehler während der Kompilierung auftritt.If E is not compatible with D, a compile-time error occurs.

Die Verarbeitung zur Laufzeit eine Delegate_creation_expression des Formulars new D(E), wobei D ist eine Delegate_type und E ist ein Ausdruck , umfasst die folgenden Schritte aus: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 Methodengruppe wird der Delegaterstellungsausdruck wird als eine Methode gruppenkonvertierung ausgewertet (Gruppe Konvertierungen) von E zu D.If E is a method group, the delegate creation expression is evaluated as a method group conversion (Method group conversions) from E to D.
  • Wenn E ist eine anonyme Funktion, die delegaterstellung wird ausgewertet, wie eine anonyme Funktion Konvertierung von E zu D (anonyme Funktion Konvertierungen).If E is an anonymous function, the delegate creation is evaluated as an anonymous function conversion from E to D (Anonymous function conversions).
  • Wenn E ist ein Wert, der eine Delegate_type:If E is a value of a delegate_type:
    • E wird ausgewertet.E is evaluated. Wenn diese Evaluierungsversion auf eine Ausnahme auslöst, werden keine weiteren Schritte ausgeführt.If this evaluation causes an exception, no further steps are executed.
    • Wenn der Wert des E ist null, System.NullReferenceException wird ausgelöst, und keine weiteren Schritte ausgeführt werden.If the value of E is null, a System.NullReferenceException is thrown and no further steps are executed.
    • Eine neue Instanz des Delegattyps D zugeordnet ist.A new instance of the delegate type D is allocated. Wenn nicht genügend Arbeitsspeicher verfügbar, um die neue Instanz einer System.OutOfMemoryException wird ausgelöst, und keine weiteren Schritte ausgeführt werden.If there is not enough memory available to allocate the new instance, a System.OutOfMemoryException is thrown and no further steps are executed.
    • Die neue Delegatinstanz wird mit der gleichen Aufrufliste als die Delegatinstanz, die vom initialisiert E.The new delegate instance is initialized with the same invocation list as the delegate instance given by E.

Die Aufrufliste eines Delegaten wird bestimmt, wenn der Delegat instanziiert wird, und klicken Sie dann für die gesamte Lebensdauer des Delegaten unverändert bleibt.The invocation list of a delegate is determined when the delegate is instantiated and then remains constant for the entire lifetime of the delegate. Das heißt, ist es nicht möglich, die Ziel um aufrufbare Entitäten eines Delegaten zu ändern, nachdem es 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 von einem anderen entfernt wird (delegieren Deklarationen), dazu, dass ein neuer Delegat; keine bestehende Delegat hat seinen Inhalt 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, Indexer, benutzerdefinierten Operator, Instanzenkonstruktor, Destruktor oder 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, wenn ein Delegat erstellt wird aus einer Methodengruppe, die Liste der formalen Parameter und Rückgabetyp des Delegaten bestimmen, welche der überladenen Methoden auswählen.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;
    }
}

die A.f Feld wird initialisiert, indem ein Delegat, der auf den zweiten verweist Square Methode, da diese Methode genau mit der Liste formaler Parameter und Rückgabetyp ü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. Haben Sie die zweite Square -Methode nicht vorhanden war, ein Fehler während der Kompilierung würde aufgetreten.Had the second Square method not been present, a compile-time error would have occurred.

Anonyme Erstellung ObjektausdrückeAnonymous object creation expressions

Ein Anonymous_object_creation_expression wird verwendet, um ein Objekt eines anonymen Typs zu erstellen.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 namenloses Klassentyp, der direkt 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 von der anonymer Objektinitialisierer, die zum Erstellen einer Instanz des Typs abgeleitet wird.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. Insbesondere ein anonymer Objektinitialisierer des FormularsSpecifically, an anonymous object initializer of the form

new { p1 = e1, p2 = e2, ..., pn = en }

deklariert einen anonymen Typ des Formularsdeclares 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() { ... }
}

in dem jede Tx ist der Typ des der entsprechende Ausdruck ex.where each Tx is the type of the corresponding expression ex. Der Ausdruck verwendet eine Member_declarator muss einen Typ haben.The expression used in a member_declarator must have a type. Daher wird ein Fehler während der Kompilierung für einen Ausdruck in einem Member_declarator Null oder eine anonyme Funktion 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 Fehler während der Kompilierung für den Ausdruck zu einen unsicheren Typ haben.It is also a compile-time error for the expression to have an unsafe type.

Die Namen eines anonymen Typs und des Parameters, der die Equals Methode werden automatisch vom Compiler generiert und kann nicht in den Programmtext 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 erzeugt zwei anonyme Objektinitialisierer, die eine Sequenz von Eigenschaften den gleichen Namen und die während der Kompilierung-Typen in derselben Reihenfolge angeben, dass Instanzen desselben anonymen Typs.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, weil p1 und p2 desselben anonymen Typs sind.the assignment on the last line is permitted because p1 and p2 are of the same anonymous type.

Die Equals und GetHashcode Methoden von anonymen Typen Überschreiben von geerbten Methoden object, und werden in Form von definiert die Equals und GetHashcode -Eigenschaften, so, dass zwei Instanzen desselben anonymen Typs gleich sind. wenn und nur dann, 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 Member-Declarator kann abgekürzt werden, um einen einfachen Namen (Typrückschluss), Memberzugriff (Überprüfungen zur Kompilierzeit der dynamischen überladungsauflösung), Basiszugriff (Zugriffbasieren) oder ein Null-bedingte Memberzugriff (bedingten Null-Ausdrücke als Projektionsinitialisierer).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 bezeichnet ein Projektion Initialisierer und ist die Kurzform für eine Deklaration und Zuweisung zu einer Eigenschaft mit dem gleichen Namen.This is called a projection initializer and is shorthand for a declaration of and assignment to a property with the same name. Insbesondere memberdeklaratoren der FormenSpecifically, member declarators of the forms

identifier
expr.identifier

sind bzw. genaue Entsprechung der folgenden:are precisely equivalent to the following, respectively:

identifier = identifier
identifier = expr.identifier

Daher in einer Projektion Initialisierung der Bezeichner wählt den Wert und an das Feld oder die Eigenschaft, der 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 Initialisierer für die Projektion, nicht nur ein 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

Die typeof Operator wird zum Abrufen der System.Type Objekt für einen Typ.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 der Typeof_expression besteht aus einem typeof Schlüsselwort, gefolgt von einer in Klammern gesetzte Typ.The first form of typeof_expression consists of a typeof keyword followed by a parenthesized type. Das Ergebnis eines Ausdrucks, der diese Form ist die System.Type -Objekt für den angegebenen Typ.The result of an expression of this form is the System.Type object for the indicated type. Es gibt nur ein System.Type Objekt für jeden angegebenen Typ.There is only one System.Type object for any given type. Dies bedeutet, dass für einen Typ T, typeof(T) == typeof(T) ist immer "true".This means that for a type T, typeof(T) == typeof(T) is always true. Die Typ nicht dynamic.The type cannot be dynamic.

Die zweite Form der Typeof_expression besteht aus einem typeof Schlüsselwort, gefolgt von einer in Klammern gesetzte Unbound_type_name.The second form of typeof_expression consists of a typeof keyword followed by a parenthesized unbound_type_name. Ein Unbound_type_name ähnelt sehr einer Type_name (Namespace und Typnamen) mit dem Unterschied, dass ein Unbound_type_name enthält Generic_dimension_specifiers, in denen eine Type_name enthält Type_argument_lists.An unbound_type_name is very similar to a type_name (Namespace and type names) except that an unbound_type_name contains generic_dimension_specifiers where a type_name contains type_argument_lists. Wenn der Operand des eine Typeof_expression ist eine Folge von Token, das die Grammatiken beider erfüllt Unbound_type_name und Type_name, es nämlich Wenn enthält weder ein Generic_dimension_specifier noch ein Type_argument_list, die Abfolge der Token gilt ein Type_name.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 des einen Unbound_type_name wird wie folgt bestimmt:The meaning of an unbound_type_name is determined as follows:

  • Konvertieren Sie die Sequenz von Token, die eine Type_name durch Ersetzen jedes Generic_dimension_specifier mit einem Type_argument_list müssen die gleiche Anzahl von Kommas und die Schlüsselwort object während jedes Type_argument.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 keyword object as each type_argument.
  • Bewerten Sie die resultierende Type_name, und ignoriert alle Einschränkungen für Typparameter.Evaluate the resulting type_name, while ignoring all type parameter constraints.
  • Die Unbound_type_name aufgelöst, die für den ungebundenen generischen Typ, der den resultierenden konstruierten Typ zugeordnet wird (gebunden und Typen von nicht gebundenen).The unbound_type_name resolves to the unbound generic type associated with the resulting constructed type (Bound and unbound types).

Das Ergebnis der Typeof_expression ist die System.Type -Objekt für generische Typ der resultierenden aufgehoben werden.The result of the typeof_expression is the System.Type object for the resulting unbound generic type.

Die dritte Form der Typeof_expression besteht aus einem typeof Schlüsselwort, gefolgt von einer in Klammern gesetzte void Schlüsselwort.The third form of typeof_expression consists of a typeof keyword followed by a parenthesized void keyword. Das Ergebnis eines Ausdrucks, der diese Form ist die System.Type -Objekt, 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 Typobjekt, das von zurückgegebene typeof(void) unterscheidet sich von das Typobjekt für den beliebigen Typs zurückgegeben.The type object returned by typeof(void) is distinct from the type object returned for any type. Dieses besondere Art-Objekt ist nützlich in Klassenbibliotheken, mit denen Reflektion für Methoden in der Sprache, in dem diese Methoden haben eine Methode zur Darstellung des Rückgabetyp einer Methode, einschließlich der void-Methoden, mit einer Instanz von möchten 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.

Die typeof -Operator kann für einen Typparameter verwendet werden.The typeof operator can be used on a type parameter. Das Ergebnis ist die System.Type -Objekt für den Laufzeittyp, der dem Typparameter gebunden war.The result is the System.Type object for the run-time type that was bound to the type parameter. Die typeof Operator kann auch auf einen konstruierten Typ oder einen ungebundenen generischen Typ verwendet werden (gebunden und Typen von nicht gebundenen).The typeof operator can also be used on a constructed type or an unbound generic type (Bound and unbound types). Die System.Type Objekt für ein ungebundener generischer Typ ist nicht identisch mit der System.Type Objekt des Instanztyps.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 also immer ein geschlossener konstruierter Typ zur Laufzeit die System.Type Objekt abhängig ist für die Laufzeit-Typargumente verwendet werden, während die ungebundenen generischen Typs 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.

Im 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 aufweisen.Note that int and System.Int32 are the same type.

Beachten Sie, dass das Ergebnis des typeof(X<>) hängt nicht das Typargument, aber das Ergebnis des typeof(X<T>) ist.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 und unchecked Operatoren werden verwendet, um zu steuern die Kontext der überlaufprüfung für arithmetische Operationen für ganzzahlige Typen und Konvertierungen.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 ')'
    ;

Die checked -Operator wertet den enthaltenen Ausdruck in einem überprüften Kontext und die unchecked -Operator wertet die enthaltenen Ausdruck in einem ungeprüften Kontext.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 einer Parenthesized_expression (Ausdrücke in Klammern), außer dass der enthaltene Ausdruck in der angegebenen Kontext der überlaufprüfung 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.

Kontext der überlaufprüfung kann auch über gesteuert werden die checked und unchecked Anweisungen (die checked und unchecked Anweisungen).The overflow checking context can also be controlled through the checked and unchecked statements (The checked and unchecked statements).

Die folgenden Vorgänge werden von hergestellt, indem Kontext der überlaufprüfung beeinflusst die checked und unchecked Operatoren und Anweisungen:The following operations are affected by the overflow checking context established by the checked and unchecked operators and statements:

Wenn eine der oben genannten Vorgänge erzeugen kann ein Ergebnis, das ist zu groß, um die Darstellung in den Zieltyp, der den Kontext, in dem der Vorgang ausgeführt Steuerelemente ist, des resultierenden Verhaltens: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, wenn der Vorgang ein konstanter Ausdruck ist (Konstante Ausdrücke), ein Fehler während der Kompilierung auftritt.In a checked context, if the operation is a constant expression (Constant expressions), a compile-time error occurs. Wenn der Vorgang zur Laufzeit, ausgeführt wird, andernfalls eine System.OverflowException ausgelöst.Otherwise, when the operation is performed at run-time, a System.OverflowException is thrown.
  • In einer unchecked Kontext ist das Ergebnis abgeschnitten, indem alle höherwertigen Bits, die nicht in den Zieltyp passen verworfen.In an unchecked 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 (Expressions, die zur Laufzeit ausgewertet werden), die von einer nicht eingeschlossen sind checked oder unchecked Operatoren oder -Anweisungen, wird der Kontext der standardmäßigen überlaufprüfung unchecked , wenn die externen (z. B. Compiler Faktoren Switches und Konfiguration der ausführungsumgebung) rufen Sie für checked Auswertung.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 (Expressions, die zum Zeitpunkt der Kompilierung vollständig ausgewertet werden können), ist der Standard-überlaufprüfung-Kontext immer checked.For constant expressions (expressions that can be fully evaluated at compile-time), the default overflow checking context is always checked. Es sei denn, Sie befindet sich ein konstanter Ausdruck explizit in ein unchecked Kontext Überläufe, die auftreten, während der Kompilierung Auswertung des Ausdrucks immer Fehler während der Kompilierung.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 betroffen von checked oder unchecked Kontexte, in dem 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
    }
}

keine Kompilierungsfehler werden 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 die F -Methode löst eine System.OverflowException, und die G Methodenrückgabe-727379968 (die unteren 32 Bits des Ergebnisses wird außerhalb des gültigen Bereichs).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 von der Standard-überlaufprüfung-Kontext für die Kompilierung, aber es ist entweder dasselbe 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
    }
}

Beim Auswerten der Konstanten Ausdrücke in auftretenden F und H verursachen Kompilierzeitfehler gemeldet werden, da die Ausdrücke, in ausgewertet werden einem checked Kontext.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 es sich bei der Auswertung des konstanten Ausdrucks in G, aber da die Auswertung in erfolgt einem unchecked Kontext, der Überlauf wird 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 und unchecked Operatoren wirken sich nur auf der überlaufprüfung Kontext für diese Vorgänge, die textlich innerhalb der "("und")" Token.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 Auswirkungen auf die Funktionsmember, die aufgerufen werden, als Ergebnis der Auswertung des Ausdrucks enthalten.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 wirkt sich nicht auf die Auswertung von x * y in Multiply, sodass x * y wird in der Standardeinstellung überlaufprüfung-Kontext 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.

Die unchecked Operator eignet sich, beim Schreiben von Konstanten der ganzzahligen Typen mit Vorzeichen in hexadezimaler Schreibweise.The unchecked operator is convenient when writing constants of the signed integral types in hexadecimal notation. Zum Beispiel:For example:

class Test
{
    public const int AllBits = unchecked((int)0xFFFFFFFF);

    public const int HighBit = unchecked((int)0x80000000);
}

Sowohl der oben genannten hexadezimalen Konstanten sind vom Typ uint.Both of the hexadecimal constants above are of type uint. Da sind die Konstanten außerhalb der int liegen, ohne die unchecked Operator, die Umwandlungen in int Fehler während der Kompilierung erzeugt.Because the constants are outside the int range, without the unchecked operator, the casts to int would produce compile-time errors.

Die checked und unchecked Operatoren und Anweisungen ermöglichen es Programmierern, um bestimmte Aspekte der einige numerischen Berechnungen zu steuern.The checked and unchecked operators and statements allow programmers to control certain aspects of some numeric calculations. Das Verhalten einiger numerischen Operatoren hängt jedoch von ihrer Operanden des Bereichsoperators-Datentypen.However, the behavior of some numeric operators depends on their operands' data types. Z. B. immer Multiplikation von zwei Dezimalstellen löst eine Ausnahme bei einem Überlauf sogar innerhalb einer explizit unchecked zu erstellen.For example, multiplying two decimals always results in an exception on overflow even within an explicitly unchecked construct. Auf ähnliche Weise Multiplizieren zweier gleitet nie Ergebnisse zu einer Ausnahme bei einem Überlauf sogar innerhalb einer explizit checked zu erstellen.Similarly, multiplying two floats never results in an exception on overflow even within an explicitly checked construct. Andere Operatoren sind außerdem nicht betroffen, durch den Modus der Überprüfung, ob der Standard- oder explizit.In addition, other operators are never affected by the mode of checking, whether default or explicit.

Ausdrücke mit StandardwertDefault value expressions

Ein Standardwertausdruck verwendet, um den Standardwert abzurufen (Standardwerte) eines Typs.A default value expression is used to obtain the default value (Default values) of a type. Ein Standardwertausdruck wird normalerweise für Typparameter verwendet werden, da nicht bekannt sein kann, wenn der Typparameter einen 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. (Keine Konvertierung vorhanden ist, aus der null Zeichenfolgenliteral auf einen Typparameter, wenn der Typparameter bekannt ist, dass ein Verweistyp sein.)(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 die Typ in einem Default_value_expression wertet zur Laufzeit in einen Verweistyp, der das Ergebnis ist null auf 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 die Typ in eine Default_value_expression wertet zur Laufzeit in einen Werttyp, der das Ergebnis ist der Value_typedes default-Wert (Standard Konstruktoren).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 ist ein Verweistyp oder ein Typparameter, der bekannt ist, dass ein Verweistyp sein (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). Darüber hinaus eine Default_value_expression ist ein konstanter Ausdruck, wenn der Typ eine der folgenden Werttypen: sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, bool, oder ein 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 verwendet, um den Namen des eine Programmentität als eine Konstante Zeichenfolge abzurufen.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
    ;

Grammatisch gesehen die Named_entity Operand ist immer ein Ausdruck.Grammatically speaking, the named_entity operand is always an expression. Da nameof ist kein reserviertes Schlüsselwort, ein Nameof-Ausdruck ist immer mit einem Aufruf der der einfache Name syntaktisch mehrdeutig 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 einer Namenssuche (einfache Namen) mit dem Namen nameof erfolgreich ist, wird der Ausdruck als behandelt eine Invocation_expression – unabhängig davon, ob der Aufruf ist Rechtlich.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 ist es eine Nameof_expression.Otherwise it is a nameof_expression.

Die Bedeutung von der Named_entity von eine Nameof_expression ändert sich die Bedeutung des Zertifikats als ein Ausdruck, also entweder als eine Simple_name, Base_access oder 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. Jedoch, in dem die Suche in beschrieben einfache Namen und Memberzugriff führt zu einem Fehler, da ein Instanzmember in einem statischen Kontext gefunden wurde ein Nameof_expressionkeine derartigen Fehler erzeugt.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 ist ein Fehler während der Kompilierung für eine Named_entity Festlegen einer Methodengruppe haben eine Type_argument_list.It is a compile-time error for a named_entity designating a method group to have a type_argument_list. Es ist ein Kompilierzeitfehler für eine Named_entity_target der Typ dynamic.It is a compile time error for a named_entity_target to have the type dynamic.

Ein Nameof_expression ist ein konstanter Ausdruck des Typs string, und hat keine Auswirkungen zur Laufzeit.A nameof_expression is a constant expression of type string, and has no effect at runtime. Insbesondere die Named_entity wird nicht ausgewertet, und wird ignoriert, für die Zwecke der Untersuchung der Zuweisung (allgemeinen 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, der die Named_entity vor dem letzten optionalen Type_argument_list, transformierten auf folgende Weise:Its value is the last identifier of the named_entity before the optional final type_argument_list, transformed in the following way:

  • Das Präfix "@", wenn verwendet, wird entfernt.The prefix "@", if used, is removed.
  • Jede Unicode_escape_sequence wird umgewandelt in das entsprechende Unicode-Zeichen.Each unicode_escape_sequence is transformed into its corresponding Unicode character.
  • Alle Formatting_characters werden entfernt.Any formatting_characters are removed.

Hierbei handelt es sich um die gleichen Transformationen angewendet Bezeichner beim Testen der Gleichheit zwischen Bezeichner.These are the same transformations applied in Identifiers when testing equality between identifiers.

TODO: BeispieleTODO: examples

Anonyme Methode AusdrückeAnonymous method expressions

Ein Anonymous_method_expression ist eines der zwei Möglichkeiten, eine anonyme Funktion definieren.An anonymous_method_expression is one of two ways of defining an anonymous function. Diese werden weiter beschrieben anonyme Funktionsausdrücke.These are further described in Anonymous function expressions.

Unäre OperatorenUnary operators

Die ?, +, -, !, ~, ++, --, umgewandelt, und await Operatoren werden als die Unäroperatoren 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 ein Unary_expression weist den Typ der Kompilierzeit dynamic, dynamisch gebunden ist (dynamische Bindung).If the operand of a unary_expression has the compile-time type dynamic, it is dynamically bound (Dynamic binding). In diesem Fall geben Sie die während der Kompilierung von der Unary_expression ist dynamic, und die unten beschriebene Lösung wird zur Laufzeit mit der Run-Time-Typ 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-bedingten operatorNull-conditional operator

Der nullbedingungsoperator gilt Operanden eine Liste der Vorgänge nur, wenn dieser Operand ungleich Null ist.The null-conditional operator applies a list of operations to its operand only if that operand is non-null. Das Ergebnis der Anwendung des Operators ist andernfalls 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? ')'
    ;

Memberzugriff und Element-Zugriffsvorgänge (der selbst bedingten Null-sein können) als auch aufrufen, kann die Liste der Vorgänge enthalten.The list of operations can include member access and element access operations (which may themselves be null-conditional), as well as invocation.

Beispiel: der Ausdruck a.b?[0]?.c() ist eine Null_conditional_expression mit einer Primary_expression a.b und Null_conditional_operations ?[0] (bedingte Null-Elementzugriff), ?.c (bedingte Null-Memberzugriff) 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).

Für eine Null_conditional_expression E mit einem Primary_expression Permöglichen E0 des Ausdrucks durch entfernen das vorangestellte textlichabgerufenwerden?von jedem der Null_conditional_operations von E , die über eines verfügen.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. Im Prinzip E0 ist der Ausdruck, der ausgewertet wird, wenn keines der null-Überprüfungen durch dargestellt die ?s finde einen null.Conceptually, E0 is the expression that will be evaluated if none of the null checks represented by the ?s do find a null.

Darüber hinaus können E1 des Ausdrucks durch Entfernen Sie die führende textlich abgerufen werden ? aus nur die zuerst die Null_conditional_operations in E.Also, let E1 be the expression obtained by textually removing the leading ? from just the first of the null_conditional_operations in E. Kann dies zu einem primären Ausdruck (wenn gab es nur eine ?) oder einem anderen Null_conditional_expression.This may lead to a primary-expression (if there was just one ?) or to another null_conditional_expression.

Z. B. wenn E ist der Ausdruck a.b?[0]?.c(), klicken Sie 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 wird dann als nichts, klassifiziert 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 zu bestimmen, die Bedeutung der E:E0 and E1 are used to determine the meaning of E:

  • Wenn E tritt ein, wenn eine Statement_expression die Bedeutung der E ist identisch mit der AnweisungIf E occurs as a statement_expression the meaning of E is the same as the statement

    if ((object)P != null) E1;
    

    mit dem Unterschied, dass P nur einmal ausgewertet wird.except that P is evaluated only once.

  • Andernfalls gilt: Wenn E0 wird klassifiziert als "nothing" ein Fehler während der Kompilierung auftritt.Otherwise, if E0 is classified as nothing a compile-time error occurs.

  • Andernfalls können T0 den Typ der E0.Otherwise, let T0 be the type of E0.

    • Wenn T0 ist ein Typparameter, die ein Verweistyp oder ein NULL-Werte werden tritt ein Fehler während der Kompilierung nicht bekannt ist.If T0 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 ist ein NULL-Werte, und klicken Sie dann auf den Typ des E ist T0?, und die Bedeutung der E ist identisch mitIf T0 is a non-nullable value type, then the type of E is T0?, and the meaning of E is the same as

      ((object)P == null) ? (T0?)null : E1
      

      mit dem Unterschied, dass P wird nur einmal ausgewertet.except that P is evaluated only once.

    • Andernfalls ist des Typs von E T0, und die Bedeutung von E ist identisch mitOtherwise the type of E is T0, and the meaning of E is the same as

      ((object)P == null) ? null : E1
      

      mit dem Unterschied, dass P wird nur einmal ausgewertet.except that P is evaluated only once.

Wenn E1 ist selbst ein Null_conditional_expression, klicken Sie dann diese Regeln werden angewendet, in diesem Fall die Tests für die Schachtelung null bis keine weiteren ?des, und der Ausdruck wurde reduziert ganz nach unten auf dem primären Ausdruck 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.

Z. B. wenn der Ausdruck a.b?[0]?.c() tritt ein, wenn eine Anweisung-Ausdruck, wie die Anweisung:For example, if the expression a.b?[0]?.c() occurs as a statement-expression, as in the statement:

a.b?[0]?.c();

die Bedeutung ist äquivalent zu:its meaning is equivalent to:

if (a.b != null) a.b[0]?.c();

Dies entspricht erneut dem:which again is equivalent to:

if (a.b != null) if (a.b[0] != null) a.b[0].c();

Mit dem Unterschied, dass 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 tritt auf, in dem sein Wert, wie in verwendet wird: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 Aufrufs kein Typ NULL-Werte ist, entspricht die Bedeutung: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 dem Unterschied, dass 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 ProjektionsinitialisiererNull-conditional expressions as projection initializers

Ein Null-bedingten Ausdruck ist nur zulässig, wie eine Member_declarator in einer Anonymous_object_creation_expression (anonyme Erstellung Objektausdrücke) Wenn Es endet mit ein (optional auch nullbedingte) Memberzugriff.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. Grammatisch, kann diese Anforderung 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 Member_declarator in anonyme Erstellung Objektausdrücke dann schließt 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 AnweisungsausdrückeNull-conditional expressions as statement expressions

Ein Null-bedingten Ausdruck ist nur zulässig, als eine Statement_expression (ausdrucksanweisungen) Wenn sie mit einem Aufruf beendet wird.A null-conditional expression is only allowed as a statement_expression (Expression statements) if it ends with an invocation. Grammatisch, kann diese Anforderung 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 Statement_expression in ausdrucksanweisungen dann schließt 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

Für einen Vorgang des Formulars +x, Auflösen der Überladung unäroperator (unäroperator überladungsauflösung) wird angewendet, um einen bestimmten Operator-Implementierung auswä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 der Parametertyp des ausgewählten Operator konvertiert, und der Typ des Ergebnisses 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 die einzelnen 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 MinusoperatorUnary minus operator

Für einen Vorgang des Formulars -x, Auflösen der Überladung unäroperator (unäroperator überladungsauflösung) wird angewendet, um einen bestimmten Operator-Implementierung auswä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 der Parametertyp des ausgewählten Operator konvertiert, und der Typ des Ergebnisses 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 Negationsoperatoren sind:The predefined negation operators are:

  • Ganze Zahl Negation:Integer negation:

    int operator -(int x);
    long operator -(long x);
    

    Das Ergebnis wird durch das Subtrahieren berechnet x 0 (null).The result is computed by subtracting x from zero. Wenn der Wert des x ist die kleinste darstellbare Wert des Typs Operand (-2 ^ 31 für int oder-2 ^ 63 für long), klicken Sie dann die mathematische Negation des x ist nicht in den Operandentyp dargestellt werden kann.If the value of x is the smallest representable value of the operand type (-2^31 for int or -2^63 for long), then the mathematical negation of x is not representable within the operand type. Wenn dies in erfolgt eine checked Kontext eine System.OverflowException ausgelöst; wenn es erfolgt eine unchecked Kontext das Ergebnis ist der Wert des Operanden und der Überlauf wird nicht gemeldet.If this occurs within a checked context, a System.OverflowException is thrown; if it occurs within an unchecked context, the result is the value of the operand and the overflow is not reported.

    Wenn der Operand der Negationsoperator vom Typ uint, es ist in den Typ konvertiert long, und der Typ des Ergebnisses ist long.If the operand of the negation operator is of type uint, it is converted to type long, and the type of the result is long. Eine Ausnahme ist die Regel, die int Wert von – 2147483648 (-2 ^ 31) als ein Ganzzahlliteral im Dezimalformat geschrieben werden (Integer-Literale).An exception is the rule that permits the int value -2147483648 (-2^31) to be written as a decimal integer literal (Integer literals).

    Wenn der Operand der Negationsoperator vom Typ ulong, ein Fehler während der Kompilierung auftritt.If the operand of the negation operator is of type ulong, a compile-time error occurs. Eine Ausnahme ist die Regel, die long Wert-9223372036854775808 (-2 ^ 63) als ein Ganzzahlliteral im Dezimalformat geschrieben werden (Integer-Literale).An exception is the rule that permits the long value -9223372036854775808 (-2^63) to be written as a decimal integer literal (Integer literals).

  • Gleitkomma Negation:Floating-point negation:

    float operator -(float x);
    double operator -(double x);
    

    Das Ergebnis ist der Wert des x mit umgekehrtem Vorzeichen.The result is the value of x with its sign inverted. Wenn x NaN ist, ist das Ergebnis ist ebenfalls NaN.If x is NaN, the result is also NaN.

  • Decimal Negation:Decimal negation:

    decimal operator -(decimal x);
    

    Das Ergebnis wird durch das Subtrahieren berechnet x 0 (null).The result is computed by subtracting x from zero. Decimal Negation ist äquivalent zur Verwendung der unäre Minusoperator des Typs System.Decimal.Decimal negation is equivalent to using the unary minus operator of type System.Decimal.

Logischer NegationsoperatorLogical negation operator

Für einen Vorgang des Formulars !x, Auflösen der Überladung unäroperator (unäroperator überladungsauflösung) wird angewendet, um einen bestimmten Operator-Implementierung auswä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 der Parametertyp des ausgewählten Operator konvertiert, und der Typ des Ergebnisses 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. Nur eine vordefinierte Logischer Negationsoperator vorhanden ist:Only one predefined logical negation operator exists:

bool operator !(bool x);

Dieser Operator wird die logische Negation des Operanden berechnet: Wenn der Operand ist true, das Ergebnis ist false.This operator computes the logical negation of the operand: If the operand is true, the result is false. Wenn der Operand ist false, das Ergebnis ist true.If the operand is false, the result is true.

Bitweiser KomplementoperatorBitwise complement operator

Für einen Vorgang des Formulars ~x, Auflösen der Überladung unäroperator (unäroperator überladungsauflösung) wird angewendet, um einen bestimmten Operator-Implementierung auswä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 der Parametertyp des ausgewählten Operator konvertiert, und der Typ des Ergebnisses 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 bitweiser Komplementoperatoren 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 die einzelnen Operatoren, ist das Ergebnis des Vorgangs das bitweise Komplement des x.For each of these operators, the result of the operation is the bitwise complement of x.

Jeder Enumerationstyp E implizit bietet die folgenden bitweiser Komplementoperator:Every enumeration type E implicitly provides the following bitwise complement operator:

E operator ~(E x);

Das Ergebnis der Auswertung ~x, wobei x ist ein Ausdruck eines Enumerationstyps E mit einem zugrunde liegenden Typ U, entspricht genau dem Auswerten von (E)(~(U)x), außer dass die Konvertierung in E ist als immer ausgeführt. sofern es sich um ein unchecked Kontext (checked und 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 Dekrement Operation muss ein Ausdruck, der als eine Variable, einen Eigenschaftenzugriff oder Indexzugriff klassifiziert sein.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 des gleichen Typs als Operand.The result of the operation is a value of the same type as the operand.

Wenn der Operand eines Präfixes erhöhen oder dekrementvorgang ist eine Eigenschaft oder Zugriffs auf Indexer, Eigenschaft oder des Indexers benötigen Sie Folgendes ein get und set Accessor.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 Fehler während der Bindung.If this is not the case, a binding-time error occurs.

Unäroperator der überladungsauflösung (unäroperator überladungsauflösung) wird angewendet, um einen bestimmten Operator-Implementierung auswählen.Unary operator overload resolution (Unary operator overload resolution) is applied to select a specific operator implementation. Vordefinierte ++ und -- Operatoren vorhanden, für die folgenden Typen: sbyte, byte, short, ushort, int, uint, long, ulong, char , float, double, decimal, und alle Enumerationstypen.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 zurückgegeben, den von den Operanden und den vordefinierten 1 hinzugefügt erzeugten Wert -- Operatoren geben einen Wert durch Subtrahieren der Operand 1 zurück.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. In einem checked Kontext, wenn das Ergebnis dieser Addition oder Subtraktion außerhalb des Bereichs des Ergebnistyps ist und der Ergebnistyp ein ganzzahliger Typ oder ein Enumerationstyp ist, eine System.OverflowException 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 Verarbeitung zur Laufzeit eine "Präfix"-Inkrementoperator oder dekrementvorgang des Formulars ++x oder --x umfasst die folgenden Schritte aus:The run-time processing of a prefix increment or decrement operation of the form ++x or --x consists of the following steps:

  • Wenn x wird als Variable klassifiziert:If x is classified as a variable:
    • x wird ausgewertet, um die Variable zu erstellen.x is evaluated to produce the variable.
    • Der ausgewählte Operator wird aufgerufen, mit dem Wert des x als Argument.The selected operator is invoked with the value of x as its argument.
    • Der Wert, der vom Operator zurückgegebenen befindet sich in den Speicherort, durch die Auswertung von x.The value returned by the operator is stored in the location given by the evaluation of x.
    • Der Wert, der vom Operator zurückgegeben wird das Ergebnis des Vorgangs.The value returned by the operator becomes the result of the operation.
  • Wenn x wird als eine Eigenschaft oder der Indexer Zugriff klassifiziert:If x is classified as a property or indexer access:
    • Der Instanzausdruck (Wenn x ist nicht static) und die Argumentliste (Wenn x Indexzugriff ist) zugeordneten x werden ausgewertet, und die Ergebnisse werden in der nachfolgenden verwendet get und set Accessor-Aufrufe.The instance expression (if x is not static) and the argument list (if x is an indexer access) associated with x are evaluated, and the results are used in the subsequent get and set accessor invocations.
    • Die get Accessor x aufgerufen wird.The get accessor of x is invoked.
    • Der ausgewählte Operator wird aufgerufen, mit den Rückgabewert von der get Accessor als Argument.The selected operator is invoked with the value returned by the get accessor as its argument.
    • Die set Accessor x wird aufgerufen, mit dem Wert, der zurückgegeben wird, durch den Operator als seine value Argument.The set accessor of x is invoked with the value returned by the operator as its value argument.
    • Der Wert, der vom Operator zurückgegeben wird das Ergebnis des Vorgangs.The value returned by the operator becomes the result of the operation.

Die ++ und -- Operatoren unterstützt auch Postfix Notation (Postfix-Inkrement und Dekrement-Operatoren).The ++ and -- operators also support postfix notation (Postfix increment and decrement operators). In der Regel das Ergebnis des x++ oder x-- ist der Wert des x vor dem Vorgang, während das Ergebnis des ++x oder --x ist der Wert des x nach Abschluss des Vorgangs.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 beiden Fällen x selbst hat den gleichen Wert nach Abschluss des Vorgangs.In either case, x itself has the same value after the operation.

Ein operator++ oder operator-- Implementierung kann mithilfe der Präfix oder Postfix-Notation aufgerufen werden.An operator++ or operator-- implementation can be invoked using either postfix or prefix notation. Es ist nicht möglich, separate 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 angegebenen Typ zu konvertieren.A cast_expression is used to explicitly convert an expression to a given type.

cast_expression
    : '(' type ')' unary_expression
    ;

Ein Cast_expression des Formulars (T)E, wobei T ist eine Typ und E ist eine Unary_expression, führt eine explizite Konvertierung (explizite Konvertierungen) des Werts der E eingeben 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 vorhanden ist E zu T, tritt ein Fehler während der Bindung.If no explicit conversion exists from E to T, a binding-time error occurs. Andernfalls ist das Ergebnis der durch die explizite Konvertierung erzeugte Wert.Otherwise, the result is the value produced by the explicit conversion. Das Ergebnis wird immer als Wert klassifiziert, wenn E steht für eine Variable.The result is always classified as a value, even if E denotes a variable.

Die Grammatik für eine Cast_expression führt zu einer bestimmten syntaktischen Mehrdeutigkeiten.The grammar for a cast_expression leads to certain syntactic ambiguities. Beispielsweise der Ausdruck (x)-y entweder als interpretiert werden konnte eine Cast_expression (eine Umwandlung von -y eingeben x) oder als ein Additive_expression in Kombination mit einer Parenthesized_expression (die den Wert berechnet 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).

Auflösen Cast_expression Mehrdeutigkeiten, die folgende Regel vorhanden ist: Eine Sequenz einer oder mehreren tokens (Leerraum) eingeschlossen in Klammern wird als Anfang betrachtet eine Cast_expression nur dann, wenn mindestens eine der folgenden erfüllt sind:To resolve cast_expression ambiguities, the following rule exists: A sequence of one or more tokens (White space) enclosed in parentheses is considered the start of a cast_expression only if at least one of the following are true:

  • Die Sequenz von Token ist richtig Grammatik für eine Typ, aber nicht für eine Ausdruck.The sequence of tokens is correct grammar for a type, but not for an expression.
  • Die Sequenz von Token ist richtig Grammatik für eine Typ, und das Token direkt nach der schließenden Klammer des Tokens "~", das Token "!", das Token "(", wird eine Bezeichner (Unicode-Escape-Zeichensequenzen), ein literal (Literale), oder ein beliebiges Schlüsselwort(Schlüsselwörter) mit Ausnahme von as und is.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) except as and is.

Der Begriff "korrekte Grammatik" bedeutet, dass nur, die, die die Folge von Token, die bestimmten grammatische 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 die eigentliche Bedeutung der einzelnen Bezeichner nicht berücksichtigt.It specifically does not consider the actual meaning of any constituent identifiers. Z. B. wenn x und y Bezeichner sind, klicken Sie dann x.y entspricht der korrekten Grammatik für einen Typ, selbst wenn x.y nicht tatsächlich einen Typ anzugeben.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.

Von der Mehrdeutigkeit Regel folgt, dass, wenn x und y Bezeichner sind, (x)y, (x)(y), und (x)(-y) sind Cast_expressions, aber (x)-y nicht, selbst wenn x identifiziert einen Typ.From the disambiguation rule it follows that, if x and y are identifiers, (x)y, (x)(y), and (x)(-y) are cast_expressions, but (x)-y is not, even if x identifies a type. Jedoch wenn x ist ein Schlüsselwort, das einen vordefinierten Typ angibt (wie z. B. int), dann sind alle vier Formen Cast_expressions (da solches Schlüsselwort nicht möglicherweise einen Ausdruck selbst handeln kann).However, if x is a keyword that identifies a predefined type (such as int), then all four forms are cast_expressions (because such a keyword could not possibly be an expression by itself).

Await-AusdrückenAwait expressions

Der Await-Operator wird verwendet, die einschließenden Async-Funktion angehalten, bis zum Abschluss der asynchronen Vorgangs, durch den Operanden dargestellt.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 asynchronen Funktion zulässig (Iteratoren).An await_expression is only allowed in the body of an async function (Iterators). In der nächsten einschließenden Async-Funktion, ein Await_expression kann nicht an diesen Orten auftreten:Within the nearest enclosing async function, an await_expression may not occur in these places:

  • In einer anonymen Funktion für geschachtelte (nicht-Async)Inside a nested (non-async) anonymous function
  • Innerhalb des Blocks, der eine Lock_statementInside the block of a lock_statement
  • In einem unsicheren KontextIn an unsafe context

Beachten Sie, dass ein Await_expression kann nicht in den meisten Stellen im Auftreten einer Query_expression, da die syntaktisch transformiert werden, um nicht-Async-Lambda-Ausdrücke 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 besteht keine syntaktischen Mehrdeutigkeit zwischen await-Ausdrücken und verschiedene Ausdrücke, die im Zusammenhang mit Bezeichnern.There is therefore no syntactic ambiguity between await-expressions and various expressions involving identifiers. Außerhalb von asynchronen Funktionen await fungiert als ein normaler Bezeichner.Outside of async functions, await acts as a normal identifier.

Der Operand ein Await_expression heißt die Aufgabe.The operand of an await_expression is called the task. Es stellt einen asynchronen Vorgang, die möglicherweise oder ist möglicherweise unvollständig zum Zeitpunkt der Await_expression ausgewertet wird.It represents an asynchronous operation that may or may not be complete at the time the await_expression is evaluated. Der Zweck des Await-Operators werden von der einschließenden Funktion für die asynchrone Ausführung anzuhalten, bis die erwartete Aufgabe abgeschlossen ist, und klicken Sie dann ihr 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.

Awaitable-AusdrückeAwaitable expressions

Die Aufgabe, ein Await-Ausdruck ist erforderlich, um werden awaitable.The task of an await expression is required to be awaitable. Ein Ausdruck t ist "awaitable", wenn eine der folgenden enthält:An expression t is awaitable if one of the following holds:

  • t ist vom Kompilierzeittyp dynamict is of compile time type dynamic
  • t verfügt über eine zugegriffen werden kann oder Erweiterungsmethode-Methode wird aufgerufen, GetAwaiter ohne Parameter und keine Typparameter und einen Rückgabetyp A für die alle der folgenden enthalten:t has an accessible instance or extension method called GetAwaiter with no parameters and no type parameters, and a return type A for which all of the following hold:
    • A implementiert die Schnittstelle System.Runtime.CompilerServices.INotifyCompletion (im folgenden genannten INotifyCompletion aus Gründen der Übersichtlichkeit)A implements the interface System.Runtime.CompilerServices.INotifyCompletion (hereafter known as INotifyCompletion for brevity)
    • A verfügt über eine Instanzeigenschaft zugegriffen werden kann, lesbaren IsCompleted des Typs boolA has an accessible, readable instance property IsCompleted of type bool
    • A verfügt über eine zugängliche Instanzmethode Methode GetResult ohne Parameter und keine TypparameterA has an accessible instance method GetResult with no parameters and no type parameters

Der Zweck der GetAwaiter Methode besteht darin, erhalten eine "awaiter" für den Task.The purpose of the GetAwaiter method is to obtain an awaiter for the task. Der Typ A heißt die "awaiter"-Typ für den Ausdruck "await".The type A is called the awaiter type for the await expression.

Der Zweck der IsCompleted Eigenschaft ist, um festzustellen, ob die Aufgabe bereits abgeschlossen ist.The purpose of the IsCompleted property is to determine if the task is already complete. Wenn dies der Fall ist, besteht keine Notwendigkeit, Auswertung anzuhalten.If so, there is no need to suspend evaluation.

Der Zweck der INotifyCompletion.OnCompleted Methode besteht darin, registrieren eine "fortsetzungs" an die Aufgabe, d. h. einen Delegaten (des Typs System.Action), wird aufgerufen, nachdem die Aufgabe abgeschlossen ist.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 des Vorgangs zu erhalten, sobald sie abgeschlossen ist.The purpose of the GetResult method is to obtain the outcome of the task once it is complete. Dieses Ergebnis möglicherweise den erfolgreichen Abschluss, möglicherweise mit einem Ergebniswert, oder es kann sein, eine Ausnahme, indem ausgelöst wird die GetResult Methode.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 des await-AusdrückenClassification of await expressions

Der Ausdruck await t wird die gleiche Weise wie der Ausdruck klassifiziert (t).GetAwaiter().GetResult().The expression await t is classified the same way as the expression (t).GetAwaiter().GetResult(). Daher, wenn der Rückgabetyp der GetResult ist void, Await_expression wird als "nothing" klassifiziert.Thus, if the return type of GetResult is void, the await_expression is classified as nothing. Wenn sie einen nicht-Void-Rückgabetyp verfügt T, Await_expression wird als ein Wert vom Typ klassifiziert T.If it has a non-void return type T, the await_expression is classified as a value of type T.

Runtime-Auswertung von await-AusdrückenRuntime evaluation of await expressions

Zur Laufzeit wird der Ausdruck await t wird wie folgt ausgewertet:At runtime, the expression await t is evaluated as follows:

  • Ein awaiter-Element a erhalten Sie durch die Auswertung des Ausdrucks (t).GetAwaiter().An awaiter a is obtained by evaluating the expression (t).GetAwaiter().
  • Ein bool b erhalten Sie durch die Auswertung des Ausdrucks (a).IsCompleted.A bool b is obtained by evaluating the expression (a).IsCompleted.
  • Wenn b ist false und Auswertung, ob abhängt a implementiert die Schnittstelle System.Runtime.CompilerServices.ICriticalNotifyCompletion (im folgenden genannten ICriticalNotifyCompletion aus Gründen der Übersichtlichkeit).If b is false then evaluation depends on whether a implements the interface System.Runtime.CompilerServices.ICriticalNotifyCompletion (hereafter known as ICriticalNotifyCompletion for brevity). Diese Überprüfung wird durchgeführt, auf die Bindungszeit; zur Laufzeit z. B. wenn a hat den Kompilierzeittyp dynamic, und zum Zeitpunkt der Kompilierung andernfalls.This check is done at binding time; i.e. at runtime if a has the compile time type dynamic, and at compile time otherwise. Lassen Sie r Wiederaufnahmedelegat zu kennzeichnen (Iteratoren):Let r denote the resumption delegate (Iterators):
    • Wenn a implementiert nicht ICriticalNotifyCompletion, klicken Sie dann den Ausdruck (a as (INotifyCompletion)).OnCompleted(r) ausgewertet wird.If a does not implement ICriticalNotifyCompletion, then the expression (a as (INotifyCompletion)).OnCompleted(r) is evaluated.
    • Wenn a implementiert ICriticalNotifyCompletion, klicken Sie dann den Ausdruck (a as (ICriticalNotifyCompletion)).UnsafeOnCompleted(r) ausgewertet wird.If a does implement ICriticalNotifyCompletion, then the expression (a as (ICriticalNotifyCompletion)).UnsafeOnCompleted(r) is evaluated.
    • Auswertung wird angehalten, und die Kontrolle an den aktuellen Aufrufer der Async-Funktion zurückgegeben wird.Evaluation is then suspended, and control is returned to the current caller of the async function.
  • Entweder unmittelbar auf (Wenn b wurde true), oder bei späteren Aufruf der Wiederaufnahmedelegat (Wenn b wurde false), der Ausdruck (a).GetResult() ausgewertet wird.Either immediately after (if b was true), or upon later invocation of the resumption delegate (if b was false), the expression (a).GetResult() is evaluated. Wenn sie einen Wert zurückgibt, 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 mit "nothing".Otherwise the result is nothing.

Ein awaiter-Element-Implementierung der Schnittstellenmethoden INotifyCompletion.OnCompleted und ICriticalNotifyCompletion.UnsafeOnCompleted sollten dazu führen, dass der Delegat r höchstens einmal aufgerufen werden.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 *, /, %, +, und - Operatoren werden die arithmetischen 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 der Kompilierzeit-Typ hat dynamic, und klicken Sie dann der Ausdruck dynamisch gebunden ist (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 den Kompilierzeittyp des Ausdrucks ist dynamic, und die unten beschriebene Lösung wird zur Laufzeit mit dem Laufzeit-Typ, der diese Operanden mit der Kompilierzeittyp 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

Für einen Vorgang des Formulars x * y, binärer Operator der überladungsauflösung (binärer Operator überladungsauflösung) wird angewendet, um einen bestimmten Operator-Implementierung auswä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 Operator konvertiert, und der Typ des Ergebnisses 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.

Der vordefinierte Multiplikationsoperatoren sind unten aufgeführt.The predefined multiplication operators are listed below. Alle Operatoren ermittelt das Produkt der x und y.The operators all compute the product of x and y.

  • 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);
    

    In einer checked Kontext, wenn außerhalb des Bereichs des Ergebnistyps, das Produkt ist eine System.OverflowException ausgelöst.In a checked context, if the product is outside the range of the result type, a System.OverflowException is thrown. In einer unchecked Kontext Überläufe werden nicht gemeldet, und alle signifikanten höherwertigen Bits außerhalb des Bereichs des Ergebnistyps werden verworfen.In an unchecked context, overflows are not reported and any significant high-order bits outside the range of the result type are discarded.

  • Multiplikation mit Gleitkommawerten: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. Die folgende Tabelle enthält die Ergebnisse der alle möglichen Kombinationen von endlichen Werten ungleich NULL, Nullen, unendliche und NaN.The following table lists the results of all possible combinations of nonzero finite values, zeros, infinities, and NaN's. In der Tabelle x und y positive endliche Werten sind.In the table, x and y are positive finite values. z ist das Ergebnis des x * y.z is the result of x * y. Wenn das Ergebnis zu groß für den Zieltyp z unendlich ist.If the result is too large for the destination type, z is infinity. Wenn das Ergebnis für den Zieltyp zu klein ist z ist 0 (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);
    

    Ist der resultierende Wert zu groß, um die Darstellung in der decimal Format eine System.OverflowException ausgelöst.If the resulting value is too large to represent in the decimal format, a System.OverflowException is thrown. Ist der Ergebniswert zu klein, um das Darstellen der decimal Format, das Ergebnis ist 0 (null).If the result value is too small to represent in the decimal format, the result is zero. Die Dezimalstellen des Ergebnisses wird vor der Rundung, ist die Summe aus der Skalierung der beiden Operanden.The scale of the result, before any rounding, is the sum of the scales of the two operands.

    Decimal Multiplikation ist äquivalent zur Verwendung des Multiplikationsoperators des Typs System.Decimal.Decimal multiplication is equivalent to using the multiplication operator of type System.Decimal.

DivisionsoperatorDivision operator

Für einen Vorgang des Formulars x / y, binärer Operator der überladungsauflösung (binärer Operator überladungsauflösung) wird angewendet, um einen bestimmten Operator-Implementierung auswä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 Operator konvertiert, und der Typ des Ergebnisses 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.

Der vordefinierte Divisionsoperatoren sind unten aufgeführt.The predefined division operators are listed below. Alle Operatoren berechnen den Quotienten x und y.The operators all compute the quotient of x and y.

  • Division ganzer Zahlen kommt: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 NULL ist, ist eine System.DivideByZeroException ausgelöst.If the value of the right operand is zero, a System.DivideByZeroException is thrown.

    Die Division rundet das Ergebnis in Richtung 0 (null).The division rounds the result towards zero. Daher ist der Absolute Wert des Ergebnisses wird die größte ganze Zahl möglich, die kleiner oder gleich dem absoluten Wert des Quotienten aus zwei 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 der gleichen Anmeldebenutzeroberfläche und 0 (null) oder negativ, wenn die beiden Operanden entgegengesetzten signiert haben.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 ist int oder long Wert und der Rechte Operand ist -1, einem Überlauf kommt.If the left operand is the smallest representable int or long value and the right operand is -1, an overflow occurs. In einem checked Kontext Dies bewirkt, dass eine System.ArithmeticException (oder eine Unterklasse davon) ausgelöst wird.In a checked context, this causes a System.ArithmeticException (or a subclass thereof) to be thrown. In einer unchecked Kontext es wird durch die Implementierung definiert, ob eine System.ArithmeticException (oder eine Unterklasse davon) wird ausgelöst, oder der Überlauf wird mit den sich ergebenden Wert, der der linke Operand wird nicht gemeldet.In an unchecked context, it is implementation-defined as to whether a System.ArithmeticException (or a subclass thereof) is thrown or the overflow goes unreported with the resulting value being that of the left operand.

  • Gleitkommadivision:Floating-point division:

    float operator /(float x, float y);
    double operator /(double x, double y);
    

    Der Quotient ist gemäß den Regeln der IEEE 754-Arithmetik berechnet.The quotient is computed according to the rules of IEEE 754 arithmetic. Die folgende Tabelle enthält die Ergebnisse der alle möglichen Kombinationen von endlichen Werten ungleich NULL, Nullen, unendliche und NaN.The following table lists the results of all possible combinations of nonzero finite values, zeros, infinities, and NaN's. In der Tabelle x und y positive endliche Werten sind.In the table, x and y are positive finite values. z ist das Ergebnis des x / y.z is the result of x / y. Wenn das Ergebnis zu groß für den Zieltyp z unendlich ist.If the result is too large for the destination type, z is infinity. Wenn das Ergebnis für den Zieltyp zu klein ist z ist 0 (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 NULL ist, ist eine System.DivideByZeroException ausgelöst.If the value of the right operand is zero, a System.DivideByZeroException is thrown. Ist der resultierende Wert zu groß, um die Darstellung in der decimal Format eine System.OverflowException ausgelöst.If the resulting value is too large to represent in the decimal format, a System.OverflowException is thrown. Ist der Ergebniswert zu klein, um das Darstellen der decimal Format, das Ergebnis ist 0 (null).If the result value is too small to represent in the decimal format, the result is zero. Die Dezimalstellen des Ergebnisses ist der kleinste Skala, die ein Ergebnis gleich beibehalten werden das am nächsten darstellbaren decimal-Wert auf "true" mathematische Ergebnis.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.

    Dezimale Division ist äquivalent zur Verwendung des Divisionsoperators des Typs System.Decimal.Decimal division is equivalent to using the division operator of type System.Decimal.

RestoperatorRemainder operator

Für einen Vorgang des Formulars x % y, binärer Operator der überladungsauflösung (binärer Operator überladungsauflösung) wird angewendet, um einen bestimmten Operator-Implementierung auswä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 Operator konvertiert, und der Typ des Ergebnisses 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.

Der vordefinierte restoperatoren sind unten aufgeführt.The predefined remainder operators are listed below. Alle Operatoren berechnen den Rest der Division zwischen x und y.The operators all compute the remainder of the division between x and y.

  • Ganzzahligen 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 des x % y wird durch der Wert erzeugt x - (x / y) * y.The result of x % y is the value produced by x - (x / y) * y. Wenn y ist 0 (null), eine System.DivideByZeroException ausgelöst.If y is zero, a System.DivideByZeroException is thrown.

    Wenn der linke Operand der kleinsten ist int oder long Wert und der Rechte Operand ist -1, System.OverflowException ausgelöst.If the left operand is the smallest int or long value and the right operand is -1, a System.OverflowException is thrown. Ist in keinem Fall x % y löst eine Ausnahme aus, in denen x / y wird keine Ausnahme ausgelöst.In no case does x % y throw an exception where x / y would not throw an exception.

  • Gleitkommarest:Floating-point remainder:

    float operator %(float x, float y);
    double operator %(double x, double y);
    

    Die folgende Tabelle enthält die Ergebnisse der alle möglichen Kombinationen von endlichen Werten ungleich NULL, Nullen, unendliche und NaN.The following table lists the results of all possible combinations of nonzero finite values, zeros, infinities, and NaN's. In der Tabelle x und y positive endliche Werten sind.In the table, x and y are positive finite values. z ist das Ergebnis des x % y und wird berechnet als x - n * y, wobei n ist die größte ganze Zahl mögliche, die kleiner als oder gleich x / y.z is the result of x % y and is computed as x - n * y, where n is the largest possible integer that is less than or equal to x / y. Diese Methode, der Berechnung des Rests ist analog zu, die für ganzzahlige Operanden verwendet, unterscheidet sich jedoch die IEEE 754-Definition (in der n ist eine ganze Zahl, die am nächsten x / y).This method of computing the remainder is analogous to that used for integer operands, but differs from the IEEE 754 definition (in which n is the integer closest to x / y).

    +y+y -y-y +0+0 -0-0 +inf+inf -inf-inf NaNNaN
    +x+x +z+z +z+z NaNNaN NaNNaN wx wx 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
  • Decimal Rest:Decimal remainder:

    decimal operator %(decimal x, decimal y);
    

    Wenn der Wert des rechten Operanden NULL ist, ist eine System.DivideByZeroException ausgelöst.If the value of the right operand is zero, a System.DivideByZeroException is thrown. Die Dezimalstellen des Ergebnisses wird vor der Rundung, ist der jeweils größere der Skalen der beiden Operanden aus, und die Vorzeichen des Ergebnisses ausgeführt, wenn ungleich NULL ist, entspricht der x.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 of x.

    Decimal Rest ist äquivalent zur Verwendung der Restoperator vom Typ System.Decimal.Decimal remainder is equivalent to using the remainder operator of type System.Decimal.

AdditionsoperatorAddition operator

Für einen Vorgang des Formulars x + y, binärer Operator der überladungsauflösung (binärer Operator überladungsauflösung) wird angewendet, um einen bestimmten Operator-Implementierung auswä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 Operator konvertiert, und der Typ des Ergebnisses 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 Additionsoperatoren sind unten aufgeführt.The predefined addition operators are listed below. Für die numerischen Typen und Enumerationstypen berechnen die vordefinierten Additionsoperatoren die Summe der beiden Operanden.For numeric and enumeration types, the predefined addition operators compute the sum of the two operands. Wenn einer oder beide Operanden vom Typzeichenfolge sind, verketten Sie die vordefinierten Additionsoperatoren eine Zeichenfolgendarstellung der Operanden.When one or both operands are of type string, the predefined addition operators concatenate the string representation of the operands.

  • Ganze Zahl hinzufügen: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, wenn die Summe außerhalb des Bereichs des Ergebnistyps, ist eine System.OverflowException ausgelöst.In a checked context, if the sum is outside the range of the result type, a System.OverflowException is thrown. In einer unchecked Kontext Überläufe werden nicht gemeldet, und alle signifikanten höherwertigen Bits außerhalb des Bereichs des Ergebnistyps werden verworfen.In an unchecked context, overflows are not reported and any significant high-order bits outside the range of the result type are discarded.

  • Gleitkommaaddition: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. Die folgende Tabelle enthält die Ergebnisse der alle möglichen Kombinationen von endlichen Werten ungleich NULL, Nullen, unendliche und NaN.The following table lists the results of all possible combinations of nonzero finite values, zeros, infinities, and NaN's. In der Tabelle x und y sind begrenzte Werte ungleich NULL, und z ist das Ergebnis des x + y.In the table, x and y are nonzero finite values, and z is the result of x + y. Wenn x und y dieselbe Größenordnung haben, aber umgekehrte meldet, z plus null ist.If x and y have the same magnitude but opposite signs, z is positive zero. Wenn x + y ist zu groß für den Zieltyp darstellen z unendlich und hat das gleichen Vorzeichen wie x + y.If x + y is too large to represent in the destination type, z is an infinity with the same sign as x + y.

    yy +0+0 -0-0 +inf+inf -inf-inf NaNNaN
    wx zz wx wx +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
  • Dezimalstellen hinzufügen:Decimal addition:

    decimal operator +(decimal x, decimal y);
    

    Ist der resultierende Wert zu groß, um die Darstellung in der decimal Format eine System.OverflowException ausgelöst.If the resulting value is too large to represent in the decimal format, a System.OverflowException is thrown. Die Dezimalstellen des Ergebnisses wird vor der Rundung, ist der jeweils 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.

    Dezimale Addition ist äquivalent zur Verwendung des Addition-Operators vom Typ System.Decimal.Decimal addition is equivalent to using the addition operator of type System.Decimal.

  • Hinzufügen der Enumeration.Enumeration addition. Jeder Enumerationstyp implizit bietet die folgenden vordefinierten Operatoren, in denen E ist der Enumerationstyp und U ist der zugrunde liegenden Typ des E:Every enumeration type implicitly provides the following predefined operators, where E is the enum type, and U is the underlying type of E:

    E operator +(E x, U y);
    E operator +(U x, E y);
    

    Zur Laufzeit diese Operatoren ausgewertet werden, genau wie (E)((U)x + (U)y).At run-time these operators are evaluated exactly as (E)((U)x + (U)y).

  • Verketten von Zeichenfolgen:String concatenation:

    string operator +(string x, string y);
    string operator +(string x, object y);
    string operator +(object x, string y);
    

    Diese Überladungen der Binärdatei + Operator führen eine zeichenfolgenverkettung aus.These overloads of the binary + operator perform string concatenation. Wenn ein Operand vom zeichenfolgenverkettung wird null, eine leere Zeichenfolge ersetzt wird.If an operand of string concatenation is null, an empty string is substituted. Andernfalls jedes Argument keine Zeichenfolge durch Aufrufen der virtuellen in seine Zeichenfolgendarstellung konvertiert ist ToString Methode geerbt vom Typ object.Otherwise, any non-string argument is converted to its string representation by invoking the virtual ToString method inherited from type object. Wenn ToString gibt null, eine leere Zeichenfolge ersetzt wird.If ToString returns null, 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 der Operator für zeichenfolgenverkettungen ist eine Zeichenfolge, die aus der Zeichen des linken Operanden gefolgt von den Zeichen des rechten Operanden. Gibt zurück, der Operator für zeichenfolgenverkettung nie eine null Wert. Ein System.OutOfMemoryException möglicherweise ausgelöst, wenn nicht genügend Arbeitsspeicher verfügbar, um die resultierende Zeichenfolge steht.A System.OutOfMemoryException may be thrown if there is not enough memory available to allocate the resulting string.

  • Delegieren Sie die Kombination aus.Delegate combination. Alle Delegattypen implizit bietet die folgenden vordefinierten Operator, in denen D ist der Delegattyp:Every delegate type implicitly provides the following predefined operator, where D is the delegate type:

    D operator +(D x, D y);
    

    Die Binärdatei + Operator führt Delegatkombination aus, wenn beide Operanden vom Delegattyp sind D.The binary + operator performs delegate combination when both operands are of some delegate type D. (Wenn die Operanden unterschiedliche Delegattypen aufweisen, tritt ein Fehler während der Bindung.) Wenn der erste Operand null, das Ergebnis des Vorgangs ist der Wert des zweiten Operanden (selbst wenn das auch ist null).(If the operands have different delegate types, a binding-time error occurs.) If the first operand is null, the result of the operation is the value of the second operand (even if that is also null). Wenn der zweite Operand ist, andernfalls null, lautet das Ergebnis des Vorgangs der Wert des ersten Operanden.Otherwise, if the second operand is null, then the result of the operation is the value of the first operand. Andernfalls ist das Ergebnis des Vorgangs ein neuer Delegaten Instanz, die, wenn aufgerufen wird, ruft der erste Operand und ruft dann den zweiten Operanden auf.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 Delegatkombination, finden Sie unter Subtraktionsoperator und Delegataufruf.For examples of delegate combination, see Subtraction operator and Delegate invocation. Da System.Delegate ist es sich nicht um ein Delegattyp, operator  + ist nicht definiert.Since System.Delegate is not a delegate type, operator + is not defined for it.

SubtraktionsoperatorSubtraction operator

Für einen Vorgang des Formulars x - y, binärer Operator der überladungsauflösung (binärer Operator überladungsauflösung) wird angewendet, um einen bestimmten Operator-Implementierung auswä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 Operator konvertiert, und der Typ des Ergebnisses 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 Subtraktionsoperatoren sind unten aufgeführt.The predefined subtraction operators are listed below. Die Operatoren, die alle subtrahieren y aus x.The operators all subtract y from x.

  • Ganze Zahl 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);
    

    In einem checked Kontext, wenn außerhalb des Bereichs des Ergebnistyps, der Unterschied ist eine System.OverflowException ausgelöst.In a checked context, if the difference is outside the range of the result type, a System.OverflowException is thrown. In einer unchecked Kontext Überläufe werden nicht gemeldet, und alle signifikanten höherwertigen Bits außerhalb des Bereichs des Ergebnistyps werden verworfen.In an unchecked context, overflows are not reported and any significant high-order bits outside the range of the result type are discarded.

  • Subtraktion von Gleitkommazahlen: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. Die folgende Tabelle enthält die Ergebnisse der alle möglichen Kombinationen von endlichen Werten ungleich NULL, Nullen, unendliche und NaN-Werte.The following table lists the results of all possible combinations of nonzero finite values, zeros, infinities, and NaNs. In der Tabelle x und y sind begrenzte Werte ungleich NULL, und z ist das Ergebnis des x - y.In the table, x and y are nonzero finite values, and z is the result of x - y. Wenn x und y gleich sind, z plus null ist.If x and y are equal, z is positive zero. Wenn x - y ist zu groß für den Zieltyp darstellen z unendlich und hat das gleichen Vorzeichen wie x - y.If x - y is too large to represent in the destination type, z is an infinity with the same sign as x - y.

    yy +0+0 -0-0 +inf+inf -inf-inf NaNNaN
    wx zz wx wx -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);
    

    Ist der resultierende Wert zu groß, um die Darstellung in der decimal Format eine System.OverflowException ausgelöst.If the resulting value is too large to represent in the decimal format, a System.OverflowException is thrown. Die Dezimalstellen des Ergebnisses wird vor der Rundung, ist der jeweils 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.

    Dezimale Subtraktion ist äquivalent zur Verwendung des Subtraktionsoperators des Typs System.Decimal.Decimal subtraction is equivalent to using the subtraction operator of type System.Decimal.

  • Subtraktion der Enumeration.Enumeration subtraction. Jeder Enumerationstyp enthält implizit den folgenden vordefinierten-Operator, in denen E der Enum-Typs ist und U ist der zugrunde liegenden Typ des E:Every enumeration type implicitly provides the following predefined operator, where E is the enum type, and U is the underlying type of E:

    U operator -(E x, E y);
    

    Dieser Operator wird ausgewertet, genau wie (U)((U)x - (U)y).This operator is evaluated exactly as (U)((U)x - (U)y). Das heißt, der Operator berechnet den Unterschied zwischen der Ordinalwerte der x und y, und der Typ des Ergebnisses ist der zugrunde liegende Typ der Enumeration.In other words, the operator computes the difference between the ordinal values of x and y, and the type of the result is the underlying type of the enumeration.

    E operator -(E x, U y);
    

    Dieser Operator wird ausgewertet, genau wie (E)((U)x - y).This operator is evaluated exactly as (E)((U)x - y). Das heißt, subtrahiert der Operator einen Wert aus der zugrunde liegende Typ der Enumeration, dies ergibt den Wert der Enumeration.In other words, the operator subtracts a value from the underlying type of the enumeration, yielding a value of the enumeration.

  • Delegieren Sie zum Entfernen.Delegate removal. Alle Delegattypen implizit bietet die folgenden vordefinierten Operator, in denen D ist der Delegattyp:Every delegate type implicitly provides the following predefined operator, where D is the delegate type:

    D operator -(D x, D y);
    

    Die Binärdatei - Operator führt delegatentfernung aus, wenn beide Operanden vom Delegattyp sind D.The binary - operator performs delegate removal when both operands are of some delegate type D. Wenn die Operanden unterschiedliche Delegattypen haben, tritt ein Fehler während der Bindung.If the operands have different delegate types, a binding-time error occurs. Wenn der erste Operand null, ist das Ergebnis des Vorgangs null.If the first operand is null, the result of the operation is null. Wenn der zweite Operand ist, andernfalls null, lautet das Ergebnis des Vorgangs der Wert des ersten Operanden.Otherwise, if the second operand is null, then the result of the operation is the value of the first operand. Beide Operanden darstellen, andernfalls Aufruflisten (delegieren Deklarationen) ein oder mehrere Einträge, und das Ergebnis ist eine neue Aufrufliste besteht aus den ersten Operanden Liste mit den zweiten Operanden Einträge daraus Diese Liste mit den zweiten Operanden angegeben ist eine ordnungsgemäße zusammenhängenden Unterliste der des 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 Unterliste auf Gleichheit zu bestimmen, werden entsprechende Einträge verglichen, wie für den Delegaten Equality-Operator (delegieren Gleichheitsoperatoren).) Andernfalls ist das Ergebnis den 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. Keiner der Operanden des Bereichsoperators Listen wird im Prozess geändert.Neither of the operands' lists is changed in the process. Wenn der zweite Operand Liste mehrerer Unterlisten zusammenhängende Einträge aus den ersten Operanden übereinstimmt, wird die am weitesten rechts befindlichen übereinstimmende Unterliste zusammenhängende Einträge 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. Wenn die Entfernung in einer leeren Liste führt, wird das Ergebnis ist null.If removal results in an empty list, the result is null. Zum 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 << und >> Operatoren werden verwendet, um wechselnden Bit-Vorgänge ausfü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 vom eine Shift_expression weist den Typ der Kompilierzeit dynamic, und klicken Sie dann der Ausdruck dynamisch gebunden ist (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 den Kompilierzeittyp des Ausdrucks ist dynamic, und die unten beschriebene Lösung wird zur Laufzeit mit dem Laufzeit-Typ, der diese Operanden mit der Kompilierzeittyp 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.

Für einen Vorgang des Formulars x << count oder x >> count, binärer Operator der überladungsauflösung (binärer Operator überladungsauflösung) wird angewendet, um einen bestimmten Operator-Implementierung auswä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 Operator konvertiert, und der Typ des Ergebnisses 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 Schiebeoperators der Typ des ersten Operanden muss immer der Klasse oder Struktur, die die Operatordeklaration enthält, und der Typ des zweiten Operanden muss immer 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.

  • Shift-Left: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);
    

    Die << verschiebt der Operator x um eine Anzahl von Bits nach links berechnet werden, wie unten beschrieben.The << operator shifts x left by a number of bits computed as described below.

    Die höherwertigen Bits außerhalb des Bereichs des Ergebnistyps der x werden verworfen, die verbleibenden Bits nach links verschoben, und die niederwertigen leeren Bitpositionen werden auf 0 (null) festgelegt.The high-order bits outside the range of the result type of x are discarded, the remaining bits are shifted left, and the low-order empty bit positions are set to zero.

  • Verschiebung nach rechts: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);
    

    Die >> verschiebt der Operator x rechts um eine Anzahl von Bits berechnet, wie unten beschrieben.The >> operator shifts x right by a number of bits computed as described below.

    Wenn x ist vom Typ int oder long, die niederwertigen Bits von x werden verworfen, die verbleibenden Bits nach rechts verschoben werden, und die höherwertige leere Bitpositionen werden auf NULL, wenn festgelegt x ist negativ und auf, wenn ein x ist negativ.When x is of type int or long, the low-order bits of x are discarded, the remaining bits are shifted right, and the high-order empty bit positions are set to zero if x is non-negative and set to one if x is negative.

    Wenn x ist vom Typ uint oder ulong, die niederwertigen Bits von x werden verworfen, die verbleibenden Bits werden nach rechts verschoben, und die höherwertige leere Bitpositionen werden auf 0 (null) festgelegt.When x is of type uint or ulong, the low-order bits of x are discarded, the remaining bits are shifted right, and the high-order empty bit positions are set to zero.

Die Anzahl der zu verschiebenden Bits wird in der für die vordefinierten Operatoren wird wie folgt berechnet:For the predefined operators, the number of bits to shift is computed as follows:

  • Wenn der Typ des x ist int oder uint, die Umschaltanzahl durch die niederwertigen fünf Bits des count.When the type of x is int or uint, the shift count is given by the low-order five bits of count. Das heißt, wird die Umschaltanzahl aus berechnet count & 0x1F.In other words, the shift count is computed from count & 0x1F.
  • Wenn der Typ des x ist long oder ulong, die Umschaltanzahl durch die niederwertigen sechs Bits des count.When the type of x is long or ulong, the shift count is given by the low-order six bits of count. Das heißt, wird die Umschaltanzahl aus berechnet count & 0x3F.In other words, the shift count is computed from count & 0x3F.

Ist die UMSCHALT-Rekursionsergebnis 0 (null), die Schiebeoperatoren einfach den Wert des zurückgeben x.If the resulting shift count is zero, the shift operators simply return the value of x.

Verschiebevorgänge nie lösen Überläufe und erzeugen identische Ergebnisse im checked und unchecked Kontexte.Shift operations never cause overflows and produce the same results in checked and unchecked contexts.

Wenn der linke Operand des der >> Operator einen ganzzahligen Typ mit Vorzeichen, der Operator führt eine arithmetische Verschiebung nach rechts in dem der Wert, der das höchstwertige Bit (das signierte Bit) des Operanden weitergegeben wird, das höherwertige leere Bitpositionen.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 der >> Operator ein Integraltyp ohne Vorzeichen, der Operator führt eine logische Verschiebung nach rechts in der höherwertige leere Bitpositionen immer auf 0 (null) festgelegt werden.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. Um den umgekehrten Vorgang aus, die von der Operandentyp abgeleitet auszuführen, können die explizite Umwandlungen verwendet werden.To perform the opposite operation of that inferred from the operand type, explicit casts can be used. Z. B. wenn x ist eine Variable vom Typ int, den Vorgang unchecked((int)((uint)x >> y)) führt eine logische Verschiebung rechts 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 ==, !=, <, >, <=, >=, is und as Operatoren werden als relationalen 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
    ;

Die is Operator finden Sie im der is-Operator und as Operator finden Sie im den Operator.The is operator is described in The is operator and the as operator is described in The as operator.

Die ==, !=, <, >, <= und >= Operatoren sind Vergleichsoperatoren.The ==, !=, <, >, <= and >= operators are comparison operators.

Wenn ein Operand eines Vergleichsoperators der Kompilierzeit-Typ hat dynamic, und klicken Sie dann der Ausdruck dynamisch gebunden ist (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 den Kompilierzeittyp des Ausdrucks ist dynamic, und die unten beschriebene Lösung wird zur Laufzeit mit dem Laufzeit-Typ, der diese Operanden mit der Kompilierzeittyp 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.

Für einen Vorgang des Formulars x Op y, wobei Op ein Vergleichsoperator, Auflösung von funktionsüberladungen (binärer Operator überladungsauflösung) wird angewendet, um einen bestimmten Operator-Implementierung auswä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 Operator konvertiert, und der Typ des Ergebnisses 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 Vergleichsoperatoren werden in den folgenden Abschnitten beschrieben.The predefined comparison operators are described in the following sections. Alle vordefinierten Vergleichsoperatoren zurückgeben ein Ergebnisses vom Typ 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 Wenn x gleich y, false andernfallstrue if x is equal to y, false otherwise
x != y true Wenn x ist nicht gleich y, false andernfallstrue if x is not equal to y, false otherwise
x < y true Wenn x ist kleiner als y, false andernfallstrue if x is less than y, false otherwise
x > y true Wenn x ist größer als y, false andernfallstrue if x is greater than y, false otherwise
x <= y true Wenn x ist kleiner als oder gleich y, false andernfallstrue if x is less than or equal to y, false otherwise
x >= y true Wenn x ist größer als oder gleich y, false andernfallstrue if x is greater than or equal to y, false otherwise

Integer-VergleichsoperatorenInteger comparison operators

Die vordefinierten Integer-Vergleichsoperatoren sind: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);

Die einzelnen Operatoren vergleicht die numerischen Werte der zwei ganzzahlige Operanden und gibt eine bool Wert, der angibt, ob die jeweilige Beziehung ist true oder 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.

Gleitkomma-VergleichsoperatorenFloating-point comparison operators

Die vordefinierten Gleitkomma-Vergleichsoperatoren sind: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 Operatoren vergleichen die Operanden gemäß den Regeln der IEEE 754-standard:The operators compare the operands according to the rules of the IEEE 754 standard:

  • Wenn einer der Operanden NaN ist, wird das Ergebnis ist false für alle Operatoren außer !=, für die das Ergebnis ist true.If either operand is NaN, the result is false for all operators except !=, for which the result is true. Für alle zwei Operanden x != y erzeugt immer das gleiche Ergebnis wie !(x == y).For any two operands, x != y always produces the same result as !(x == y). Wenn einer oder beide Operanden sind jedoch NaN ist, die <, >, <=, und >= Operatoren erzeugen die gleichen Ergebnisse wie die logische Negation des den entgegengesetzten Operator nicht.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. Z. B., wenn entweder der x und y ist NaN, x < y ist false, aber !(x >= y) ist true.For example, if either of x and y is NaN, then x < y is false, but !(x >= y) is true.

  • Wenn keiner der Operanden NaN ist, vergleichen Sie die Operatoren die Werte von zwei Gleitkommazahlen Operanden in Bezug auf die ReihenfolgeWhen 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
    

    wo min und max sind die kleinstmöglichen und größtmöglichen positiven endlichen Werten, die in der angegebenen Gleitkomma-Format dargestellt werden können.where min and max are the smallest and largest positive finite values that can be represented in the given floating-point format. Diese Sortierung wesentliche Auswirkungen sind:Notable effects of this ordering are:

    • Negative und positive Nullen werden als gleich betrachtet.Negative and positive zeros are considered equal.
    • Eine negative Unendlichkeit gilt als kleiner als alle anderen Werte, aber gleich einem anderen minus 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 gleich einem anderen plus unendlich.A positive infinity is considered greater than all other values, but equal to another positive infinity.

Decimal-VergleichsoperatorenDecimal comparison operators

Die vordefinierten decimal Vergleichsoperatoren sind: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);

Die einzelnen Operatoren vergleicht die numerischen Werte der beiden decimal Operanden und gibt eine bool Wert, der angibt, ob die jeweilige Beziehung ist true oder 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 dezimale Vergleich ist äquivalent zur Verwendung des entsprechenden relationalen oder Equality-Operator vom Typ System.Decimal.Each decimal comparison is equivalent to using the corresponding relational or equality operator of type System.Decimal.

Boolesche OperatorenBoolean equality operators

Die vordefinierten booleschen Operatoren sind:The predefined boolean equality operators are:

bool operator ==(bool x, bool y);
bool operator !=(bool x, bool y);

Das Ergebnis des == ist true sowohl x und y sind true oder wenn beide x und y sind false.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 des != ist false sowohl x und y sind true oder wenn beide x und y sind false.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 sind vom Typ bool, != Operator erzeugt das gleiche Ergebnis wie die ^ Operator.When the operands are of type bool, the != operator produces the same result as the ^ operator.

Enumeration-VergleichsoperatorenEnumeration comparison operators

Jeder Enumerationstyp bietet implizit die folgenden vordefinierten Vergleichsoperatoren: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 x op y, wobei x und y sind Ausdrücke eines Enumerationstyps E mit einem zugrunde liegenden Typ U, und op ist eine der folgenden Vergleichsoperatoren, entspricht genau 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). Das heißt, vergleichen die Enumeration-Typ-Vergleichsoperatoren 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.

GleichheitsoperatorenReference type equality operators

Die Gleichheitsoperatoren vordefinierten Typ 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 die beiden Verweise auf Gleichheit oder wertungleichheit zurück.The operators return the result of comparing the two references for equality or non-equality.

Da die vordefinierten Typ Gleichheitsoperatoren Operanden vom Typ akzeptieren object, gelten für alle Typen, die keinen entsprechenden deklarieren operator == und operator != Member.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 ausblenden, alle anwendbaren benutzerdefinierte Operatoren effektiv die Gleichheitsoperatoren vordefinierten Typ.Conversely, any applicable user-defined equality operators effectively hide the predefined reference type equality operators.

Die Gleichheitsoperatoren vordefinierten Typ erfordert einen der folgenden:The predefined reference type equality operators require one of the following:

  • Beide Operanden sind, einen Wert eines Typs, die bekanntermaßen eine Reference_type oder das Literal null.Both operands are a value of a type known to be a reference_type or the literal null. Darüber hinaus eine explizite Konvertierung (explizite Konvertierungen) aus dem Typ der Operanden in den 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.
  • Einer der Operanden ist ein Wert vom Typ T , in denen T ist eine Type_parameter und der andere Operand ist das Literal null.One operand is a value of type T where T is a type_parameter and the other operand is the literal null. Außerdem T verfügt nicht über die werteinschränkung-Typ.Furthermore T does not have the value type constraint.

Wenn eine der folgenden Bedingungen erfüllt sind, tritt ein Fehler während der Bindung.Unless one of these conditions are true, a binding-time error occurs. Wesentliche Auswirkungen auf die diese Regeln sind:Notable implications of these rules are:

  • Es ist ein Fehler während der Bindung, die Gleichheitsoperatoren vordefinierten Typ zu verwenden, um zwei Verweise zu vergleichen, die bekannt sind, zum Zeitpunkt der Bindung unterschiedlich sein.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 Bindung-Time-Typen der Operanden zwei Klassentypen sind z. B. A und B, und wenn weder A noch B von der anderen abgeleitet ist, und es unmöglich, dass die beiden Operanden wäre auf dasselbe Objekt verweisen.For example, if the binding-time types of the operands are two class types A and B, and if neither A nor B derives from the other, then it would be impossible for the two operands to reference the same object. Daher gilt der Vorgang einen Fehler während der Bindung.Thus, the operation is considered a binding-time error.
  • Die vordefinierten Typ Gleichheitsoperatoren lassen nicht Wert Operanden vom Typ zu vergleichende.The predefined reference type equality operators do not permit value type operands to be compared. Es sei denn, eine eigene Operatoren ein Strukturtyp deklariert wird, ist es daher nicht möglich, zum Vergleichen von Werten dieses Strukturtyps.Therefore, unless a struct type declares its own equality operators, it is not possible to compare values of that struct type.
  • Die vordefinierten Typ Gleichheitsoperatoren verursachen nie Boxing-Vorgänge für ihre Operanden sicher auftreten.The predefined reference type equality operators never cause boxing operations to occur for their operands. Es wäre ohne Bedeutung für solche Boxing-Vorgänge ausführen, da Verweise auf das neu zugeordneten geschachtelten Instanzen unbedingt von allen anderen verweisen voneinander 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 vom Typ Parametertyp T im Vergleich zu null, und welche Laufzeit T ein Werttyp ist, ist das Ergebnis des Vergleichs false.If an operand of a type parameter type T is compared to null, and the run-time type of T is a value type, the result of the comparison is false.

Das folgende Beispiel überprüft, ob ein Argument des Typs einer beschränkten Typ-Parameter 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();
        ...
    }
}

Die x == null Konstrukt ist zulässig, obwohl T könnte einen Werttyp darstellen, und das Ergebnis wird lediglich definiert false beim 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.

Für einen Vorgang des Formulars x == y oder x != yggf. alle operator == oder operator != vorhanden ist, handelt es sich bei der überladungsauflösung für Operator (binärer Operator überladungsauflösung) Regeln auswählen, werden Operator anstelle der vordefinierten Gleichheitsoperator.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, wählen Sie die vordefinierten Gleichheitsoperator, indem Sie explizit umwandeln, eine oder beide der Operanden in den Typ 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. Im 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 und t Variablen verweisen auf zwei unterschiedliche string Instanzen, die dieselben Zeichen enthält.The s and t variables refer to two distinct string instances containing the same characters. Der erste Vergleich gibt True da die vordefinierte Zeichenfolge Equality-Operator (Zeichenfolge Gleichheitsoperatoren) wird aktiviert, 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, die alle Ausgabe False , da die vordefinierte Gleichheitsoperator ausgewählt ist, wenn eine oder beide der Operanden des Typs sind 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 genannten Technik nicht für Werttypen von Bedeutung ist.Note that the above technique is not meaningful for value types. Im BeispielThe example

class Test
{
    static void Main() {
        int i = 123;
        int j = 123;
        System.Console.WriteLine((object)i == (object)j);
    }
}

Gibt False geschachtelt, da die Umwandlungen Verweise auf zwei separate Instanzen des erstellen int Werte.outputs False because the casts create references to two separate instances of boxed int values.

Zeichenfolge-GleichheitsoperatorenString equality operators

Die Gleichheitsoperatoren vordefinierte Zeichenfolge 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 Bedingungen zutrifft:Two string values are considered equal when one of the following is true:

  • Beide Werte sind null.Both values are null.
  • Beide Werte sind nicht-Null-Verweise auf String-Instanzen, die dieselbe Länge haben und die identische Zeichen in jeder Position des Zeichens.Both values are non-null references to string instances that have identical lengths and identical characters in each character position.

Die Gleichheitsoperatoren vergleichen Zeichenfolgenwerte anstelle der Zeichenfolge verweisen.The string equality operators compare string values rather than string references. Wenn zwei unterschiedliche Instanzen genaue dieselbe Sequenz von Zeichen enthalten, die Werte der Zeichenfolgen gleich sind, aber die Verweise unterscheiden.When two separate string instances contain the exact same sequence of characters, the values of the strings are equal, but the references are different. Siehe Gleichheitsoperatoren, die Gleichheitsoperatoren können verwendet werden, um Verweise auf Zeichenfolgen anstelle von String-Werten verglichen werden soll.As described in Reference type equality operators, the reference type equality operators can be used to compare string references instead of string values.

Delegieren von GleichheitsoperatorenDelegate equality operators

Alle Delegattypen bietet implizit die folgenden vordefinierten Vergleichsoperatoren: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 wie folgt gelten als gleich:Two delegate instances are considered equal as follows:

  • Wenn eine Delegatinstanz null, sie gleich sind, wenn beide null.If either of the delegate instances is null, they are equal if and only if both are null.
  • Wenn die Delegaten unterschiedliche Laufzeit-Typinformationen, die sie nicht gleich sind haben.If the delegates have different run-time type they are never equal.
  • Wenn beide Delegatinstanzen eine Aufrufliste haben (delegieren Deklarationen), die Instanzen gleich sind, wenn ihre Aufruflisten die gleiche Länge sind, und jeder Eintrag in der Aufrufliste gleich ist (wie unten definiert) mit dem entsprechenden Eintrag in der Reihenfolge, in die andere Aufrufliste.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 Listeneinträgen Aufruf:The following rules govern the equality of invocation list entries:

  • Wenn zwei Aufruf Listeneinträge sowohl auf die gleiche statische finden Sie unter sind Methode und dann 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 beide auf dieselbe nicht statische Methode auf dem gleichen Zielobjekt verweisen (wie durch die Gleichheitsoperatoren definiert) klicken Sie dann 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 Einträge erstellt, bei der Auswertung des semantisch identisch Anonymous_method_expressions oder Lambda_expressionmit den gleichen Satz erfassten äußere Variable (möglicherweise leere) Instanzen sind zulässig (jedoch nicht erforderlich) gleich sind.Invocation list entries produced from evaluation of semantically identical anonymous_method_expressions or lambda_expressions with the same (possibly empty) set of captured outer variable instances are permitted (but not required) to be equal.

Operatoren und nullEquality operators and null

Die == und != Operatoren ermöglichen einer der Operanden ein als Wert für einen nullable-Typ und die andere, werden die null literal, selbst wenn keine vordefinierte oder benutzerdefinierte-Operator (in unlifted oder Formular aufgehoben) 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 von einem der FormateFor an operation of one of the forms

x == null
null == x
x != null
null != x

in denen x ist ein Ausdruck, der einen nullable-Typ, wenn überladungsauflösung für Operator (binärer Operator überladungsauflösung) ein Fehler auftritt, finden Sie einen entsprechenden Operator das Ergebnis wird stattdessen aus berechnet die HasValue Eigenschaft des 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 zwei Formen 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

Die is Operator wird verwendet, um dynamisch zu überprüfen, ob der Laufzeittyp 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 ist ein Ausdruck und T ist ein Typ, ist ein boolescher Wert, der angibt, der Wert, ob E erfolgreich Typ konvertiert werden kann T von einer verweiskonvertierung, einer Boxing Konvertierung oder einer unboxing-Konvertierung.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. Die Operation wird wie folgt ausgewertet, nachdem für alle Typparameter Typargumente ersetzt wurden:The operation is evaluated as follows, after type arguments have been substituted for all type parameters:

  • Wenn E wird eine anonyme Funktion, ein Fehler während der Kompilierung tritt ein,If E is an anonymous function, a compile-time error occurs
  • Wenn E ist eine Methodengruppe oder null Zeichenliteral zurück, wenn der Typ des E ist ein Verweistyp oder einem nullable-Typ und den Wert der E ist null das Ergebnis ist "false".If E is a method group or the null literal, of if the type of E is a reference type or a nullable type and the value of E is null, the result is false.
  • Andernfalls können D darstellen den dynamischen Typ der E wie folgt:Otherwise, let D represent the dynamic type of E as follows:
    • Wenn der Typ des E ist ein Verweistyp, D ist der Run-Time-Typ, der den Instanzverweis von E.If the type of E is a reference type, D is the run-time type of the instance reference by E.
    • Wenn der Typ des E ist ein NULL-Werte zulässt, D ist der zugrunde liegende Typ dieses nullable-Typ.If the type of E is a nullable type, D is the underlying type of that nullable type.
    • Wenn der Typ des E ist ein NULL-Werttyp, D ist der Typ des E.If the type of E is a non-nullable value type, D is the type of E.
  • Das Ergebnis des Vorgangs hängt D und T wie folgt:The result of the operation depends on D and T as follows:
    • Wenn T ein Verweistyp ist das Ergebnis ist "true" Wenn D und T desselben Typs sind, wenn D ist ein Verweistyp und eine implizite verweiskonvertierung von D zu T vorhanden ist, oder wenn D ist ein Werttyp und eine Boxingkonvertierung von D zu T vorhanden ist.If T is a reference type, the result is true if D and T are the same type, if D is a reference type and an implicit reference conversion from D to T exists, or if D is a value type and a boxing conversion from D to T exists.
    • Wenn T ein nullable-Typ ist das Ergebnis ist "true" Wenn D ist der zugrunde liegenden Typ des T.If T is a nullable type, the result is true if D is the underlying type of T.
    • Wenn T ist ein NULL-Werttyp, das Ergebnis ist True, wenn D und T denselben Typ aufweisen.If T is a non-nullable value type, the result is true if D and T are the same type.
    • Das Ergebnis ist, andernfalls "false".Otherwise, the result is false.

Beachten Sie, dass benutzerdefinierte Konvertierungen werden nicht berücksichtigt, indem die is Operator.Note that user defined conversions, are not considered by the is operator.

Den OperatorThe as operator

Die as Operator wird verwendet, um explizit einen Wert in einen angegebenen Referenztyp oder ein nullable-Typ zu konvertieren.The as operator is used to explicitly convert a value to a given reference type or nullable type. Im Gegensatz zu Cast-Ausdruck (Umwandlungsausdrücke), wird die as Operator niemals eine Ausnahme auslöst.Unlike a cast expression (Cast expressions), the as operator never throws an exception. Stattdessen ist die angegebene Konvertierung nicht möglich, die der resultierende Wert ist null.Instead, if the indicated conversion is not possible, the resulting value is null.

In einem Vorgang des Formulars E as T, E muss ein Ausdruck sein und T muss ein Verweistyp, ein Typparameter ein Verweistyp oder einem nullable-Typ bezeichnet.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. Darüber hinaus muss mindestens eine der folgenden "true" sein, oder andernfalls ein Kompilierungsfehler tritt auf:Furthermore, at least one of the following must be true, or otherwise a compile-time error occurs:

Wenn die Kompilierung von eingeben E nicht dynamic, den Vorgang E as T führt zum gleiche 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. Der Compiler zur Optimierung erwarten E as T höchstens einen Typ "dynamic" Überprüfung statt zwei dynamischen Typprüfungen impliziert durch die Erweiterung, die oben genannten ausführen.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 die Kompilierung von eingeben E ist dynamic, anders als bei der Cast-Operator der as Operator ist 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). Aus diesem Grund ist die Erweiterung in diesem Fall ein:Therefore the expansion in this case is:

E is T ? (T)(object)(E) : (T)null

Beachten Sie, dass einige Konvertierungen wie die benutzerdefinierte Konvertierungen nicht zulässig sind die as Operator und stattdessen mithilfe der Cast-Ausdrücke ausgeführt werden soll.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 wird ein Verweistyp sein bezeichnet, da sie die klasseneinschränkung verfügt.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 daher die Verwendung von der as -Operator in H ist nicht zulässig.The type parameter U of H is not however; hence the use of the as operator in H is disallowed.

Logische OperatorenLogical operators

Die &, ^, und | Operatoren werden als die logischen 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 vom ein logischer Operator, der während der Kompilierung-Typ hat dynamic, und klicken Sie dann der Ausdruck dynamisch gebunden ist (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 den Kompilierzeittyp des Ausdrucks ist dynamic, und die unten beschriebene Lösung wird zur Laufzeit mit dem Laufzeit-Typ, der diese Operanden mit der Kompilierzeittyp 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.

Für einen Vorgang des Formulars x op y, wobei op ist eine logische Operatoren, Auflösung von funktionsüberladungen (binärer Operator überladungsauflösung) wird angewendet, um einen bestimmten Operator-Implementierung auswä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 Operator konvertiert, und der Typ des Ergebnisses 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 logische Operatoren werden in den folgenden Abschnitten beschrieben.The predefined logical operators are described in the following sections.

Logische Operatoren für ganze ZahlenInteger logical operators

Die vordefinierten Ganzzahl logischen Operatoren sind: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);

Die & -Operator berechnet das bitweise logische AND der zwei Operanden, die | -Operator berechnet das bitweise logische OR der zwei Operanden, und die ^ -Operator berechnet das bitweise logische XOR OR der beiden 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. Keine Überläufe sind von diesen Vorgängen möglich.No overflows are possible from these operations.

Logische EnumerationsoperatorenEnumeration logical operators

Jeder Enumerationstyp E implizit bietet die folgenden vordefinierten logische Operatoren: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 x op y, wobei x und y sind Ausdrücke eines Enumerationstyps E mit einem zugrunde liegenden Typ U, und op ist einer der logischen Operatoren, entspricht genau 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). Das heißt, führen Sie die logischen Operatoren für die Enumeration einfach die logische Operation mit den zugrunde liegenden Typ, der zwei Operanden.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 sind: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 des x | y ist true Wenn 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 des x ^ y ist true Wenn x ist true und y ist false, oder x ist false und y ist 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 sind vom Typ bool, ^ -Operator berechnet das gleiche Ergebnis wie die != Operator.When the operands are of type bool, the ^ operator computes the same result as the != operator.

Auf NULL festlegbaren booleschen logischen OperatorenNullable boolean logical operators

Der auf NULL festlegbaren booleschen Typ bool? kann drei Werte darstellen true, false, und null, und ist konzeptionell identisch mit den drei Werten-Typ für boolesche Ausdrücke, die in SQL verwendet.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 von den Ergebnissen der & und | Operatoren für bool? Operanden sind konsistent mit der SQL dreiwertige Logik, die folgenden vordefinierten Operatoren werden 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);

Die folgende Tabelle enthält die Ergebnisse dieser Operatoren für den Werten aller Kombinationen von true, false, und 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 && und || Operatoren werden als die bedingten logischen Operatoren bezeichnet.The && and || operators are called the conditional logical operators. Sie werden auch die "verkürzte" logischen 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 && und || Operatoren sind bedingte Versionen der & und | Operatoren:The && and || operators are conditional versions of the & and | operators:

  • Der Vorgang x && y entspricht dem Vorgang x & y, außer dass y nur ausgewertet, wenn x nicht false.The operation x && y corresponds to the operation x & y, except that y is evaluated only if x is not false.
  • Der Vorgang x || y entspricht dem Vorgang x | y, außer dass y nur ausgewertet, wenn x nicht true.The operation x || y corresponds to the operation x | y, except that y is evaluated only if x is not true.

Wenn ein Operand eines bedingten logischen Operators der Kompilierzeit-Typ hat dynamic, und klicken Sie dann der Ausdruck dynamisch gebunden ist (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 den Kompilierzeittyp des Ausdrucks ist dynamic, und die unten beschriebene Lösung wird zur Laufzeit mit dem Laufzeit-Typ, der diese Operanden mit der Kompilierzeittyp 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 Auflösung von funktionsüberladungen verarbeitet (binärer Operator überladungsauflösung), 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. Klicken Sie dannThen,

Es ist nicht möglich, direkt die bedingten logischen Operatoren überladen.It is not possible to directly overload the conditional logical operators. Aber da die bedingten logischen Operatoren in Bezug auf die regulären logischen Operatoren ausgewertet werden, gelten Überladungen der regulären logischen Operatoren mit gewissen Einschränkungen auch Überladungen der bedingten logischen Operatoren als.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 in bedingten logischen Operatoren eine benutzerdefinierte.This is described further in User-defined conditional logical operators.

Boolesche bedingte logische OperatorenBoolean conditional logical operators

Wenn die Operanden des && oder || sind vom Typ bool, oder wenn die Operanden sind Typen, die keinem zutreffenden definieren operator & oder operator |, aber implizite Konvertierungen in definieren bool, der Vorgang ist 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 ausgewertet, x ? y : false.The operation x && y is evaluated as x ? y : false. Das heißt, x wird zuerst ausgewertet und in den Typ konvertiert bool.In other words, x is first evaluated and converted to type bool. Wenn danach x ist true, y ausgewertet und in den Typ konvertiert bool, und dies ist das Ergebnis des Vorgangs.Then, if x is true, y is evaluated and converted to type bool, and this becomes the result of the operation. Andernfalls ist das Ergebnis des Vorgangs false.Otherwise, the result of the operation is false.
  • Der Vorgang x || y wird als ausgewertet, x ? true : y.The operation x || y is evaluated as x ? true : y. Das heißt, x wird zuerst ausgewertet und in den Typ konvertiert bool.In other words, x is first evaluated and converted to type bool. Wenn danach x ist true, ist das Ergebnis des Vorgangs true.Then, if x is true, the result of the operation is true. Andernfalls y ausgewertet und in den Typ konvertiert bool, und dies ist das Ergebnis des Vorgangs.Otherwise, y is evaluated and converted to type bool, and this becomes the result of the operation.

Eine benutzerdefinierte bedingten logischen OperatorenUser-defined conditional logical operators

Wenn die Operanden des && oder || sind Typen, die dem zutreffenden deklarieren Sie eine benutzerdefinierte operator & oder operator |, die folgenden beiden muss "true", in denen T ist der Typ, in dem der ausgewählte Operator deklariert wird: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 den Typ jedes Parameters, der den ausgewählten Operator muss T.The return type and the type of each parameter of the selected operator must be T. Das heißt, muss der Operator die logische compute AND oder die logische OR der beiden Operanden vom Typ T, und ein Ergebnis vom Typ zurückgeben müssen T.In other words, the operator must compute the logical AND or the logical OR of two operands of type T, and must return a result of type T.
  • T Deklarationen von darf operator true und operator false.T must contain declarations of operator true and operator false.

Ein Fehler während der Bindung tritt auf, wenn der Anforderungen nicht erfüllt wird.A binding-time error occurs if either of these requirements is not satisfied. Andernfalls die && oder || Operation wird ausgewertet, durch die Kombination der benutzerdefinierte operator true oder operator false mit den ausgewählten benutzerdefinierten Operator: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 ausgewertet, T.false(x) ? x : T.&(x, y), wobei T.false(x) ist ein Aufruf von der operator false in deklarierten T, und T.&(x, y) ist ein Aufruf des ausgewählten operator &.The operation x && y is evaluated as T.false(x) ? x : T.&(x, y), where T.false(x) is an invocation of the operator false declared in T, and T.&(x, y) is an invocation of the selected operator &. Das heißt, x wird zuerst ausgewertet und operator false wird aufgerufen, auf das Ergebnis aus, um zu bestimmen, ob x ist definitiv "false".In other words, x is first evaluated and operator false is invoked on the result to determine if x is definitely false. Wenn danach x ist definitiv "false" werden, das Ergebnis des Vorgangs ist der Wert, der zuvor für berechneten x.Then, if x is definitely false, the result of the operation is the value previously computed for x. Andernfalls y ausgewertet wird, und der ausgewählten operator & wird aufgerufen, für die zuvor für x und den berechneten Wert für y um das Ergebnis des Vorgangs zu erstellen.Otherwise, y is evaluated, and the selected operator & is invoked on the value previously computed for x and the value computed for y to produce the result of the operation.
  • Der Vorgang x || y wird als ausgewertet, T.true(x) ? x : T.|(x, y), wobei T.true(x) ist ein Aufruf von der operator true in deklarierten T, und T.|(x,y) ist ein Aufruf des ausgewählten operator|.The operation x || y is evaluated as T.true(x) ? x : T.|(x, y), where T.true(x) is an invocation of the operator true declared in T, and T.|(x,y) is an invocation of the selected operator|. Das heißt, x wird zuerst ausgewertet und operator true wird aufgerufen, auf das Ergebnis aus, um zu bestimmen, ob x auf jeden Fall ist.In other words, x is first evaluated and operator true is invoked on the result to determine if x is definitely true. Wenn danach x auf jeden Fall true ist, das Ergebnis des Vorgangs ist der Wert, der zuvor für berechneten x.Then, if x is definitely true, the result of the operation is the value previously computed for x. Andernfalls y ausgewertet wird, und der ausgewählten operator | wird aufgerufen, für die zuvor für x und den berechneten Wert für y um das Ergebnis des Vorgangs zu erstellen.Otherwise, y is evaluated, and the selected operator | is invoked on the value previously computed for x and the value computed for y to produce the result of the operation.

In einer dieser Vorgänge, die der angegebene Ausdruck x ist nur einmal ausgewertet, und der angegebene Ausdruck y wird nicht ausgewertet oder genau einmal 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 implementiert operator true und operator false, finden Sie unter Datenbank booleschen Typ.For an example of a type that implements operator true and operator false, see Database boolean type.

Die null-SammeloperatorThe null coalescing operator

Die ?? Operator, der null-Sammeloperator aufgerufen wird.The ?? operator is called the null coalescing operator.

null_coalescing_expression
    : conditional_or_expression
    | conditional_or_expression '??' null_coalescing_expression
    ;

Ein null-sammelausdrücken im Format a ?? b erfordert a vom einen Nullable-Typ oder Verweis-Typ sein.A null coalescing expression of the form a ?? b requires a to be of a nullable type or reference type. Wenn a ungleich Null sind, ist das Ergebnis des a ?? b ist aist, andernfalls ist das Ergebnis b.If a is non-null, the result of a ?? b is a; otherwise, the result is b. Der Vorgang ermittelt b nur, wenn a ist null.The operation evaluates b only if a is null.

Die null-Sammeloperator ist rechtsassoziativ, was bedeutet, dass Vorgänge, die von rechts nach links gruppiert werden.The null coalescing operator is right-associative, meaning that operations are grouped from right to left. Z. B. ein Ausdruck der Form a ?? b ?? c wird als ausgewertet, a ?? (b ?? c).For example, an expression of the form a ?? b ?? c is evaluated as a ?? (b ?? c). Im allgemeinen Begriffe, einen Ausdruck der Form E1 ?? E2 ?? ... ?? En gibt den ersten Operanden, der ist ungleich Null verwendet werden soll, 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 von der impliziten Konvertierungen auf die Operanden verfügbar sind.The type of the expression a ?? b depends on which implicit conversions are available on the operands. In der Reihenfolge ihrer Priorität, die den Typ des a ?? b ist A0, A, oder B, wobei A ist der Typ des a (vorausgesetzt, dass a verfügt über einen Typ), B ist der Typ des b () vorausgesetzt, dass b verfügt über einen Typ), und A0 ist der zugrunde liegenden Typ des A Wenn A ist ein NULL-Werte zulässt, oder 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 ist und keinen nullable-Typ oder ein Verweistyp, ein Fehler während der Kompilierung auftritt.If A exists and is not a nullable type or a reference type, a compile-time error occurs.
  • Wenn b ein dynamisches Ausdrucks, ist der Ergebnistyp ist dynamic.If b is a dynamic expression, the result type is dynamic. Zur Laufzeit a wird zuerst ausgewertet.At run-time, a is first evaluated. Wenn a ist nicht null, a wird konvertiert in einen dynamischen, und dies ist das Ergebnis.If a is not null, a is converted to dynamic, and this becomes the result. Andernfalls b ausgewertet wird, und dies ist das Ergebnis.Otherwise, b is evaluated, and this becomes the result.
  • Andernfalls gilt: Wenn A vorhanden ist und ein nullable-Typ und eine implizite Konvertierung vorhanden ist aus b zu A0, der Ergebnistyp ist A0.Otherwise, if A exists and is a nullable type and an implicit conversion exists from b to A0, the result type is A0. Zur Laufzeit a wird zuerst ausgewertet.At run-time, a is first evaluated. Wenn a ist nicht null, a wird entpackt, um geben A0, und dies ist das Ergebnis.If a is not null, a is unwrapped to type A0, and this becomes the result. Andernfalls b ausgewertet und in den Typ konvertiert A0, und dies ist das Ergebnis.Otherwise, b is evaluated and converted to type A0, and this becomes the result.
  • Andernfalls gilt: Wenn A vorhanden ist und eine implizite Konvertierung von b zu A, ist der Ergebnistyp A.Otherwise, if A exists and an implicit conversion exists from b to A, the result type is A. Zur Laufzeit a wird zuerst ausgewertet.At run-time, a is first evaluated. Wenn a ist nicht null, a wird das Ergebnis.If a is not null, a becomes the result. Andernfalls b ausgewertet und in den Typ konvertiert A, und dies ist das Ergebnis.Otherwise, b is evaluated and converted to type A, and this becomes the result.
  • Andernfalls gilt: Wenn b weist einen Typ B und eine implizite Konvertierung von a zu B, der Ergebnistyp ist B.Otherwise, if b has a type B and an implicit conversion exists from a to B, the result type is B. Zur Laufzeit a wird zuerst ausgewertet.At run-time, a is first evaluated. Wenn a ist nicht null, a wird entpackt, um geben A0 (Wenn A vorhanden ist, und NULL-Werte zulässt) und in den Typ konvertiert B, und dies ist das Ergebnis.If a is not null, a is unwrapped to type A0 (if A exists and is nullable) and converted to type B, and this becomes the result. Andernfalls b ausgewertet wird und das Ergebnis.Otherwise, b is evaluated and becomes the result.
  • Andernfalls a und b nicht kompatibel sind und ein Fehler während der Kompilierung auftritt.Otherwise, a and b are incompatible, and a compile-time error occurs.

Bedingter OperatorConditional operator

Die ?: Operator wird den bedingten Operator aufgerufen.The ?: operator is called the conditional operator. Sie wird gelegentlich auch den ternären Operator aufgerufen.It is at times also called the ternary operator.

conditional_expression
    : null_coalescing_expression
    | null_coalescing_expression '?' expression ':' expression
    ;

Ein bedingter Ausdruck der Form b ? x : y zuerst wertet die Bedingung b.A conditional expression of the form b ? x : y first evaluates the condition b. Wenn danach b ist true, x ausgewertet wird und das Ergebnis des Vorgangs.Then, if b is true, x is evaluated and becomes the result of the operation. Andernfalls y ausgewertet wird und das Ergebnis des Vorgangs.Otherwise, y is evaluated and becomes the result of the operation. Ein bedingter Ausdruck ist nie ergibt, beide x und y.A conditional expression never evaluates both x and y.

Der bedingte Operator ist rechtsassoziativ, was bedeutet, dass Vorgänge, die von rechts nach links gruppiert werden.The conditional operator is right-associative, meaning that operations are grouped from right to left. Z. B. ein Ausdruck der Form a ? b : c ? d : e wird 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 der ?: Operator muss ein Ausdruck, der implizit in konvertiert werden kann bool, oder ein Ausdruck, der ein Typ, 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 nicht erfüllt ist, tritt ein Fehler während der Kompilierung.If neither of these requirements is satisfied, a compile-time error occurs.

Die zweiten und dritten Operanden, x und y, der die ?: -Operators bestimmen den Typ des bedingten Ausdrucks.The second and third operands, x and y, of the ?: operator control the type of the conditional expression.

  • Wenn x weist den Typ X und y weist den Typ Y dannIf x has type X and y has type Y then
    • Wenn eine implizite Konvertierung (implizite Konvertierungen) vorhanden ist, von X zu Y, jedoch nicht von Y zu X, klicken Sie dann Y ist der Typ des bedingten Ausdrucks.If an implicit conversion (Implicit conversions) exists from X to Y, but not from Y to X, then Y is the type of the conditional expression.
    • Wenn eine implizite Konvertierung (implizite Konvertierungen) vorhanden ist, von Y zu X, jedoch nicht von X zu Y, klicken Sie dann X ist der Typ des bedingten Ausdrucks.If an implicit conversion (Implicit conversions) exists from Y to X, but not from X to Y, then X is the type of the conditional expression.
    • Andernfalls keine Ausdruckstyp bestimmt werden kann, und ein Fehler während der Kompilierung auftritt.Otherwise, no expression type can be determined, and a compile-time error occurs.
  • Wenn nur eine der x und y verfügt über einen Typ und beide x und y, der implizit in diesen Typ konvertiert werden, dann wird der Typ des bedingten Ausdrucks.If only one of x and y has a type, and both x and y, of are implicitly convertible to that type, then that is the type of the conditional expression.
  • Andernfalls keine Ausdruckstyp bestimmt werden kann, und ein Fehler während der Kompilierung auftritt.Otherwise, no expression type can be determined, and a compile-time error occurs.

Die Run-Time-Verarbeitung von einem bedingten Ausdruck der Form b ? x : y umfasst die folgenden Schritte aus:The run-time processing of a conditional expression of the form b ? x : y consists of the following steps:

  • Zuerst b ausgewertet wird, und die bool Wert b bestimmt wird:First, b is evaluated, and the bool value of b is determined:
    • Wenn eine implizite Konvertierung vom Typ des b zu bool vorhanden ist, und klicken Sie dann diese implizite Konvertierung ausgeführt wird, erzeugt eine bool Wert.If an implicit conversion from the type of b to bool exists, then this implicit conversion is performed to produce a bool value.
    • Andernfalls die operator true definiert durch den Typ der b wird aufgerufen, um zu erzeugen eine bool Wert.Otherwise, the operator true defined by the type of b is invoked to produce a bool value.
  • Wenn die bool ist der Wert, der vom vorherigen Schritt generiert true, klicken Sie dann x ausgewertet und konvertiert Sie in den Typ des bedingten Ausdrucks, und dies ist das Ergebnis des bedingten Ausdrucks.If the bool value produced by the step above is true, then x is evaluated and converted to the type of the conditional expression, and this becomes the result of the conditional expression.
  • Andernfalls y ausgewertet und konvertiert Sie in den Typ des bedingten Ausdrucks, und dies ist 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.

Anonyme FunktionsausdrückeAnonymous function expressions

Ein anonyme Funktion ist ein Ausdruck, der eine "inline" Methodendefinition 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, aber in einen kompatiblen Delegat- oder ausdrucksbaumtyp konvertierbar ist.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 Funktion Konvertierung hängt von den Zieltyp der Konvertierung ab: Wenn sie einen Delegattyp ist, ergibt die Konvertierung eines Delegatwerts verweisen auf die Methode, die die anonyme Funktion definiert.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 sie einen Typ für die Ausdrucksbaumstruktur ist, ergibt sich die Konvertierung in eine Ausdrucksbaumstruktur, die die Struktur der Methode, wie eine 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 Verlaufsgründen es gibt zwei syntaktische Varianten von anonymen Funktionen, d. h. Lambda_expressions und Anonymous_method_expressions.For historical reasons there are two syntactic flavors of anonymous functions, namely lambda_expressions and anonymous_method_expressions. Fast alle Gründen Lambda_expressions sind präziser und ausdrucksbasierte als Anonymous_method_expressions, die in der Sprache für die Abwärtskompatibilität Kompatibilität bleiben.For almost all purposes, lambda_expressions are more concise and expressive than anonymous_method_expressions, 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 asynchrone Funktion und die in beschriebenen Regeln folgt Iteratoren.An anonymous function with the async modifier is an async function and follows the rules described in Iterators.

Die Parameter einer anonymen Funktion in Form einer Lambda_expression können explizit oder implizit typisiert werden.The parameters of an anonymous function in the form of a lambda_expression can be explicitly or implicitly typed. In der Parameterliste eine explizit typisierte ist 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, die Typen der Parameter aus dem Kontext, in dem die anonyme Funktion tritt auf, abgeleitet werden – insbesondere, wenn die anonyme Funktion konvertiert wird auf einen kompatiblen Delegaten-Typ oder den Typ für die Ausdrucksbaumstruktur, den bereitstellt die Parametertypen (anonyme Funktion Konvertierungen).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 einzigen, implizit typisierte Parameter können die Klammern aus der Liste ausgelassen werden.In an anonymous function with a single, implicitly typed parameter, the parentheses may be omitted from the parameter list. Das heißt, eine anonyme Funktion des FormularsIn other words, an anonymous function of the form

( param ) => expr

kann abgekürzt werden zucan be abbreviated to

param => expr

Der Parameterliste eine anonyme 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 sein.If given, the parameters must be explicitly typed. Wenn nicht der Fall, die anonyme Funktion konvertiert werden kann, um einen Delegaten mit einer der Parameter ist aufgelistet, die nicht enthalten out Parameter.If not, the anonymous function is convertible to a delegate with any parameter list not containing out parameters.

Ein Block Text einer anonymen Funktion erreichbar ist (Endpunkte und Erreichbarkeit), wenn die anonyme Funktion in einer nicht erreichbar-Anweisung auftritt.A block body of an anonymous function is reachable (End points and reachability) unless the anonymous function occurs inside an unreachable statement.

Einige Beispiele für anonyme Funktionen führen Sie die folgenden: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 der Lambda_expressions und Anonymous_method_expressions ist gleichermaßen, weisen die folgenden Punkte:The behavior of lambda_expressions and anonymous_method_expressions is the same except for the following points:

  • Anonymous_method_expressions zulassen die Parameterliste komplett weggelassen werden, stellt die Konvertierung zu einer Liste von Wertparameter Delegattypen.anonymous_method_expressions permit the parameter list to be omitted entirely, yielding convertibility to delegate types of any list of value parameters.
  • Lambda_expressions zulassen, Parametertypen, die nicht angegeben werden, und abgeleitet werden, während Anonymous_method_expressionerfordern Parametertypen explizit angegeben werden.lambda_expressions permit parameter types to be omitted and inferred whereas anonymous_method_expressions require parameter types to be explicitly stated.
  • Der Text der ein Lambda_expression kann ein Ausdruck oder einen Anweisungsblock sein werden, während der Text der ein Anonymous_method_expression muss ein Anweisungsblock sein.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_expressions haben Konvertierungen in kompatibel ausdrucksbaumstrukturtypen (ausdrucksbaumstrukturtypen).Only lambda_expressions have conversions to compatible expression tree types (Expression tree types).

Anonyme FunktionssignaturenAnonymous function signatures

Der optionale Anonymous_function_signature eine anonyme Funktion definiert, die Namen und optional auch 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 Bereich der Parameter für die anonyme Funktion ist die Anonymous_function_body.The scope of the parameters of the anonymous function is the anonymous_function_body. (Bereiche) zusammen mit der Parameterliste (sofern vorhanden) bildet die anonyme-Methode-Body einen Deklarationsabschnitt (Deklarationen).(Scopes) Together with the parameter list (if given) the anonymous-method-body constitutes a declaration space (Declarations). Es ist daher ein Fehler während der Kompilierung für den Namen eines Parameters, der anonyme Funktion, die mit dem Namen des eine lokale Variable, die lokale Konstante oder die Parameter, deren Bereich umfasst, die Anonymous_method_expression oder Lambda_ Ausdruck.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 verfügt über eine Explicit_anonymous_function_signature, und klicken Sie dann der Satz von kompatible Delegattypen und ausdrucksbaumstrukturtypen auf diejenigen beschränkt ist, die den gleichen Parametertypen und -Modifizierern 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 Group Konvertierungen (Gruppe Konvertierungen), Kontravarianz von Parametertypen der anonymen Funktion wird 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 kein Anonymous_function_signature, und klicken Sie dann der Satz von kompatible Delegattypen und ausdrucksbaumstrukturtypen auf diejenigen beschränkt ist, die keine out Parameter.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 darf keine Attribute oder ein Parameterarray.Note that an anonymous_function_signature cannot include attributes or a parameter array. Dennoch eine Anonymous_function_signature kann mit einem Delegattyp, dessen Parameterliste ein Parameterarray enthält, kompatibel sein.Nevertheless, an anonymous_function_signature may be compatible with a delegate type whose parameter list contains a parameter array.

Beachten Sie auch diese Konvertierung in einen Typ für die Ausdrucksbaumstruktur, selbst wenn kompatibel, kann immer noch ausfallen, zum Zeitpunkt der Kompilierung (ausdrucksbaumstrukturtypen).Note also that conversion to an expression tree type, even if compatible, may still fail at compile-time (Expression tree types).

Anonyme funktionsrümpfeAnonymous function bodies

Der Text (Ausdruck oder Block) eine anonyme 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 Parameter, die in der Signatur angegeben im Text zur Verfügung.If the anonymous function includes a signature, the parameters specified in the signature are available in the body. Wenn die anonyme Funktion keine Signatur hat es konvertiert werden kann einem Delegattyp bzw. den Ausdruckstyp Parametern (anonyme Funktion Konvertierungen), aber der Parameter können nicht zugegriffen werden, im Text.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 von ref oder out Parameter angegeben wird, in der Signatur (sofern vorhanden) der nächsten einschließenden anonyme Funktion wird ein Fehler während der Kompilierung für den Text, den Zugriff auf eine ref oder out Parameter.Except for ref or out parameters specified in the signature (if any) of the nearest enclosing anonymous function, it is a compile-time error for the body to access a ref or out parameter.
  • Wenn der Typ des this ist ein Strukturtyp, es ist ein Fehler während der Kompilierung für den Text, den Zugriff auf this.When the type of this is a struct type, it is a compile-time error for the body to access this. Dies ist "true" gibt an, ob der Zugriff explizit ist (wie in this.x) oder implizit (wie in x , in denen x ist ein Instanzmember der Struktur).This is true whether the access is explicit (as in this.x) or implicit (as in x where x is an instance member of the struct). Diese Regel verhindert, dass dieser Zugriff einfach und wirkt sich nicht, ob die Suche nach Membern in ein Member der Struktur ergibt.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ßeren Variablen) der anonymen Funktion.The body has access to the outer variables (Outer variables) of the anonymous function. Zugriff auf eine äußere Variable verweist auf die Instanz der Variablen, die zu dem Zeitpunkt aktiv ist die Lambda_expression oder Anonymous_method_expression ausgewertet wird (Auswertung anonyme Funktionsausdrücke).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 Fehler während der Kompilierung für den Textkörper enthält ein goto -Anweisung break -Anweisung oder continue -Anweisung ein, deren Ziel außerhalb des Texts oder im Text einer enthaltenen anonymen Funktion.It is a compile-time error for the body to contain a goto statement, break statement, or continue statement whose target is outside the body or within the body of a contained anonymous function.
  • Ein return -Anweisung im Hauptteil übergibt die Kontrolle über einen Aufruf der nächsten einschließenden anonyme Funktion, die nicht aus der einschließenden Funktionsmember.A return statement in the body returns control from an invocation of the nearest enclosing anonymous function, not from the enclosing function member. Ein im angegebenen Ausdruck eine return -Anweisung muss implizit in den Rückgabetyp des Delegattyps oder Typ, der für die Ausdrucksbaumstruktur sein der nächsten einschließenden Lambda_expression oder Anonymous_ Method_expression konvertiert wird (anonyme Funktion Konvertierungen).An expression specified in a return 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).

Ist nicht explizit angegeben, ob es eine Möglichkeit gibt, führen Sie den Block, eine anonyme Funktion außer durch Auswertung und der 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 so implementieren Sie eine anonyme Funktion synthetisieren eine oder mehrere benannte Methoden und Typen.In particular, the compiler may choose to implement an anonymous function by synthesizing one or more named methods or types. Die Namen dieser alle synthetischen Elemente müssen eines Formulars, das für die Verwendung durch den Compiler reserviert sein.The names of any such synthesized elements must be of a form reserved for compiler use.

Auflösung von funktionsüberladungen und anonymen FunktionenOverload resolution and anonymous functions

Anonyme Funktionen in einer Argumentliste Typrückschluss teilnehmen und Auflösen der Überladung.Anonymous functions in an argument list participate in type inference and overload resolution. Näheres Typrückschluss und Überladungsauflösung die genauen Regeln.Please refer to Type inference and Overload resolution for the exact rules.

Das folgende Beispiel veranschaulicht die Auswirkungen von anonymen Funktionen auf überladungsauflö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 hat eine selector -Argument, das der Wert auf Summe von einem Listenelement 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 double und die resultierende Summe ist ebenso 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. zum Berechnen von Summen aus einer Liste der Detailzeilen in einer Reihenfolge verwendet werden.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);
    ...
}

In den ersten Aufruf des orderDetails.Sum, beide Sum Methoden gelten. da die anonyme Funktion d => d. UnitCount ist kompatibel mit sowohl Func<Detail,int> und 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>. Auflösung von funktionsüberladungen wählt jedoch die erste Sum Methode da die Konvertierung in Func<Detail,int> ist besser als die Konvertierung zu 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>.

Im zweiten Aufruf von orderDetails.Sum, nur der zweite Sum Methode gilt. da die anonyme Funktion d => d.UnitPrice * d.UnitCount erzeugt einen Wert vom Typ 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 überladen Auflösung auswählt, die zweite Sum Methode für diesen Aufruf.Thus, overload resolution picks the second Sum method for that invocation.

Anonyme Funktionen und dynamische BindungAnonymous functions and dynamic binding

Eine anonyme Funktion darf nicht über einen Empfänger, Argument oder zum Operand eine dynamisch gebundene Vorgang sein.An anonymous function cannot be a receiver, argument or operand of a dynamically bound operation.

Äußere VariablenOuter variables

Alle lokalen Variablen, "Value"-Parameter oder Parameterarray, deren Bereich umfasst, die Lambda_expression oder Anonymous_method_expression heißt ein äußere Variable der anonyme Funktion.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 einer Instanz Funktionsmember der Member einer Klasse die this Wert gilt, dass einen Value-Parameter, und eine äußere Variable von jeder anonyme Funktion, die in der Funktionsmember enthalten sind.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.

Äußere Variablen erfasstCaptured outer variables

Wenn eine äußere Variable, die von einer anonymen Funktion verwiesen wird, gilt die äußere Variable wurden als erfasst von der anonymen Funktion.When an outer variable is referenced by an anonymous function, the outer variable is said to have been captured by the anonymous function. Die Lebensdauer einer lokalen Variablen ist normalerweise begrenzt, für die Ausführung von Block oder der Anweisung, mit denen sie zugeordnet 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). Jedoch die Lebensdauer einer erfassten äußeren Variablen wird mindestens erweitert, bis der Delegat oder Ausdrucksbaumstruktur, die aus der anonymen Funktion erstellt wurde, wird für die Garbagecollection.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 erfasst, indem Sie die anonyme Funktion und die Lebensdauer des x mindestens erweitert wurde, bis der Delegat, der von zurückgegebene F wird zum Kandidaten für die Garbagecollection (die erst ganz am Ende nicht der Fall ist das Programm).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 der gleichen Instanz von jedem Aufruf der anonymen Funktion arbeitet x, die Ausgabe des Beispiels ist: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, die von einer anonymen Funktion erfasst sind, die lokale Variable oder Parameter wird nicht mehr als eine feste Variable sein (für feste und verschiebbare Variablen), aber stattdessen gilt eine Moveable Variable.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. Daher alle unsafe Code, der die Adresse der erfassten äußere Variable ist, muss zunächst mithilfe der fixed Anweisung, um die Variable zu beheben.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 Variable uncaptured eine aufgezeichnete lokale Variable gleichzeitig für mehrere Ausführungsthreads 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 gilt instanziiert bei Ausführung des Gültigkeitsbereichs der Variablen wechselt.A local variable is considered to be instantiated when execution enters the scope of the variable. Z. B. wenn die folgende Methode aufgerufen wird, die lokale Variable x instanziiert und initialisiert drei Mal – einmal für jede Iteration 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;
        ...
    }
}

Verschieben Sie jedoch die Deklaration von x außerhalb der Schleife Ergebnisse in eine einzelne Instanziierung 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;
        ...
    }
}

Wenn nicht erfasst werden, besteht keine Möglichkeit, beachten Sie, wie oft eine lokale Variable instanziiert wird, da die Lebensdauer der die Instanziierungen disjunkt sind, kann für alle Instanziierungen einfach am gleichen 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 eine lokale Variable erhält, werden die Auswirkungen der Instanziierung jedoch offensichtlich.However, when an anonymous function captures a local variable, the effects of instantiation become apparent.

Im 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

Aber wenn die Deklaration von x wird außerhalb der Schleife verschoben: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 Iterationsvariable in eine for-Schleife deklariert wird, gilt die Variable selbst außerhalb der Schleife deklariert werden.If a for-loop declares an iteration variable, that variable itself is considered to be declared outside of the loop. Also, wenn das Beispiel so geändert wird, um die Iterationsvariable selbst zu erfassen: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;
}

nur eine Instanz der Iterationsvariablen wird erfasst, das die Ausgabe generiert:only one instance of the iteration variable is captured, which produces the output:

3
3
3

Es ist möglich, dass anonyme Funktion freigeben einige erfassten Variablen noch verfügen über separate Instanzen von anderen Delegaten.It is possible for anonymous function delegates to share some captured variables yet have separate instances of others. Z. B. wenn F in geändert wirdFor 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 die gleiche Instanz von x jedoch separaten Instanzen von y, und die Ausgabe: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 mit die gleiche Instanz von eine äußere Variable erfassen.Separate anonymous functions can capture the same instance of an outer variable. Im folgenden BeispielIn 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 die gleiche Instanz von der lokalen Variablen x, und sie können daher "kommunizieren" über diese Variable.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 ist:The output of the example is:

5
10

Auswertung von Ausdrücken für anonyme FunktionEvaluation of anonymous function expressions

Eine anonyme Funktion F muss immer in einen Delegattyp konvertiert werden D oder ein Typ für die Ausdrucksbaumstruktur E, entweder direkt oder über die Ausführung von Delegaterstellungsausdrücke new D(F).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 Hauptfunktion unter anonyme Funktion Konvertierungen.This conversion determines the result of the anonymous function, as described in Anonymous function conversions.

AbfrageausdrückeQuery expressions

Abfrageausdrücke bieten eine integrierte Sprachsyntax für Abfragen, die relationale und hierarchische Abfragesprachen wie SQL oder XQuery ähnelt.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 Abfrageausdruck beginnt mit einer from -Klausel und endet mit einem select oder group Klausel.A query expression begins with a from clause and ends with either a select or group clause. Der ursprüngliche from Klausel gefolgt von NULL oder mehr from, let, where, join oder orderby Klauseln.The initial from clause can be followed by zero or more from, let, where, join or orderby clauses. Jede from -Klausel ist ein Generator Einführung in eine Bereichsvariable der Bereiche, über die Elemente einer Sequenz.Each from clause is a generator introducing a range variable which ranges over the elements of a sequence. Jede let Klausel führt eine Bereichsvariable, der ein über den vorherigen Bereichsvariablen berechnet.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 ausgeschlossen sind.Each where clause is a filter that excludes items from the result. Jede join -Klausel vergleicht die angegebenen Schlüssel der Quellsequenz mit Schlüsseln von einer anderen Sequenz, die übereinstimmende Paare Rückgabe.Each join clause compares specified keys of the source sequence with keys of another sequence, yielding matching pairs. Jede orderby Klausel sortiert die Elemente gemäß den angegebenen Kriterien. Die endgültige select oder group -Klausel gibt die Form des Ergebnisses in Bezug auf die Bereichsvariablen.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 eine into -Klausel kann verwendet werden, für die Abfragen "Zusammenführung", indem Sie die Ergebnisse einer Abfrage als einen Generator in einer nachfolgenden Abfrage zu behandeln.Finally, an into clause can be used to "splice" queries by treating the results of one query as a generator in a subsequent query.

Allerdings haben Mehrdeutigkeiten in AbfrageausdrückenAmbiguities in query expressions

Abfrageausdrücke enthalten eine Anzahl von "kontextabhängige Schlüsselwörter", d. h. die 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. Insbesondere Hierbei handelt es sich 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 Abfrageausdrücken aufgrund gemischter Verwendung dieser Bezeichner als Schlüsselwörter oder einfache Namen zu vermeiden, gelten diese Bezeichner Schlüsselwörter, wenn eine beliebige Stelle in einem Abfrageausdruck stattfinden.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 ein Abfrageausdruck ist ein Ausdruck, der mit "from identifier"gefolgt von jedes Token, mit Ausnahme von";","="oder",".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 in einem Abfrageausdruck verwenden, sie können dem Präfix "@" (Bezeichner).In order to use these words as identifiers within a query expression, they can be prefixed with "@" (Identifiers).

Übersetzung AbfrageausdrucksQuery expression translation

Die C#-Sprache gibt nicht die Ausführungssemantik von Abfrageausdrücken an.The C# language does not specify the execution semantics of query expressions. Stattdessen Abfrageausdrücke werden in übersetzt, Aufrufe von Methoden, die folgen, der Abfrageausdrucksmuster (das Abfrageausdrucksmuster).Rather, query expressions are translated into invocations of methods that adhere to the query expression pattern (The query expression pattern). Insbesondere werden die Abfrageausdrücke in Aufrufe von Methoden, die mit dem Namen übersetzt Where, Select, SelectMany, Join, GroupJoin, OrderBy, OrderByDescending, ThenBy, ThenByDescending, GroupBy, und Cast. Diese Methoden werden voraussichtlich bestimmter Signaturen und Ergebnistypen, siehe das Abfrageausdrucksmuster.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 sein, Instanzmethoden des abgefragten Objekts oder von Erweiterungsmethoden, die auf das Objekt extern sind, und implementieren sie die eigentliche 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 Abfrageausdrücken Methodenaufrufe ist eine syntaktische Zuordnung, die vor jeder typbindung oder die Auflösung von funktionsüberladungen ausgeführt wurde.The translation from query expressions to method invocations is a syntactic mapping that occurs before any type binding or overload resolution has been performed. Die Übersetzung wird garantiert, syntaktisch korrekt zu sein, aber nicht notwendigerweise um semantisch richtige C#-Code zu erzeugen.The translation is guaranteed to be syntactically correct, but it is not guaranteed to produce semantically correct C# code. Nach der Übersetzung von Abfrageausdrücken, die sich ergebende Methodenaufrufe werden als reguläre Methodenaufrufe verarbeitet, und dies kann wiederum Fehler, z. B. aufzudecken, wenn die Methoden nicht vorhanden sind, wenn Argumente falsch aufweisen, oder die Methoden generisch sind und Typrückschluss schlägt fehl.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 Abfrageausdruck wird verarbeitet, durch die folgenden Übersetzungen wiederholtes anwenden, bis keine weiteren Reduzierung möglich sind.A query expression is processed by repeatedly applying the following translations until no further reductions are possible. Die Übersetzungen sind in der Reihenfolge der Anwendung aufgeführt: jeder Abschnitt wird davon ausgegangen, dass die Übersetzungen in den vorherigen Abschnitten wurden vollständig ausgeführt, und nachdem erreicht, ein Abschnitt nicht höher sein bei der Verarbeitung der selben Abfrageausdruck Revisited wird.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.

Zuweisung zu einer Bereichsvariablen darf nicht in Abfrageausdrücken.Assignment to range variables is not allowed in query expressions. Eine C#-Implementierung darf jedoch nicht immer dieser Einschränkung zu erzwingen, da dies in einigen Fällen möglicherweise nicht mit dem hier vorgestellten syntaktische Übersetzung-Schema werden kann.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 injizieren Bereichsvariablen mit transparenter Bezeichner gekennzeichnet durch *.Certain translations inject range variables with transparent identifiers denoted by *. Die speziellen Eigenschaften transparenter Bezeichner werden erläutert. im weiteren transparenter Bezeichner.The special properties of transparent identifiers are discussed further in Transparent identifiers.

Wählen Sie "und" Groupby-Klausel mit FortsetzungenSelect and groupby clauses with continuations

Ein Abfrageausdruck mit einer FortsetzungA query expression with a continuation

from ... into x ...

wird übersetztis translated into

from x in ( from ... ) ...

Die Übersetzungen in den folgenden Abschnitten wird davon ausgegangen, dass Abfragen keine into Fortsetzungen.The translations in the following sections assume that queries have no into continuations.

Im BeispielThe example

from c in customers
group c by c.Country into g
select new { Country = g.Key, CustCount = g.Count() }

wird übersetztis translated into

from g in
    from c in customers
    group c by c.Country
select new { Country = g.Key, CustCount = g.Count() }

die endgültige Übersetzung der istthe final translation of which is

customers.
GroupBy(c => c.Country).
Select(g => new { Country = g.Key, CustCount = g.Count() })

Explizite Bereich VariablentypenExplicit range variable types

Ein from -Klausel, die einen Bereichsvariablentyp gibt explizit anA from clause that explicitly specifies a range variable type

from T x in e

wird übersetztis translated into

from x in ( e ) . Cast < T > ( )

Ein join -Klausel, die einen Bereichsvariablentyp gibt explizit anA join clause that explicitly specifies a range variable type

join T x in e on k1 equals k2

wird übersetztis translated into

join x in ( e ) . Cast < T > ( ) on k1 equals k2

Die Übersetzungen in den folgenden Abschnitten wird davon ausgegangen, dass Abfragen keine expliziten Bereich Variablentypen.The translations in the following sections assume that queries have no explicit range variable types.

Im BeispielThe example

from Customer c in customers
where c.City == "London"
select c

wird übersetztis translated into

from c in customers.Cast<Customer>()
where c.City == "London"
select c

die endgültige Übersetzung der istthe final translation of which is

customers.
Cast<Customer>().
Where(c => c.City == "London")

Variablentypen expliziten Bereich sind nützlich zum Abfragen von Auflistungen bereit, die nicht generische implementieren IEnumerable -Schnittstelle, aber nicht 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 wurden vom Typ ArrayList.In the example above, this would be the case if customers were of type ArrayList.

Degenerierte-AbfrageausdrückeDegenerate query expressions

Ein Abfrageausdruck den Wert des FormularsA query expression of the form

from x in e select x

wird übersetztis translated into

( e ) . Select ( x => x )

Im BeispielThe example

from c in customers
select c

wird übersetztis translated into

customers.Select(c => c)

Ein degenerierter Abfrageausdruck ist eine, die einfach die Elemente der Quelle auswählt.A degenerate query expression is one that trivially selects the elements of the source. Eine spätere Phase der Übersetzung entfernt degenerierte Abfragen durch andere Übersetzungsschritten, indem diese zu ihrer Quelle ersetzt.A later phase of the translation removes degenerate queries introduced by other translation steps by replacing them with their source. Es ist wichtig, jedoch um sicherzustellen, dass das Ergebnis einer Abfrage Ausdruck nie das Quellobjekt selbst ist, wie die, die den Typ und die Identität der Quelle an den Client der Abfrage anzeigen würden.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. Aus diesem Grund schützt dadurch degenerierte Abfragen, die direkt im Quellcode geschrieben wird, durch explizites Aufrufen von Select auf dem Quellcomputer.Therefore this step protects degenerate queries written directly in source code by explicitly calling Select on the source. Es ist Ihre Aufgabe die Implementierer von Select und andere Abfrageoperatoren, um sicherzustellen, dass diese Methoden geben das Quellobjekt selbst nie zurück.It is then up to the implementers of Select and other query operators to ensure that these methods never return the source object itself.

Zu ermöglichen, where, Join und Orderby-KlauselFrom, let, where, join and orderby clauses

Ein Abfrageausdruck mit einer Sekunde from Klausel gefolgt von einem select KlauselA query expression with a second from clause followed by a select clause

from x1 in e1
from x2 in e2
select v

wird übersetztis translated into

( e1 ) . SelectMany( x1 => e2 , ( x1 , x2 ) => v )

Ein Abfrageausdruck mit einer Sekunde from Klausel gefolgt von etwas anders als eine 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 übersetztis translated into

from * in ( e1 ) . SelectMany( x1 => e2 , ( x1 , x2 ) => new { x1 , x2 } )
...

Ein Abfrageausdruck mit einer let KlauselA query expression with a let clause

from x in e
let y = f
...

wird übersetztis translated into

from * in ( e ) . Select ( x => new { x , y = f } )
...

Ein Abfrageausdruck mit einer where KlauselA query expression with a where clause

from x in e
where f
...

wird übersetztis translated into

from x in ( e ) . Where ( x => f )
...

Einen Abfrageausdruck mit einer join -Klausel ohne eine into gefolgt von einem select KlauselA 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 übersetztis translated into

( e1 ) . Join( e2 , x1 => k1 , x2 => k2 , ( x1 , x2 ) => v )

Einen Abfrageausdruck mit einer join -Klausel ohne eine into gefolgt von etwas anders als eine select KlauselA 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 übersetztis translated into

from * in ( e1 ) . Join( e2 , x1 => k1 , x2 => k2 , ( x1 , x2 ) => new { x1 , x2 })
...

Einen Abfrageausdruck mit einer join -Klausel mit einer into gefolgt von einer select KlauselA 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 übersetztis translated into

( e1 ) . GroupJoin( e2 , x1 => k1 , x2 => k2 , ( x1 , g ) => v )

Einen Abfrageausdruck mit einer join -Klausel mit einer into gefolgt von etwas anders als eine select KlauselA 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 übersetztis translated into

from * in ( e1 ) . GroupJoin( e2 , x1 => k1 , x2 => k2 , ( x1 , g ) => new { x1 , g })
...

Ein Abfrageausdruck mit einer orderby KlauselA query expression with an orderby clause

from x in e
orderby k1 , k2 , ..., kn
...

wird übersetztis translated into

from x in ( e ) . 
OrderBy ( x => k1 ) . 
ThenBy ( x => k2 ) .
... .
ThenBy ( x => kn )
...

-Klausel gibt an, wenn eine Sortierung, die eine descending Richtung-Symbol, einen Aufruf der OrderByDescending oder ThenByDescending stattdessen erzeugt wird.If an ordering clause specifies a descending direction indicator, an invocation of OrderByDescending or ThenByDescending is produced instead.

Die folgenden Übersetzungen wird davon ausgegangen, dass es sind keine let, where, join oder orderby -Klauseln und nicht mehr als einen ersten from -Klausel in jedem Abfrageausdruck.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.

Im BeispielThe example

from c in customers
from o in c.Orders
select new { c.Name, o.OrderID, o.Total }

wird übersetztis translated into

customers.
SelectMany(c => c.Orders,
     (c,o) => new { c.Name, o.OrderID, o.Total }
)

Im BeispielThe example

from c in customers
from o in c.Orders
orderby o.Total descending
select new { c.Name, o.OrderID, o.Total }

wird übersetztis 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 endgültige Übersetzung der istthe 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 })

wo x ist ein vom Compiler generierten Bezeichner, der ansonsten nicht sichtbar und kann nicht zugegriffen werden.where x is a compiler generated identifier that is otherwise invisible and inaccessible.

Im 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 übersetztis 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 endgültige Übersetzung der istthe 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 })

wo x ist ein vom Compiler generierten Bezeichner, der ansonsten nicht sichtbar und kann nicht zugegriffen werden.where x is a compiler generated identifier that is otherwise invisible and inaccessible.

Im 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 übersetztis translated into

customers.Join(orders, c => c.CustomerID, o => o.CustomerID,
    (c, o) => new { c.Name, o.OrderDate, o.Total })

Im 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 übersetztis 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 endgültige Übersetzung der istthe 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)

wo x und y sind vom Compiler generierten Bezeichner, die andernfalls nicht sichtbar und kann nicht zugegriffen werden.where x and y are compiler generated identifiers that are otherwise invisible and inaccessible.

Im BeispielThe example

from o in orders
orderby o.Customer.Name, o.Total descending
select o

hat die letzte Übersetzunghas the final translation

orders.
OrderBy(o => o.Customer.Name).
ThenByDescending(o => o.Total)

Select-KlauselnSelect clauses

Ein Abfrageausdruck den Wert des FormularsA query expression of the form

from x in e select v

wird übersetztis translated into

( e ) . Select ( x => v )

es sei denn, V den Bezeichner X, die Übersetzung ist 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

In wird einfach übersetzt werden.is simply translated into

customers.Where(c => c.City == "London")

GroupBy-KlauselGroupby clauses

Ein Abfrageausdruck den Wert des FormularsA query expression of the form

from x in e group v by k

wird übersetztis translated into

( e ) . GroupBy ( x => k , x => v )

es sei denn, V den Bezeichner X, die Übersetzung ist.except when v is the identifier x, the translation is

( e ) . GroupBy ( x => k )

Im BeispielThe example

from c in customers
group c.Name by c.Country

wird übersetztis translated into

customers.
GroupBy(c => c.Country, c => c.Name)

Transparenter BezeichnerTransparent identifiers

Bestimmte Übersetzungen einfügen Bereichsvariablen mit transparenter Bezeichner gekennzeichnet durch *.Certain translations inject range variables with transparent identifiers denoted by *. Transparente-IDs sind keine geeignete Sprache-Funktion. Sie sind nur als ein Zwischenschritt bei der Abfrage Ausdruck Übersetzungsprozess 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 einbettet sollten, weiter weitergegeben Übersetzungsschritten den transparenten Bezeichner in anonymen 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 transparenter 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 anonymen Typs zugeordnet automatisch im Bereich des Texts der anonymen Funktion.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 ein Element mit einem transparenten Bezeichner im Gültigkeitsbereich befindet, sind im Bereich auch die Elemente dieses Elements.When a member with a transparent identifier is in scope, the members of that member are in scope as well.
  • Tritt ein transparenter Bezeichner als ein Member-Declarator in einem anonyme Objektinitialisierer, führt er einen Member mit einem transparenten Bezeichner.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 Übersetzungsschritten werden transparent Bezeichner immer zusammen mit anonymen Typen, mit der Absicht an mehrere Bereichsvariablen als Mitglieder eines einzelnen Objekts erfassen eingeführt.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# ist zulässig, einen anderen Mechanismus als anonyme Typen zu verwenden, um mehrere Bereichsvariablen 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 Beispielen für die Übersetzung wird davon ausgegangen, dass anonyme Typen werden verwendet, und wie transparent Bezeichner zeigen sofort übersetzt werden kann.The following translation examples assume that anonymous types are used, and show how transparent identifiers can be translated away.

Im BeispielThe example

from c in customers
from o in c.Orders
orderby o.Total descending
select new { c.Name, o.Total }

wird übersetztis translated into

from * in customers.
    SelectMany(c => c.Orders, (c,o) => new { c, o })
orderby o.Total descending
select new { c.Name, o.Total }

die übersetzt weiteren 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 transparente Bezeichner gelöscht werden, entsprichtwhich, 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 })

wo x ist ein vom Compiler generierten Bezeichner, der ansonsten nicht sichtbar und kann nicht zugegriffen werden.where x is a compiler generated identifier that is otherwise invisible and inaccessible.

Im 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 übersetztis 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 }

die weiteren wird nach einer Verkleinerung 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 endgültige Übersetzung der istthe 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 })

wo x, y, und z sind vom Compiler generierten Bezeichner, die andernfalls nicht sichtbar und kann nicht zugegriffen werden.where x, y, and z are compiler generated identifiers that are otherwise invisible and inaccessible.

Das AbfrageausdrucksmusterThe query expression pattern

Die Abfrageausdrucksmuster richtet ein Muster von Methoden, Typen implementiert werden können, um Abfrageausdrücke unterstützen.The Query expression pattern establishes a pattern of methods that types can implement to support query expressions. Da durch eine syntaktische Zuordnung Abfrageausdrücke Methodenaufrufe übersetzt werden, haben Typen beträchtliche Flexibilität bei, wie sie das Abfrageausdrucksmuster implementieren.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 Erweiterungsmethoden implementiert werden, da die beiden die gleiche Aufrufsyntax haben und die Methoden Delegaten oder Ausdrucksbaumstrukturen anfordern können, da anonyme Funktionen sowohl konvertiert werden.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> , unterstützt Abfragemusters Ausdruck unten dargestellt ist.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 Ergebnis zu veranschaulichen, aber es ist möglich, die das Muster für nicht generische Typen ebenfalls 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 generische Delegattypen Func<T1,R> und Func<T1,T2,R>, aber sie ebenso gut hätten auch andere Typen für Delegat- oder Struktur mit den gleichen Beziehungen in Parameter und Ergebnis.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, dass die empfohlene Beziehung zwischen C<T> und O<T> wird sichergestellt, dass die ThenBy und ThenByDescending Methoden stehen nur auf das Ergebnis einer OrderBy oder 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 GroupBy – eine Sequenz von Sequenzen, die jeder innere Sequenz verfügt, in denen über einen zusätzlichen Key Eigenschaft.Also notice the recommended shape of the result of GroupBy -- a sequence of sequences, where each inner sequence has an additional Key property.

Die System.Linq Namespace stellt eine Implementierung des Abfragemusters Operator für jeden Typ, der implementiert die System.Collections.Generic.IEnumerable<T> Schnittstelle.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 Zuweisungsoperatoren zuweisen eine Variable, eine Eigenschaft, ein Ereignis oder ein Indexerelement einen neuen Wert.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, der als eine Variable, einen Eigenschaftenzugriff, Indexzugriff oder ein Ereigniszugriff klassifiziert sind.The left operand of an assignment must be an expression classified as a variable, a property access, an indexer access, or an event access.

Die = Operator wird aufgerufen, die einfacher Zuweisungsoperator.The = operator is called the simple assignment operator. Es weist den Wert des rechten Operanden, auf die Variable, Eigenschaft oder der Indexer-Element, durch den linken Operanden angegeben.It assigns the value of the right operand to the variable, property, or indexer element given by the left operand. Der linke Operand des der einfache Zuweisungsoperator möglicherweise kein Event-Zugriff (mit Ausnahme beschriebener in Feldähnliche Ereignisse).The left operand of the simple assignment operator may not be an event access (except as described in Field-like events). Der einfache Zuweisungsoperator finden Sie im einfache Zuweisung.The simple assignment operator is described in Simple assignment.

Die Zuweisungsoperatoren außer der = Operator heißen die zusammensetzungszuweisungsoperatoren.The assignment operators other than the = operator are called the compound assignment operators. Diese Operatoren den angegebenen Vorgang für die beiden Operanden ausführen, und klicken Sie dann den resultierenden Wert zuweisen, auf die Variable, Eigenschaft oder der Indexer-Element, durch den linken Operanden angegeben.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 zusammengesetzten Zuweisungsoperatoren werden in beschrieben Verbundzuweisung.The compound assignment operators are described in Compound assignment.

Die += und -= Operatoren mit einem Event-Access-Ausdruck wie der linke Operand heißen die Ereignis Zuweisungsoperatoren.The += and -= operators with an event access expression as the left operand are called the event assignment operators. Keine anderen Zuweisungsoperator ist wie der linke Operand ein Ereigniszugriff gültig.No other assignment operator is valid with an event access as the left operand. Die Ereignis-Zuweisungsoperatoren werden in beschrieben Ereignis Zuweisung.The event assignment operators are described in Event assignment.

Die Zuweisungsoperatoren sind rechtsassoziativ, was bedeutet, dass Vorgänge, die von rechts nach links gruppiert werden.The assignment operators are right-associative, meaning that operations are grouped from right to left. Z. B. ein Ausdruck der Form a = b = c wird als ausgewertet, a = (b = c).For example, an expression of the form a = b = c is evaluated as a = (b = c).

Einfache ZuweisungSimple assignment

Die = Operator wird den einfache Zuweisungsoperator aufgerufen.The = operator is called the simple assignment operator.

Wenn der linke Operand, der eine einfache Zuweisung des Formulars ist E.P oder E[Ei] , in denen E weist den Typ der Kompilierzeit dynamic, und klicken Sie dann die Zuweisung dynamisch gebunden ist (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 den Kompilierzeittyp des Zuweisungsausdrucks ist dynamic, und die unten beschriebene Lösung wird zur Laufzeit basierend auf den Laufzeittyp der 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 ist.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 auf die Variable, Eigenschaft oder der Indexer-Element, durch den linken Operanden angegeben.The operation assigns the value of the right operand to the variable, property, or indexer element given by the left operand.

Das Ergebnis eines Ausdrucks für die einfache Zuweisung wird der Wert, der linke Operand zugewiesen.The result of a simple assignment expression is the value assigned to the left operand. Das Ergebnis weist den gleichen Typ wie der linke Operand, und es 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 der Indexer-Zugriff ist, Eigenschaft oder des Indexers benötigen eine set Accessor.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 Fehler während der Bindung.If this is not the case, a binding-time error occurs.

Die Verarbeitung zur Laufzeit eine einfache Zuweisung des Formulars x = y umfasst die folgenden Schritte aus:The run-time processing of a simple assignment of the form x = y consists of the following steps:

  • Wenn x wird als Variable klassifiziert:If x is classified as a variable:
    • x wird ausgewertet, um die Variable zu erstellen.x is evaluated to produce the variable.
    • y wird ausgewertet und, falls erforderlich, konvertiert in den Typ des x über eine implizite Konvertierung (implizite Konvertierungen).y is evaluated and, if required, converted to the type of x through an implicit conversion (Implicit conversions).
    • Wenn die Variable, die vom x ist ein Arrayelement einen Reference_type, eine laufzeitüberprüfung ausgeführt, um sicherzustellen, dass der Wert für berechnet y ist kompatibel mit der Arrayinstanz, von denen x ist ein Element.If the variable given by x is an array element of a reference_type, a run-time check is performed to ensure that the value computed for y is compatible with the array instance of which x is an element. Die Überprüfung ist erfolgreich, wenn y ist null, oder wenn implizite verweiskonvertierung (implizite Verweis-) vorhanden ist, aus dem tatsächlichen Typ der Instanz verweist y in den tatsächlichen Elementtyp der Instanz für das Array mit x.The check succeeds if y is null, or if an implicit reference conversion (Implicit reference conversions) exists from the actual type of the instance referenced by y to the actual element type of the array instance containing x. Andernfalls wird eine System.ArrayTypeMismatchException ausgelöst.Otherwise, a System.ArrayTypeMismatchException is thrown.
    • Der Wert der Auswertung und Konvertierung von y befindet sich in den Speicherort durch die Auswertung von x.The value resulting from the evaluation and conversion of y is stored into the location given by the evaluation of x.
  • Wenn x wird als eine Eigenschaft oder der Indexer Zugriff klassifiziert:If x is classified as a property or indexer access:
    • Der Instanzausdruck (Wenn x ist nicht static) und die Argumentliste (Wenn x Indexzugriff ist) zugeordneten x werden ausgewertet, und die Ergebnisse werden in der nachfolgenden verwendet set Accessor-Aufruf.The instance expression (if x is not static) and the argument list (if x is an indexer access) associated with x are evaluated, and the results are used in the subsequent set accessor invocation.
    • y wird ausgewertet und, falls erforderlich, konvertiert in den Typ des x über eine implizite Konvertierung (implizite Konvertierungen).y is evaluated and, if required, converted to the type of x through an implicit conversion (Implicit conversions).
    • Die set Accessor x wird aufgerufen, mit dem Wert für berechnet y als seine value Argument.The set accessor of x is invoked with the value computed for y as its value argument.

Die Array-Co Varianz-Regeln (Array-Kovarianz) zulassen den Wert eines Arraytyps A[] sollen einen Verweis auf eine Instanz des Arraytyps B[], sofern eine implizite verweiskonvertierung von vorhanden ist B zu 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, die Zuweisung an ein Arrayelement einen Reference_type erfordert eine laufzeitüberprüfung aus, um sicherzustellen, dass der zugewiesene Wert mit dem 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

bewirkt, dass die letzte Zuweisung einer System.ArrayTypeMismatchException ausgelöst werden, da eine Instanz von ArrayList kann nicht gespeichert werden, in einem Element des eine 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 Eigenschaft oder der Indexer in deklariert eine Struct_type ist das Ziel einer Zuweisung, die den Instanzausdruck, die mit der Eigenschaft verknüpften oder Indexerzugriff muss 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 ist, tritt ein Fehler während der Bindung.If the instance expression is classified as a value, a binding-time error occurs. Aufgrund der Memberzugriff, die gleiche Regel gilt auch für Felder.Because of Member access, the same rule also applies to fields.

Betrachten Sie die 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 zu 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 Beispiel allerdingsHowever, 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 sind keine Variablen.the assignments are all invalid, since r.A and r.B are not variables.

VerbundzuweisungCompound assignment

Wenn der linke Operand des eine zusammengesetzte Zuweisung des Formulars ist E.P oder E[Ei] , in denen E weist den Typ während der Kompilierung dynamic, und klicken Sie dann die Zuweisung dynamisch gebunden ist (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 den Kompilierzeittyp des Zuweisungsausdrucks ist dynamic, und die unten beschriebene Lösung wird zur Laufzeit basierend auf den Laufzeittyp der 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 durch Anwenden der Auflösung von funktionsüberladungen binärer Operator verarbeitet (binärer Operator überladungsauflösung), 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. Klicken Sie dannThen,

  • Wenn der Rückgabetyp des ausgewählten Operators implizit in den Typ des x, der Vorgang wird als ausgewertet x = x op y, außer dass x wird nur einmal ausgewertet.If the return type of the selected operator is implicitly convertible to the type of x, the operation is evaluated as x = x op y, except that x is evaluated only once.
  • Andernfalls, wenn der ausgewählte Operator einen vordefinierten Operator ist, ist der Rückgabetyp von den ausgewählten Operator explizit konvertiert werden kann, in den Typ des x, und wenn y wird implizit in den Typ des x oder der Operator ist ein Shift-Operator, und klicken Sie dann der Vorgang als ausgewertet wird x = (T)(x op y), wobei T ist der Typ des x, außer dass x wird nur einmal ausgewertet.Otherwise, if the selected operator is a predefined operator, if the return type of the selected operator is explicitly convertible to the type of x, and if y is implicitly convertible to the type of x or the operator is a shift operator, then the operation is evaluated as x = (T)(x op y), where T is the type of x, except that x is evaluated only once.
  • Andernfalls die zusammengesetzte Zuweisung ist ungültig, und beim Auftreten eines Laufzeitfehlers-Bindung.Otherwise, the compound assignment is invalid, and a binding-time error occurs.

Der Begriff "nur einmal ausgewertet" bedeutet, dass bei der Auswertung x op y, die Ergebnisse der enthaltenen Ausdrücke von x vorübergehend gespeichert und dann wiederverwendet werden, bei der Zuweisung zu 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. Z. B. in der Zuweisung A()[B()] += C(), wobei A ist eine Methode zurückgeben int[], und B und C sind Methoden, die zurückgeben int, die Methoden werden nur einmal aufgerufen, in der Reihenfolge A, 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 des eine zusammengesetzte Zuweisung einer Eigenschaft oder Indexzugriff ist, Eigenschaft oder des Indexers benötigen Sie Folgendes ein get Accessor und einen set Accessor.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 Fehler während der Bindung.If this is not the case, a binding-time error occurs.

Die zweite Regel oben ermöglicht x op= y als auszuwertenden x = (T)(x op y) in bestimmten Kontexten.The second rule above permits x op= y to be evaluated as x = (T)(x op y) in certain contexts. Die Regel vorhanden ist, dass die vordefinierten Operatoren an, die als zusammengesetzte Operatoren verwendet werden können, wenn der linke Operand vom Typ sbyte, byte, short, ushort, oder 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 einer dieser Typen sind, die vordefinierten Operatoren erzeugt ein Ergebnis vom Typ int, wie in beschrieben binären numerischen heraufstufungen.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 ohne eine Umwandlung wäre nicht möglich, einem der linke Operand das Ergebnis zuzuweisen es.Thus, without a cast it would not be possible to assign the result to the left operand.

Die intuitive Auswirkung der Regel für die vordefinierten Operatoren ist einfach, x op= y ist zulässig, wenn sowohl der x op y und x = y sind zulässig.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

die Fehlerursache für jeden Fehler ist, dass eine entsprechende einfache Zuweisung auch ein Fehler gewesen wäre.the intuitive reason for each error is that a corresponding simple assignment would also have been an error.

Dies bedeutet auch, dass die verbundzuweisung, in die Vorgänge unterstützen Vorgänge aufgehoben.This also means that compound assignment operations support lifted operations. Im BeispielIn the example

int? i = 0;
i += 1;             // Ok

der transformierten Operator +(int?,int?) verwendet wird.the lifted operator +(int?,int?) is used.

Ereignis-ZuweisungEvent assignment

Wenn der linke Operand des eine += oder -= Operator wird als Ereigniszugriff klassifiziert, und der Ausdruck wird 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 wird ggf. von der Ereigniszugriff ausgewertet.The instance expression, if any, of the event access is evaluated.
  • Der Rechte Operand des der += oder -= Operator wird ausgewertet, und, falls erforderlich, konvertiert in den Typ des linken Operanden über eine implizite Konvertierung (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 Ereignisaccessor des Ereignisses aufgerufen wird, mit der Argumentliste, die mit dem rechten Operanden ist, nach der Auswertung und, falls erforderlich, Konvertierung.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 -Accessor wird aufgerufen, wenn der Operator war -=, remove -Accessor wird aufgerufen.If the operator was +=, the add accessor is invoked; if the operator was -=, the remove accessor is invoked.

Zuweisungsausdruck Ereignis ergibt sich nicht auf einen Wert aus.An event assignment expression does not yield a value. Daher Zuweisungsausdruck Ereignis nur im Kontext gültig ist eine Statement_expression (ausdrucksanweisungen).Thus, an event assignment expression is valid only in the context of a statement_expression (Expression statements).

AusdruckExpression

Ein Ausdruck ist entweder ein Non_assignment_expression oder Zuweisung.An expression is either a non_assignment_expression or an assignment.

expression
    : non_assignment_expression
    | assignment
    ;

non_assignment_expression
    : conditional_expression
    | lambda_expression
    | query_expression
    ;

Konstante AusdrückeConstant expressions

Ein Constant_expression ist ein Ausdruck, der zum Zeitpunkt der Kompilierung vollständig ausgewertet werden kann.A constant_expression is an expression that can be fully evaluated at compile-time.

constant_expression
    : expression
    ;

Es muss ein konstanter Ausdruck sein. die null Literal oder einen Wert mit einem der folgenden Typen: sbyte, byte, short, ushort, int, uint, long, ulong, char , float, double, decimal, bool, object, string, oder ein Enumerationstyp.A constant expression must be the null literal or a value with one of the following types: sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, bool, object, string, or any enumeration type. Nur die folgenden Konstrukte sind in Konstanten Ausdrücken zulässig:Only the following constructs are permitted in constant expressions:

  • Literale (einschließlich der null literal).Literals (including the null literal).
  • Verweise auf const Member der Klasse und Strukturtypen.References to const members of class and struct types.
  • Verweise auf Member von Enumerationstypen.References to members of enumeration types.
  • Verweise auf const Parameter oder lokale VariablenReferences to const parameters or local variables
  • Untergeordnete Ausdrücke in Klammern, die Konstante Ausdrücke sind.Parenthesized sub-expressions, which are themselves constant expressions.
  • CAST-Ausdrücke, die den Typ des bereitgestellten ist einer der oben aufgeführten Typen.