Lexikalische StrukturLexical structure

ProgrammePrograms

Ein c# Programm _ besteht aus mindestens einer _Quelldatei_, die formal als _ Kompilierungs Einheiten (Kompilierungs Einheiten) bekannt ist.A C# program _ consists of one or more _source files_, known formally as _ compilation units (Compilation units). Eine Quelldatei ist eine geordnete Sequenz von Unicode-Zeichen.A source file is an ordered sequence of Unicode characters. Quelldateien verfügen in der Regel über eine eins-zu-eins-Entsprechung zu Dateien in einem Dateisystem, diese Entsprechung ist jedoch nicht erforderlich.Source files typically have a one-to-one correspondence with files in a file system, but this correspondence is not required. Zur maximalen Portabilität wird empfohlen, dass Dateien in einem Dateisystem mit der UTF-8-Codierung codiert werden.For maximal portability, it is recommended that files in a file system be encoded with the UTF-8 encoding.

Konzeptionell wird ein Programm mithilfe von drei Schritten kompiliert:Conceptually speaking, a program is compiled using three steps:

  1. Transformation, die eine Datei von einem bestimmten Zeichen-und Codierungsschema in eine Unicode-Zeichenfolge konvertiert.Transformation, which converts a file from a particular character repertoire and encoding scheme into a sequence of Unicode characters.
  2. Lexikalische Analyse, die einen Stream von Unicode-Eingabezeichen in einen Datenstrom von Token übersetzt.Lexical analysis, which translates a stream of Unicode input characters into a stream of tokens.
  3. Syntaktische Analyse, bei der der Datenstrom von Token in ausführbaren Code übersetzt wird.Syntactic analysis, which translates the stream of tokens into executable code.

Grammars (Grammatik)Grammars

Diese Spezifikation zeigt die Syntax der c#-Programmiersprache mit zwei Grammatiken.This specification presents the syntax of the C# programming language using two grammars. Die lexikalische Grammatik _ (lexikalischeGrammatik) definiert, wie Unicode-Zeichen kombiniert werden, um Zeilen Abschluss Zeichen, Leerzeichen, Kommentare, Token und Vorverarbeitungs Direktiven zu bilden.The *lexical grammar _ (Lexical grammar) defines how Unicode characters are combined to form line terminators, white space, comments, tokens, and pre-processing directives. Die syntaktische Grammatik * (syntaktische Grammatik) definiert, wie die aus der lexikalischen Grammatik resultierenden Token kombiniert werden, um c#-Programme zu bilden.The _ syntactic grammar* (Syntactic grammar) defines how the tokens resulting from the lexical grammar are combined to form C# programs.

Grammatik NotationGrammar notation

Die lexikalischen und syntaktischen Grammatiken werden in Backus-Naur Formular mithilfe der Notation des antlr-Grammatik Tools dargestellt.The lexical and syntactic grammars are presented in Backus-Naur form using the notation of the ANTLR grammar tool.

Lexikalische GrammatikLexical grammar

Die lexikalische Grammatik von c# wird in lexikalischen Analysen, Tokenund Vorverarbeitungs Direktivendargestellt.The lexical grammar of C# is presented in Lexical analysis, Tokens, and Pre-processing directives. Die Terminal Symbole der lexikalischen Grammatik sind die Zeichen des Unicode-Zeichensatzes, und die lexikalische Grammatik gibt an, wie Zeichen kombiniert werden, um Token (Token), Leerzeichen (Leerraum), Kommentare (Kommentare) und Vorverarbeitungs Direktiven (Vorverarbeitungs Direktiven) zu bilden.The terminal symbols of the lexical grammar are the characters of the Unicode character set, and the lexical grammar specifies how characters are combined to form tokens (Tokens), white space (White space), comments (Comments), and pre-processing directives (Pre-processing directives).

Jede Quelldatei in einem c#-Programm muss der Eingabe Produktion der lexikalischen Grammatik (lexikalische Analyse) entsprechen.Every source file in a C# program must conform to the input production of the lexical grammar (Lexical analysis).

Syntaktische GrammatikSyntactic grammar

Die syntaktische Grammatik von c# wird in den Kapiteln und Anhänge dargestellt, die diesem Kapitel folgen.The syntactic grammar of C# is presented in the chapters and appendices that follow this chapter. Die Terminal Symbole der syntaktischen Grammatik sind die von der lexikalischen Grammatik definierten Token, und die syntaktische Grammatik gibt an, wie Token kombiniert werden, um c#-Programme zu bilden.The terminal symbols of the syntactic grammar are the tokens defined by the lexical grammar, and the syntactic grammar specifies how tokens are combined to form C# programs.

Jede Quelldatei in einem c#-Programm muss der compilation_unit Produktion der syntaktischen Grammatik (Kompilierungs Einheiten) entsprechen.Every source file in a C# program must conform to the compilation_unit production of the syntactic grammar (Compilation units).

Lexikalische AnalyseLexical analysis

Die Eingabe Produktion definiert die lexikalische Struktur einer c#-Quelldatei.The input production defines the lexical structure of a C# source file. Jede Quelldatei in einem c#-Programm muss mit dieser lexikalischen Grammatik Produktion übereinstimmen.Each source file in a C# program must conform to this lexical grammar production.

input
    : input_section?
    ;

input_section
    : input_section_part+
    ;

input_section_part
    : input_element* new_line
    | pp_directive
    ;

input_element
    : whitespace
    | comment
    | token
    ;

Fünf grundlegende Elemente bilden die lexikalische Struktur einer c#-Quelldatei: Zeilen Abschluss Zeichen (ZeilenAbschluss Zeichen), Leerraum (Leerraum), Kommentare (Kommentare), Token (Token) und Vorverarbeitungs Direktiven (Vorverarbeitungs Direktiven).Five basic elements make up the lexical structure of a C# source file: Line terminators (Line terminators), white space (White space), comments (Comments), tokens (Tokens), and pre-processing directives (Pre-processing directives). Von diesen grundlegenden Elementen sind nur Token in der syntaktischen Grammatik eines c#-Programms (syntaktische Grammatik) von Bedeutung.Of these basic elements, only tokens are significant in the syntactic grammar of a C# program (Syntactic grammar).

Die lexikalische Verarbeitung einer c#-Quelldatei besteht darin, dass die Datei in eine Sequenz von Token reduziert wird, die zur Eingabe für die syntaktische Analyse wird.The lexical processing of a C# source file consists of reducing the file into a sequence of tokens which becomes the input to the syntactic analysis. Zeilen Abschluss Zeichen, Leerzeichen und Kommentare können für separate Token dienen, und Vorverarbeitungs Direktiven können dazu führen, dass Abschnitte der Quelldatei übersprungen werden. andernfalls haben diese lexikalischen Elemente keinerlei Auswirkung auf die syntaktische Struktur eines c#-Programms.Line terminators, white space, and comments can serve to separate tokens, and pre-processing directives can cause sections of the source file to be skipped, but otherwise these lexical elements have no impact on the syntactic structure of a C# program.

Bei interpoliert-Zeichen folgen Literalen (interpoliert Zeichen folgen Literale) wird zunächst ein einzelnes Token von der lexikalischen Analyse erstellt, aber in mehrere Eingabeelemente unterteilt, die wiederholt der lexikalischen Analyse unterzogen werden, bis alle interpoliert-Zeichen folgen Literale aufgelöst wurden.In the case of interpolated string literals (Interpolated string literals) a single token is initially produced by lexical analysis, but is broken up into several input elements which are repeatedly subjected to lexical analysis until all interpolated string literals have been resolved. Die resultierenden Token dienen dann als Eingabe für die syntaktische Analyse.The resulting tokens then serve as input to the syntactic analysis.

Wenn mehrere lexikalische Grammatik Produktionen einer Sequenz von Zeichen in einer Quelldatei entsprechen, bildet die lexikalische Verarbeitung immer das längstmögliche lexikalische Element.When several lexical grammar productions match a sequence of characters in a source file, the lexical processing always forms the longest possible lexical element. Beispielsweise wird die Zeichenfolge // als Anfang eines einzeiligen Kommentars verarbeitet, da dieses lexikalische Element länger als ein einzelnes Token ist / .For example, the character sequence // is processed as the beginning of a single-line comment because that lexical element is longer than a single / token.

Zeilen Abschluss ZeichenLine terminators

Zeilen Abschluss Zeichen teilen die Zeichen einer c#-Quelldatei in Zeilen auf.Line terminators divide the characters of a C# source file into lines.

new_line
    : '<Carriage return character (U+000D)>'
    | '<Line feed character (U+000A)>'
    | '<Carriage return character (U+000D) followed by line feed character (U+000A)>'
    | '<Next line character (U+0085)>'
    | '<Line separator character (U+2028)>'
    | '<Paragraph separator character (U+2029)>'
    ;

Aus Gründen der Kompatibilität mit Tools zur Quell Code Bearbeitung, die Dateiendemarker hinzufügen und eine Quelldatei als Sequenz von ordnungsgemäß beendeten Zeilen angezeigt werden können, werden die folgenden Transformationen in der entsprechenden Reihenfolge auf jede Quelldatei in einem c#-Programm angewendet:For compatibility with source code editing tools that add end-of-file markers, and to enable a source file to be viewed as a sequence of properly terminated lines, the following transformations are applied, in order, to every source file in a C# program:

  • Wenn das letzte Zeichen der Quelldatei ein Control-Z-Zeichen ( U+001A ) ist, wird dieses Zeichen gelöscht.If the last character of the source file is a Control-Z character (U+001A), this character is deleted.
  • Ein Wagen Rücklauf Zeichen ( U+000D ) wird am Ende der Quelldatei hinzugefügt, wenn diese Quelldatei nicht leer ist, und wenn das letzte Zeichen der Quelldatei kein Wagen Rücklauf Zeichen ( U+000D ), ein Zeilenvorschub ( U+000A ), ein Zeilen Trennzeichen ( U+2028 ) oder ein Absatz Trennzeichen ( U+2029 ) ist.A carriage-return character (U+000D) is added to the end of the source file if that source file is non-empty and if the last character of the source file is not a carriage return (U+000D), a line feed (U+000A), a line separator (U+2028), or a paragraph separator (U+2029).

KommentareComments

Es werden zwei Arten von Kommentaren unterstützt: einzeilige Kommentare und durch Trennzeichen getrennte Kommentare.Two forms of comments are supported: single-line comments and delimited comments.\ Einzeilige Kommentare _ beginnen mit den Zeichen // und erweitern bis zum Ende der Quellzeile.\ Single-line comments _ start with the characters // and extend to the end of the source line. Durch Trennzeichen getrennte _Kommentare_ beginnen mit den Zeichen /_ und enden mit den Zeichen */ .Delimited comments start with the characters /_ and end with the characters */. Durch Trennzeichen getrennte Kommentare können mehrere Zeilen umfassen.Delimited comments may span multiple lines.

comment
    : single_line_comment
    | delimited_comment
    ;

single_line_comment
    : '//' input_character*
    ;

input_character
    : '<Any Unicode character except a new_line_character>'
    ;

new_line_character
    : '<Carriage return character (U+000D)>'
    | '<Line feed character (U+000A)>'
    | '<Next line character (U+0085)>'
    | '<Line separator character (U+2028)>'
    | '<Paragraph separator character (U+2029)>'
    ;

delimited_comment
    : '/*' delimited_comment_section* asterisk+ '/'
    ;

delimited_comment_section
    : '/'
    | asterisk* not_slash_or_asterisk
    ;

asterisk
    : '*'
    ;

not_slash_or_asterisk
    : '<Any Unicode character except / or *>'
    ;

Kommentare werden nicht geschachtelt.Comments do not nest. Die Zeichen folgen /* und */ haben keine besondere Bedeutung innerhalb eines // Kommentars, und die Zeichen folgen // und /* haben keine besondere Bedeutung in einem durch Trennzeichen getrennten Kommentar.The character sequences /* and */ have no special meaning within a // comment, and the character sequences // and /* have no special meaning within a delimited comment.

Kommentare werden nicht innerhalb von Zeichen-und Zeichen folgen literalen verarbeitet.Comments are not processed within character and string literals.

Das BeispielThe example

/* Hello, world program
   This program writes "hello, world" to the console
*/
class Hello
{
    static void Main() {
        System.Console.WriteLine("hello, world");
    }
}

enthält einen durch Trennzeichen getrennten Kommentar.includes a delimited comment.

Das BeispielThe example

// Hello, world program
// This program writes "hello, world" to the console
//
class Hello // any name will do for this class
{
    static void Main() { // this method must be named "Main"
        System.Console.WriteLine("hello, world");
    }
}

enthält mehrere einzeilige Kommentare.shows several single-line comments.

LeerzeichenWhite space

Leerraum ist als beliebiges Zeichen mit Unicode-Klassen-ZS (einschließlich Leerzeichen) sowie dem horizontalen Tabstopp Zeichen, dem vertikalen Tabstopp Zeichen und dem Formular Vorschub Zeichen definiert.White space is defined as any character with Unicode class Zs (which includes the space character) as well as the horizontal tab character, the vertical tab character, and the form feed character.

whitespace
    : '<Any character with Unicode class Zs>'
    | '<Horizontal tab character (U+0009)>'
    | '<Vertical tab character (U+000B)>'
    | '<Form feed character (U+000C)>'
    ;

TokenTokens

Es gibt mehrere Arten von Token: Bezeichner, Schlüsselwörter, Literale, Operatoren und Satzzeichen.There are several kinds of tokens: identifiers, keywords, literals, operators, and punctuators. Leerzeichen und Kommentare sind keine Token, obwohl Sie als Trennzeichen für Token fungieren.White space and comments are not tokens, though they act as separators for tokens.

token
    : identifier
    | keyword
    | integer_literal
    | real_literal
    | character_literal
    | string_literal
    | interpolated_string_literal
    | operator_or_punctuator
    ;

Unicode-EscapesequenzenUnicode character escape sequences

Eine Unicode-Escapesequenz stellt ein Unicode-Zeichen dar.A Unicode character escape sequence represents a Unicode character. Escapesequenzen von Unicode-Zeichen werden in bezeichern (bezeichern), Zeichen Literalen (Zeichen literalen) und regulären Zeichen folgen Literalen (Zeichen folgen Literale) verarbeitet.Unicode character escape sequences are processed in identifiers (Identifiers), character literals (Character literals), and regular string literals (String literals). Eine Unicode-Escapesequenz wird an keinem anderen Speicherort verarbeitet (z. b. zum bilden eines Operators, eines interpunterators oder eines Schlüssel Worts).A Unicode character escape is not processed in any other location (for example, to form an operator, punctuator, or keyword).

unicode_escape_sequence
    : '\\u' hex_digit hex_digit hex_digit hex_digit
    | '\\U' hex_digit hex_digit hex_digit hex_digit hex_digit hex_digit hex_digit hex_digit
    ;

Eine Unicode-Escapesequenz stellt das einzelne Unicode-Zeichen dar, das durch die hexadezimal Zahl nach den \u Zeichen "" oder "" gebildet wird \U .A Unicode escape sequence represents the single Unicode character formed by the hexadecimal number following the "\u" or "\U" characters. Da in c# eine 16-Bit-Codierung von Unicode-Code Punkten in Zeichen und Zeichen folgen Werten verwendet wird, ist ein Unicode-Zeichen im Bereich u + 10000 bis U + 10FFFF in einem Zeichenliterals nicht zulässig und wird mit einem Unicode-Ersatz Zeichenpaar in einem Zeichenfolgenliteralzeichen dargestellt.Since C# uses a 16-bit encoding of Unicode code points in characters and string values, a Unicode character in the range U+10000 to U+10FFFF is not permitted in a character literal and is represented using a Unicode surrogate pair in a string literal. Unicode-Zeichen mit Code Punkten oberhalb von 0x10FFFF werden nicht unterstützt.Unicode characters with code points above 0x10FFFF are not supported.

Es werden nicht mehrere Übersetzungen ausgeführt.Multiple translations are not performed. Beispielsweise entspricht das Zeichen folgen Literalzeichen "" \u005Cu005C \u005C anstelle von "" \ .For instance, the string literal "\u005Cu005C" is equivalent to "\u005C" rather than "\". Der Unicode-Wert \u005C ist das Zeichen " \ ".The Unicode value \u005C is the character "\".

Das BeispielThe example

class Class1
{
    static void Test(bool \u0066) {
        char c = '\u0066';
        if (\u0066)
            System.Console.WriteLine(c.ToString());
    }        
}

zeigt verschiedene Verwendungen von \u0066 , d. h. die Escapesequenz für den Buchstaben " f ".shows several uses of \u0066, which is the escape sequence for the letter "f". Das Programm entsprichtThe program is equivalent to

class Class1
{
    static void Test(bool f) {
        char c = 'f';
        if (f)
            System.Console.WriteLine(c.ToString());
    }        
}

BezeichnerIdentifiers

Die Regeln für Bezeichner, die in diesem Abschnitt angegeben sind, entsprechen genau den Regeln, die vom Unicode-Standard Anhang 31 empfohlen werden, mit dem Unterschied, dass Unterstriche als Ausgangs Zeichen zulässig sind (wie es in der C-Programmiersprache üblich ist), Unicode-Escapesequenzen sind in bezeichlen zulässig, und das @ Zeichen "" ist als Präfix zulässigThe rules for identifiers given in this section correspond exactly to those recommended by the Unicode Standard Annex 31, except that underscore is allowed as an initial character (as is traditional in the C programming language), Unicode escape sequences are permitted in identifiers, and the "@" character is allowed as a prefix to enable keywords to be used as identifiers.

identifier
    : available_identifier
    | '@' identifier_or_keyword
    ;

available_identifier
    : '<An identifier_or_keyword that is not a keyword>'
    ;

identifier_or_keyword
    : identifier_start_character identifier_part_character*
    ;

identifier_start_character
    : letter_character
    | '_'
    ;

identifier_part_character
    : letter_character
    | decimal_digit_character
    | connecting_character
    | combining_character
    | formatting_character
    ;

letter_character
    : '<A Unicode character of classes Lu, Ll, Lt, Lm, Lo, or Nl>'
    | '<A unicode_escape_sequence representing a character of classes Lu, Ll, Lt, Lm, Lo, or Nl>'
    ;

combining_character
    : '<A Unicode character of classes Mn or Mc>'
    | '<A unicode_escape_sequence representing a character of classes Mn or Mc>'
    ;

decimal_digit_character
    : '<A Unicode character of the class Nd>'
    | '<A unicode_escape_sequence representing a character of the class Nd>'
    ;

connecting_character
    : '<A Unicode character of the class Pc>'
    | '<A unicode_escape_sequence representing a character of the class Pc>'
    ;

formatting_character
    : '<A Unicode character of the class Cf>'
    | '<A unicode_escape_sequence representing a character of the class Cf>'
    ;

Informationen zu den oben erwähnten Unicode-Zeichenklassen finden Sie im Unicode-Standard, Version 3,0, Abschnitt 4,5.For information on the Unicode character classes mentioned above, see The Unicode Standard, Version 3.0, section 4.5.

Beispiele für gültige Bezeichner sind " identifier1 ", " _identifier2 " und " @if ".Examples of valid identifiers include "identifier1", "_identifier2", and "@if".

Ein Bezeichner in einem übereinstimmenden Programm muss das kanonische Format aufweisen, das durch die Unicode-normalisierungs Form C definiert ist, wie im Unicode-Standard Anhang 15 definiertAn identifier in a conforming program must be in the canonical format defined by Unicode Normalization Form C, as defined by Unicode Standard Annex 15. Das Verhalten beim Auffinden eines Bezeichners, der nicht in der normalisierungs Form C vorliegt, ist Implementierungs definiert. eine Diagnose ist jedoch nicht erforderlich.The behavior when encountering an identifier not in Normalization Form C is implementation-defined; however, a diagnostic is not required.

Das-Präfix " @ " ermöglicht die Verwendung von Schlüsselwörtern als Bezeichner, was bei der Schnittstellen mit anderen Programmiersprachen nützlich ist.The prefix "@" enables the use of keywords as identifiers, which is useful when interfacing with other programming languages. Das Zeichen @ ist nicht Teil des Bezeichners, daher kann der Bezeichner in anderen Sprachen als normaler Bezeichner ohne das Präfix angezeigt werden.The character @ is not actually part of the identifier, so the identifier might be seen in other languages as a normal identifier, without the prefix. Ein Bezeichner mit einem @ Präfix wird als ausführlicher Bezeichner bezeichnet.An identifier with an @ prefix is called a verbatim identifier. Die Verwendung des @ Präfix für Bezeichner, bei denen es sich nicht um Schlüsselwörter handelt, ist zulässig, aber es wird dringend davon abgeraten.Use of the @ prefix for identifiers that are not keywords is permitted, but strongly discouraged as a matter of style.

Beispiel:The example:

class @class
{
    public static void @static(bool @bool) {
        if (@bool)
            System.Console.WriteLine("true");
        else
            System.Console.WriteLine("false");
    }    
}

class Class1
{
    static void M() {
        cl\u0061ss.st\u0061tic(true);
    }
}

definiert eine Klasse mit dem Namen " class " mit einer statischen Methode mit dem Namen "" static , die einen Parameter mit dem Namen " bool " annimmt.defines a class named "class" with a static method named "static" that takes a parameter named "bool". Beachten Sie, dass das Token "" ein Bezeichner ist, da Unicode-Escapezeichen in Schlüsselwörtern nicht zulässig sind cl\u0061ss und denselben Bezeichner wie " @class " haben.Note that since Unicode escapes are not permitted in keywords, the token "cl\u0061ss" is an identifier, and is the same identifier as "@class".

Zwei Bezeichner werden als identisch angesehen, wenn Sie nach dem Anwenden der folgenden Transformationen identisch sind:Two identifiers are considered the same if they are identical after the following transformations are applied, in order:

  • Wenn Sie verwendet wird, wird das Präfix " @ " entfernt.The prefix "@", if used, is removed.
  • Jede unicode_escape_sequence wird in das entsprechende Unicode-Zeichen transformiert.Each unicode_escape_sequence is transformed into its corresponding Unicode character.
  • Alle formatting_character s werden entfernt.Any formatting_character s are removed.

Bezeichner, die zwei aufeinander folgende Unterstriche () enthalten, U+005F sind für die Verwendung durch die-Implementierung reserviert.Identifiers containing two consecutive underscore characters (U+005F) are reserved for use by the implementation. Beispielsweise kann eine-Implementierung erweiterte Schlüsselwörter bereitstellen, die mit zwei unterstrichen beginnen.For example, an implementation might provide extended keywords that begin with two underscores.

KeywordsKeywords

Ein Schlüsselwort ist eine bezeichnerartige Zeichenfolge, die reserviert ist und nicht als Bezeichner verwendet werden kann, es sei denn, das Zeichen wird vorangestellt @ .A keyword is an identifier-like sequence of characters that is reserved, and cannot be used as an identifier except when prefaced by the @ character.

keyword
    : 'abstract' | 'as'       | 'base'       | 'bool'      | 'break'
    | 'byte'     | 'case'     | 'catch'      | 'char'      | 'checked'
    | 'class'    | 'const'    | 'continue'   | 'decimal'   | 'default'
    | 'delegate' | 'do'       | 'double'     | 'else'      | 'enum'
    | 'event'    | 'explicit' | 'extern'     | 'false'     | 'finally'
    | 'fixed'    | 'float'    | 'for'        | 'foreach'   | 'goto'
    | 'if'       | 'implicit' | 'in'         | 'int'       | 'interface'
    | 'internal' | 'is'       | 'lock'       | 'long'      | 'namespace'
    | 'new'      | 'null'     | 'object'     | 'operator'  | 'out'
    | 'override' | 'params'   | 'private'    | 'protected' | 'public'
    | 'readonly' | 'ref'      | 'return'     | 'sbyte'     | 'sealed'
    | 'short'    | 'sizeof'   | 'stackalloc' | 'static'    | 'string'
    | 'struct'   | 'switch'   | 'this'       | 'throw'     | 'true'
    | 'try'      | 'typeof'   | 'uint'       | 'ulong'     | 'unchecked'
    | 'unsafe'   | 'ushort'   | 'using'      | 'virtual'   | 'void'
    | 'volatile' | 'while'
    ;

An manchen Stellen in der Grammatik haben bestimmte Bezeichner eine besondere Bedeutung, aber keine Schlüsselwörter.In some places in the grammar, specific identifiers have special meaning, but are not keywords. Solche Bezeichner werden manchmal als "kontextabhängige Schlüsselwörter" bezeichnet.Such identifiers are sometimes referred to as "contextual keywords". In einer Eigenschafts Deklaration get haben die Bezeichner "" und " set " z. b. eine besondere Bedeutung (Accessoren).For example, within a property declaration, the "get" and "set" identifiers have special meaning (Accessors). Ein anderer Bezeichner als get oder set ist in diesen Speicherorten nie zulässig, sodass diese Verwendung nicht mit der Verwendung dieser Wörter als Bezeichner in Konflikt steht.An identifier other than get or set is never permitted in these locations, so this use does not conflict with a use of these words as identifiers. In anderen Fällen, z. b. mit dem Bezeichner " var " in implizit typisierten lokalen Variablen Deklarationen (lokale Variablen Deklarationen), kann ein Kontext Schlüsselwort mit deklarierten Namen in Konflikt stehen.In other cases, such as with the identifier "var" in implicitly typed local variable declarations (Local variable declarations), a contextual keyword can conflict with declared names. In solchen Fällen hat der deklarierte Name Vorrang vor der Verwendung des Bezeichners als kontextbezogenes Schlüsselwort.In such cases, the declared name takes precedence over the use of the identifier as a contextual keyword.

LiteraleLiterals

Ein Literal ist die Quellcodedarstellung eines Werts.A literal is a source code representation of a value.

literal
    : boolean_literal
    | integer_literal
    | real_literal
    | character_literal
    | string_literal
    | null_literal
    ;

Boolesche LiteraleBoolean literals

Es gibt zwei boolesche Literalwerte: true und false .There are two boolean literal values: true and false.

boolean_literal
    : 'true'
    | 'false'
    ;

Der Typ eines boolean_literal ist bool .The type of a boolean_literal is bool.

GanzzahlenliteralInteger literals

Ganzzahlige Literale werden verwendet, um Werte der Typen int , uint , und zu schreiben long ulong .Integer literals are used to write values of types int, uint, long, and ulong. Ganzzahlige Literale haben zwei mögliche Formen: decimal und hexadezimal.Integer literals have two possible forms: decimal and hexadecimal.

integer_literal
    : decimal_integer_literal
    | hexadecimal_integer_literal
    ;

decimal_integer_literal
    : decimal_digit+ integer_type_suffix?
    ;

decimal_digit
    : '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
    ;

integer_type_suffix
    : 'U' | 'u' | 'L' | 'l' | 'UL' | 'Ul' | 'uL' | 'ul' | 'LU' | 'Lu' | 'lU' | 'lu'
    ;

hexadecimal_integer_literal
    : '0x' hex_digit+ integer_type_suffix?
    | '0X' hex_digit+ integer_type_suffix?
    ;

hex_digit
    : '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
    | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'a' | 'b' | 'c' | 'd' | 'e' | 'f';

Der Typ eines ganzzahligen Literals wird wie folgt bestimmt:The type of an integer literal is determined as follows:

  • Wenn das Literale kein Suffix aufweist, verfügt es über den ersten dieser Typen, in dem sein Wert dargestellt werden kann: int , uint , long , ulong .If the literal has no suffix, it has the first of these types in which its value can be represented: int, uint, long, ulong.
  • Wenn das Literale von oder als Suffix versehen wird U u , verfügt es über den ersten dieser Typen, in dem sein Wert dargestellt werden kann: uint , ulong .If the literal is suffixed by U or u, it has the first of these types in which its value can be represented: uint, ulong.
  • Wenn das Literale von oder als Suffix versehen wird L l , verfügt es über den ersten dieser Typen, in dem sein Wert dargestellt werden kann: long , ulong .If the literal is suffixed by L or l, it has the first of these types in which its value can be represented: long, ulong.
  • Wenn das Literale von UL , Ul , uL , ul , LU ,, oder suffixt wird Lu lU lu , ist es vom Typ ulong .If the literal is suffixed by UL, Ul, uL, ul, LU, Lu, lU, or lu, it is of type ulong.

Wenn der durch ein Ganzzahlliteral dargestellte Wert außerhalb des Bereichs des ulong Typs liegt, tritt ein Kompilierzeitfehler auf.If the value represented by an integer literal is outside the range of the ulong type, a compile-time error occurs.

Es wird empfohlen, L l beim Schreiben von literalen des Typs "" anstelle von "" long zu verwenden, da es einfach ist, den Buchstaben " l " mit der Ziffer "" zu verwechseln 1 .As a matter of style, it is suggested that "L" be used instead of "l" when writing literals of type long, since it is easy to confuse the letter "l" with the digit "1".

Um zuzulassen, dass die kleinsten möglichen int long Werte und als Dezimale ganzzahlige Literale geschrieben werden, sind die folgenden zwei Regeln vorhanden:To permit the smallest possible int and long values to be written as decimal integer literals, the following two rules exist:

  • Wenn eine decimal_integer_literal mit dem Wert 2147483648 (2 ^ 31) und kein integer_type_suffix als das Token unmittelbar nach einem unären Minus Operator Token (unärer Minus Operator) angezeigt wird, ist das Ergebnis eine Konstante vom Typ int mit dem Wert-2147483648 (-2 ^ 31).When a decimal_integer_literal with the value 2147483648 (2^31) and no integer_type_suffix appears as the token immediately following a unary minus operator token (Unary minus operator), the result is a constant of type int with the value -2147483648 (-2^31). In allen anderen Fällen ist eine solche decimal_integer_literal vom Typ uint .In all other situations, such a decimal_integer_literal is of type uint.
  • Wenn ein decimal_integer_literal mit dem Wert 9.223.372.036.854.775.808 (2 ^ 63) und kein integer_type_suffix oder die integer_type_suffix L oder l als Token unmittelbar nach einem unären Minus Operator Token (unärer Minus Operator) angezeigt wird, ist das Ergebnis eine Konstante vom Typ long mit dem Wert-9.223.372.036.854.775.808 (-2 ^ 63).When a decimal_integer_literal with the value 9223372036854775808 (2^63) and no integer_type_suffix or the integer_type_suffix L or l appears as the token immediately following a unary minus operator token (Unary minus operator), the result is a constant of type long with the value -9223372036854775808 (-2^63). In allen anderen Fällen ist eine solche decimal_integer_literal vom Typ ulong .In all other situations, such a decimal_integer_literal is of type ulong.

Real-LiteraleReal literals

Echte Literale werden verwendet, um Werte der Typen float , double und zu schreiben decimal .Real literals are used to write values of types float, double, and decimal.

real_literal
    : decimal_digit+ '.' decimal_digit+ exponent_part? real_type_suffix?
    | '.' decimal_digit+ exponent_part? real_type_suffix?
    | decimal_digit+ exponent_part real_type_suffix?
    | decimal_digit+ real_type_suffix
    ;

exponent_part
    : 'e' sign? decimal_digit+
    | 'E' sign? decimal_digit+
    ;

sign
    : '+'
    | '-'
    ;

real_type_suffix
    : 'F' | 'f' | 'D' | 'd' | 'M' | 'm'
    ;

Wenn keine real_type_suffix angegeben wird, ist der Typ des echten Literals double .If no real_type_suffix is specified, the type of the real literal is double. Andernfalls bestimmt das echte Typsuffix den Typ des echten Literals wie folgt:Otherwise, the real type suffix determines the type of the real literal, as follows:

  • Ein echtes LiteralSuffix, das von F oder f ist, ist vom Typ float .A real literal suffixed by F or f is of type float. Die Literale 1f ,, 1.5f 1e10f und sind z. b 123.456F . vom Typ float .For example, the literals 1f, 1.5f, 1e10f, and 123.456F are all of type float.
  • Ein echtes LiteralSuffix, das von D oder d ist, ist vom Typ double .A real literal suffixed by D or d is of type double. Die Literale 1d ,, 1.5d 1e10d und sind z. b 123.456D . vom Typ double .For example, the literals 1d, 1.5d, 1e10d, and 123.456D are all of type double.
  • Ein echtes LiteralSuffix, das von M oder m ist, ist vom Typ decimal .A real literal suffixed by M or m is of type decimal. Die Literale 1m ,, 1.5m 1e10m und sind z. b 123.456M . vom Typ decimal .For example, the literals 1m, 1.5m, 1e10m, and 123.456M are all of type decimal. Diese Literale werden in einen- decimal Wert konvertiert, indem der genaue Wert verwendet wird, und, falls erforderlich, auf den nächstgelegenen darstellbaren Wert mit der-Rundung (dem Decimal-Typ) gerundet.This literal is converted to a decimal value by taking the exact value, and, if necessary, rounding to the nearest representable value using banker's rounding (The decimal type). Alle in der Literale sichtbaren Skalierungen bleiben erhalten, es sei denn, der Wert ist gerundet, oder der Wert ist NULL (in letzterem Fall ist das Vorzeichen und die Dezimalstellen 0).Any scale apparent in the literal is preserved unless the value is rounded or the value is zero (in which latter case the sign and scale will be 0). Daher wird das Literale 2.900m analysiert, um das Dezimaltrennzeichen, den 0 Koeffizienten und die Skala zu bilden 2900 3 .Hence, the literal 2.900m will be parsed to form the decimal with sign 0, coefficient 2900, and scale 3.

Wenn das angegebene Literale nicht im angegebenen Typ dargestellt werden kann, tritt ein Kompilierzeitfehler auf.If the specified literal cannot be represented in the indicated type, a compile-time error occurs.

Der Wert eines echten Literals vom Typ float oder double wird mit dem IEEE-Modus "Round to Next" bestimmt.The value of a real literal of type float or double is determined by using the IEEE "round to nearest" mode.

Beachten Sie, dass in einem echten Literalzeichen nach dem Dezimaltrennzeichen immer Dezimalstellen erforderlich sind.Note that in a real literal, decimal digits are always required after the decimal point. Beispielsweise 1.3F ist ein echtes Literalzeichen, aber 1.F nicht.For example, 1.3F is a real literal but 1.F is not.

ZeichenliteraleCharacter literals

Ein Zeichenliteral stellt ein einzelnes Zeichen dar und besteht normalerweise aus einem Zeichen in Anführungszeichen, wie in 'a' .A character literal represents a single character, and usually consists of a character in quotes, as in 'a'.

Hinweis: die Grammatik-Notation von antlr macht folgendes verwirrend!Note: The ANTLR grammar notation makes the following confusing! Wenn Sie in antlr schreiben, \' steht es für ein einzelnes Anführungszeichen ' .In ANTLR, when you write \' it stands for a single quote '. Und wenn Sie schreiben, \\ steht ein einzelner umgekehrter Schrägstrich \ .And when you write \\ it stands for a single backslash \. Daher bedeutet die erste Regel für ein Zeichenliteral, dass Sie mit einem einfachen Anführungszeichen, einem Zeichen und einem einfachen Anführungszeichen beginnt.Therefore the first rule for a character literal means it starts with a single quote, then a character, then a single quote. Und die elf möglichen einfachen Escapesequenzen sind \' , \" , \\ , \0 , \a , \b , \f , \n , \r , \t , \v .And the eleven possible simple escape sequences are \', \", \\, \0, \a, \b, \f, \n, \r, \t, \v.

character_literal
    : '\'' character '\''
    ;

character
    : single_character
    | simple_escape_sequence
    | hexadecimal_escape_sequence
    | unicode_escape_sequence
    ;

single_character
    : '<Any character except \' (U+0027), \\ (U+005C), and new_line_character>'
    ;

simple_escape_sequence
    : '\\\'' | '\\"' | '\\\\' | '\\0' | '\\a' | '\\b' | '\\f' | '\\n' | '\\r' | '\\t' | '\\v'
    ;

hexadecimal_escape_sequence
    : '\\x' hex_digit hex_digit? hex_digit? hex_digit?;

Ein Zeichen, das einem umgekehrten Schrägstrich ( \ ) in einem Zeichen folgt, muss eines der folgenden Zeichen sein: ' , " , \ , 0 , a , b , f , n , r , t , u , U , x , v .A character that follows a backslash character (\) in a character must be one of the following characters: ', ", \, 0, a, b, f, n, r, t, u, U, x, v. Andernfalls tritt ein Kompilierungsfehler auf.Otherwise, a compile-time error occurs.

Eine hexadezimale Escapesequenz stellt ein einzelnes Unicode-Zeichen dar, wobei der Wert durch die hexadezimale Zahl nach "" gebildet wird \x .A hexadecimal escape sequence represents a single Unicode character, with the value formed by the hexadecimal number following "\x".

Wenn der Wert, der von einem Zeichenliterals dargestellt wird, größer als ist U+FFFF , tritt ein Kompilierzeitfehler auf.If the value represented by a character literal is greater than U+FFFF, a compile-time error occurs.

Eine Unicode-Escapesequenz (Escapesequenzen fürUnicode-Zeichen) in einem Zeichenliterals muss im Bereich U+0000 von liegen U+FFFF .A Unicode character escape sequence (Unicode character escape sequences) in a character literal must be in the range U+0000 to U+FFFF.

Eine einfache Escapesequenz stellt eine Unicode-Zeichencodierung dar, wie in der folgenden Tabelle beschrieben.A simple escape sequence represents a Unicode character encoding, as described in the table below.

EscapesequenzEscape sequence ZeichennameCharacter name Unicode-CodierungUnicode encoding
\' Einfaches AnführungszeichenSingle quote 0x0027
\" Doppeltes AnführungszeichenDouble quote 0x0022
\\ Umgekehrter SchrägstrichBackslash 0x005C
\0 NullNull 0x0000
\a WarnungAlert 0x0007
\b RücktasteBackspace 0x0008
\f SeitenvorschubForm feed 0x000C
\n ZeilenwechselNew line 0x000A
\r WagenrücklaufCarriage return 0x000D
\t Horizontaler TabulatorHorizontal tab 0x0009
\v Vertikaler TabulatorVertical tab 0x000B

Der Typ eines character_literal ist char .The type of a character_literal is char.

ZeichenfolgenliteraleString literals

C# unterstützt zwei Formen von Zeichenfolgenliteralen: *reguläre Zeichenfolge Literale _ und _ ausführliche Zeichen folgen Literale *.C# supports two forms of string literals: regular string literals _ and _verbatim string literals**.

Ein reguläres Zeichenfolgenliterale besteht aus null oder mehr Zeichen, die in doppelten Anführungszeichen eingeschlossen sind, wie z. b., und kann sowohl einfache Escapesequenzen (z. b. "hello" \t für das Tabstopp Zeichen) als auch hexadezimale undA regular string literal consists of zero or more characters enclosed in double quotes, as in "hello", and may include both simple escape sequences (such as \t for the tab character), and hexadecimal and Unicode escape sequences.

Ein ausführlichen Zeichenfolgenliterals besteht aus einem @ Zeichen, gefolgt von einem doppelten Anführungszeichen, NULL oder mehr Zeichen und einem schließenden doppelten Anführungszeichen.A verbatim string literal consists of an @ character followed by a double-quote character, zero or more characters, and a closing double-quote character. Ein einfaches Beispiel ist @"hello" .A simple example is @"hello". In einem ausführlichen zeichenfolgenliteralliteralen werden die Zeichen zwischen den Trennzeichen wörtlich interpretiert, die einzige Ausnahme ist eine quote_escape_sequence.In a verbatim string literal, the characters between the delimiters are interpreted verbatim, the only exception being a quote_escape_sequence. Insbesondere einfache Escapesequenzen und hexadezimale und Unicode-Escapesequenzen werden in ausführlichen Zeichenfolgenliteralen nicht verarbeitet.In particular, simple escape sequences, and hexadecimal and Unicode escape sequences are not processed in verbatim string literals. Ein ausführlicher zeichenfolgenliteralvorgang kann mehrere Zeilen umfassen.A verbatim string literal may span multiple lines.

string_literal
    : regular_string_literal
    | verbatim_string_literal
    ;

regular_string_literal
    : '"' regular_string_literal_character* '"'
    ;

regular_string_literal_character
    : single_regular_string_literal_character
    | simple_escape_sequence
    | hexadecimal_escape_sequence
    | unicode_escape_sequence
    ;

single_regular_string_literal_character
    : '<Any character except " (U+0022), \\ (U+005C), and new_line_character>'
    ;

verbatim_string_literal
    : '@"' verbatim_string_literal_character* '"'
    ;

verbatim_string_literal_character
    : single_verbatim_string_literal_character
    | quote_escape_sequence
    ;

single_verbatim_string_literal_character
    : '<any character except ">'
    ;

quote_escape_sequence
    : '""'
    ;

Ein Zeichen, das einem umgekehrten Schrägstrich ( \ ) in einem regular_string_literal_character folgt, muss eines der folgenden Zeichen sein: ' , " , \ , 0 , a , b , f , n , r , t ,,, u U x , v .A character that follows a backslash character (\) in a regular_string_literal_character must be one of the following characters: ', ", \, 0, a, b, f, n, r, t, u, U, x, v. Andernfalls tritt ein Kompilierungsfehler auf.Otherwise, a compile-time error occurs.

Das BeispielThe example

string a = "hello, world";                   // hello, world
string b = @"hello, world";                  // hello, world

string c = "hello \t world";                 // hello      world
string d = @"hello \t world";                // hello \t world

string e = "Joe said \"Hello\" to me";       // Joe said "Hello" to me
string f = @"Joe said ""Hello"" to me";      // Joe said "Hello" to me

string g = "\\\\server\\share\\file.txt";    // \\server\share\file.txt
string h = @"\\server\share\file.txt";       // \\server\share\file.txt

string i = "one\r\ntwo\r\nthree";
string j = @"one
two
three";

zeigt eine Vielzahl von Zeichenfolgenliteralen an.shows a variety of string literals. Das letzte Zeichenfolgenliterale, j , ist ein ausführlicher Zeichenfolgenliteral, das mehrere ZeilenThe last string literal, j, is a verbatim string literal that spans multiple lines. Die Zeichen zwischen den Anführungszeichen, einschließlich Leerzeichen, z. b. neue Zeilenzeichen, werden wörtlich beibehalten.The characters between the quotation marks, including white space such as new line characters, are preserved verbatim.

Da eine hexadezimale Escapesequenz eine Variable Anzahl von hexadezimalen Ziffern aufweisen kann, enthält das Zeichenfolgenliterale "\x123" ein einzelnes Zeichen 123 mit dem hexadeziSince a hexadecimal escape sequence can have a variable number of hex digits, the string literal "\x123" contains a single character with hex value 123. Um eine Zeichenfolge zu erstellen, die das Zeichen mit dem Hexadezimalwert 12 gefolgt vom Zeichen 3 enthält, könnte ein "\x00123" oder stattdessen geschrieben werden "\x12" + "3" .To create a string containing the character with hex value 12 followed by the character 3, one could write "\x00123" or "\x12" + "3" instead.

Der Typ eines string_literal ist string .The type of a string_literal is string.

Jedes Zeichenfolgenliterale führt nicht unbedingt zu einer neuen Zeichen folgen Instanz.Each string literal does not necessarily result in a new string instance. Wenn zwei oder mehr Zeichen folgen Literale, die gemäß dem Zeichen folgen Gleichheits Operator (Zeichen folgen Gleichheits Operatoren) gleichwertig sind, im selben Programm vorkommen, verweisen diese Zeichen folgen Literale auf dieselbe Zeichen folgen Instanz.When two or more string literals that are equivalent according to the string equality operator (String equality operators) appear in the same program, these string literals refer to the same string instance. Beispielsweise die Ausgabe, die vonFor instance, the output produced by

class Test
{
    static void Main() {
        object a = "hello";
        object b = "hello";
        System.Console.WriteLine(a == b);
    }
}

liegt True daran, dass die beiden Literale auf dieselbe Zeichen folgen Instanz verweisen.is True because the two literals refer to the same string instance.

Interpoliert Zeichen folgen LiteraleInterpolated string literals

Interinterpolierte Zeichen folgen Literale ähneln Zeichen folgen Literalen, enthalten jedoch Lücken, die durch und getrennt sind { } , wobei Ausdrücke auftreten können.Interpolated string literals are similar to string literals, but contain holes delimited by { and }, wherein expressions can occur. Zur Laufzeit werden die Ausdrücke so ausgewertet, dass Ihre Text Formulare in der Zeichenfolge an der Stelle, an der die Lücke auftritt, ersetzt werden.At runtime, the expressions are evaluated with the purpose of having their textual forms substituted into the string at the place where the hole occurs. Die Syntax und die Semantik der Zeichen folgen Interpolationen werden im Abschnitt (interpoliertZeichen folgen) beschrieben.The syntax and semantics of string interpolation are described in section (Interpolated strings).

Wie bei Zeichenfolgenliteralen können interpoliert Zeichen folgen Literale entweder regulär oder wörtlich sein.Like string literals, interpolated string literals can be either regular or verbatim. Interpoliert reguläre Zeichenfolgenliterale werden durch $" und getrennt " , und interpoliert, ausführliche Zeichen folgen Literale werden durch $@" und getrennt " .Interpolated regular string literals are delimited by $" and ", and interpolated verbatim string literals are delimited by $@" and ".

Wie bei anderen literalen ergibt die lexikalische Analyse eines interpoliert für interpoliert zunächst ein einzelnes Token, wie gemäß der Grammatik unten.Like other literals, lexical analysis of an interpolated string literal initially results in a single token, as per the grammar below. Vor der syntaktischen Analyse wird jedoch das einzelne Token eines interpoliert-Zeichenfolgenliterals in mehrere Token für die Teile der Zeichenfolge aufgeteilt, die die Löcher einschließen, und die in den Löchern auftretenden Eingabeelemente werden lexikalisch erneut analysiert.However, before syntactic analysis, the single token of an interpolated string literal is broken into several tokens for the parts of the string enclosing the holes, and the input elements occurring in the holes are lexically analysed again. Dies kann wiederum dazu führen, dass mehr interinterpolierte Zeichenfolgenliterale verarbeitet werden, die verarbeitet werden können, aber wenn lexikalisch korrekt ist, führt letztendlich zu einer Sequenz von Tokens, damit die syntaktische Analyse verarbeitet wird.This may in turn produce more interpolated string literals to be processed, but, if lexically correct, will eventually lead to a sequence of tokens for syntactic analysis to process.

interpolated_string_literal
    : '$' interpolated_regular_string_literal
    | '$' interpolated_verbatim_string_literal
    ;

interpolated_regular_string_literal
    : interpolated_regular_string_whole
    | interpolated_regular_string_start  interpolated_regular_string_literal_body interpolated_regular_string_end
    ;

interpolated_regular_string_literal_body
    : regular_balanced_text
    | interpolated_regular_string_literal_body interpolated_regular_string_mid regular_balanced_text
    ;

interpolated_regular_string_whole
    : '"' interpolated_regular_string_character* '"'
    ;

interpolated_regular_string_start
    : '"' interpolated_regular_string_character* '{'
    ;

interpolated_regular_string_mid
    : interpolation_format? '}' interpolated_regular_string_characters_after_brace? '{'
    ;

interpolated_regular_string_end
    : interpolation_format? '}' interpolated_regular_string_characters_after_brace? '"'
    ;

interpolated_regular_string_characters_after_brace
    : interpolated_regular_string_character_no_brace
    | interpolated_regular_string_characters_after_brace interpolated_regular_string_character
    ;

interpolated_regular_string_character
    : single_interpolated_regular_string_character
    | simple_escape_sequence
    | hexadecimal_escape_sequence
    | unicode_escape_sequence
    | open_brace_escape_sequence
    | close_brace_escape_sequence
    ;

interpolated_regular_string_character_no_brace
    : '<Any interpolated_regular_string_character except close_brace_escape_sequence and any hexadecimal_escape_sequence or unicode_escape_sequence designating } (U+007D)>'
    ;

single_interpolated_regular_string_character
    : '<Any character except \" (U+0022), \\ (U+005C), { (U+007B), } (U+007D), and new_line_character>'
    ;

open_brace_escape_sequence
    : '{{'
    ;

close_brace_escape_sequence
    : '}}'
    ;
    
regular_balanced_text
    : regular_balanced_text_part+
    ;

regular_balanced_text_part
    : single_regular_balanced_text_character
    | delimited_comment
    | '@' identifier_or_keyword
    | string_literal
    | interpolated_string_literal
    | '(' regular_balanced_text ')'
    | '[' regular_balanced_text ']'
    | '{' regular_balanced_text '}'
    ;
    
single_regular_balanced_text_character
    : '<Any character except / (U+002F), @ (U+0040), \" (U+0022), $ (U+0024), ( (U+0028), ) (U+0029), [ (U+005B), ] (U+005D), { (U+007B), } (U+007D) and new_line_character>'
    | '</ (U+002F), if not directly followed by / (U+002F) or * (U+002A)>'
    ;
    
interpolation_format
    : ':' interpolation_format_character+
    ;
    
interpolation_format_character
    : '<Any character except \" (U+0022), : (U+003A), { (U+007B) and } (U+007D)>'
    ;
    
interpolated_verbatim_string_literal
    : interpolated_verbatim_string_whole
    | interpolated_verbatim_string_start interpolated_verbatim_string_literal_body interpolated_verbatim_string_end
    ;

interpolated_verbatim_string_literal_body
    : verbatim_balanced_text
    | interpolated_verbatim_string_literal_body interpolated_verbatim_string_mid verbatim_balanced_text
    ;
    
interpolated_verbatim_string_whole
    : '@"' interpolated_verbatim_string_character* '"'
    ;
    
interpolated_verbatim_string_start
    : '@"' interpolated_verbatim_string_character* '{'
    ;
    
interpolated_verbatim_string_mid
    : interpolation_format? '}' interpolated_verbatim_string_characters_after_brace? '{'
    ;
    
interpolated_verbatim_string_end
    : interpolation_format? '}' interpolated_verbatim_string_characters_after_brace? '"'
    ;
    
interpolated_verbatim_string_characters_after_brace
    : interpolated_verbatim_string_character_no_brace
    | interpolated_verbatim_string_characters_after_brace interpolated_verbatim_string_character
    ;
    
interpolated_verbatim_string_character
    : single_interpolated_verbatim_string_character
    | quote_escape_sequence
    | open_brace_escape_sequence
    | close_brace_escape_sequence
    ;
    
interpolated_verbatim_string_character_no_brace
    : '<Any interpolated_verbatim_string_character except close_brace_escape_sequence>'
    ;
    
single_interpolated_verbatim_string_character
    : '<Any character except \" (U+0022), { (U+007B) and } (U+007D)>'
    ;
    
verbatim_balanced_text
    : verbatim_balanced_text_part+
    ;

verbatim_balanced_text_part
    : single_verbatim_balanced_text_character
    | comment
    | '@' identifier_or_keyword
    | string_literal
    | interpolated_string_literal
    | '(' verbatim_balanced_text ')'
    | '[' verbatim_balanced_text ']'
    | '{' verbatim_balanced_text '}'
    ;
    
single_verbatim_balanced_text_character
    : '<Any character except / (U+002F), @ (U+0040), \" (U+0022), $ (U+0024), ( (U+0028), ) (U+0029), [ (U+005B), ] (U+005D), { (U+007B) and } (U+007D)>'
    | '</ (U+002F), if not directly followed by / (U+002F) or * (U+002A)>'
    ;

Ein interpolated_string_literal Token wird wie folgt als mehrere Token und andere Eingabeelemente in der Reihenfolge des interpolated_string_literal neu interpretiert:An interpolated_string_literal token is reinterpreted as multiple tokens and other input elements as follows, in order of occurrence in the interpolated_string_literal:

  • Vorkommen der folgenden werden als separate einzelne Token neu interpretiert: das führende $ Vorzeichen, interpolated_regular_string_whole, interpolated_regular_string_start, die interpolated_regular_string_mid, interpolated_regular_string_end, interpolated_verbatim_string_whole, interpolated_verbatim_string_start, interpolated_verbatim_string_mid und interpolated_verbatim_string_end.Occurrences of the following are reinterpreted as separate individual tokens: the leading $ sign, interpolated_regular_string_whole, interpolated_regular_string_start, interpolated_regular_string_mid, interpolated_regular_string_end, interpolated_verbatim_string_whole, interpolated_verbatim_string_start, interpolated_verbatim_string_mid and interpolated_verbatim_string_end.
  • Vorkommen von regular_balanced_text und verbatim_balanced_text dazwischen werden als input_section (lexikalische Analyse) neu verarbeitet und als resultierende Sequenz von Eingabe Elementen interpretiert.Occurrences of regular_balanced_text and verbatim_balanced_text between these are reprocessed as an input_section (Lexical analysis) and are reinterpreted as the resulting sequence of input elements. Diese können wiederum interinterpolierte zeichenfolgenliteraltoken enthalten, die neu interpretiert werden.These may in turn include interpolated string literal tokens to be reinterpreted.

Die syntaktische Analyse kombiniert die Token erneut in eine interpolated_string_expression (interpoliert).Syntactic analysis will recombine the tokens into an interpolated_string_expression (Interpolated strings).

Beispiele TODOExamples TODO

Das NULL-LiteraleThe null literal

null_literal
    : 'null'
    ;

Der null_literal kann implizit in einen Verweistyp oder einen Typ konvertiert werden, der NULL-Werte zulässt.The null_literal can be implicitly converted to a reference type or nullable type.

Operatoren und TrennzeichenOperators and punctuators

Es gibt verschiedene Arten von Operatoren und Trennzeichen.There are several kinds of operators and punctuators. Operatoren werden in Ausdrücken verwendet, um Vorgänge mit einem oder mehreren Operanden zu beschreiben.Operators are used in expressions to describe operations involving one or more operands. Der Ausdruck a + b verwendet beispielsweise den Operator +, um die zwei Operanden a und b hinzuzufügen.For example, the expression a + b uses the + operator to add the two operands a and b. Trennzeichen werden zum Gruppieren und Trennen verwendet.Punctuators are for grouping and separating.

operator_or_punctuator
    : '{'  | '}'  | '['  | ']'  | '('   | ')'  | '.'  | ','  | ':'  | ';'
    | '+'  | '-'  | '*'  | '/'  | '%'   | '&'  | '|'  | '^'  | '!'  | '~'
    | '='  | '<'  | '>'  | '?'  | '??'  | '::' | '++' | '--' | '&&' | '||'
    | '->' | '==' | '!=' | '<=' | '>='  | '+=' | '-=' | '*=' | '/=' | '%='
    | '&=' | '|=' | '^=' | '<<' | '<<=' | '=>'
    ;

right_shift
    : '>>'
    ;

right_shift_assignment
    : '>>='
    ;

Der senkrechte Strich in den right_shift -und right_shift_assignment Produktionen wird verwendet, um anzugeben, dass im Gegensatz zu anderen Produktionen in der syntaktischen Grammatik keine Zeichen jeglicher Art (nicht sogar Leerzeichen) zwischen den Token zulässig sind.The vertical bar in the right_shift and right_shift_assignment productions are used to indicate that, unlike other productions in the syntactic grammar, no characters of any kind (not even whitespace) are allowed between the tokens. Diese Produktionen werden speziell behandelt, um die korrekte Handhabung von type_parameter_list s (Typparameter) zu ermöglichen.These productions are treated specially in order to enable the correct handling of type_parameter_list s (Type parameters).

Vorverarbeitungs DirektivenPre-processing directives

Die Vorverarbeitungs Direktiven bieten die Möglichkeit, Abschnitte von Quelldateien bedingt zu überspringen, Fehler-und Warnungs Bedingungen zu melden und verschiedene Bereiche des Quellcodes zu gliedern.The pre-processing directives provide the ability to conditionally skip sections of source files, to report error and warning conditions, and to delineate distinct regions of source code. Der Begriff "Vorverarbeitungs Direktiven" wird nur aus Gründen der Konsistenz mit den Programmiersprachen C und C++ verwendet.The term "pre-processing directives" is used only for consistency with the C and C++ programming languages. In c# gibt es keinen separaten Schritt vor der Verarbeitung. Vorverarbeitungs Direktiven werden im Rahmen der lexikalischen Analysephase verarbeitet.In C#, there is no separate pre-processing step; pre-processing directives are processed as part of the lexical analysis phase.

pp_directive
    : pp_declaration
    | pp_conditional
    | pp_line
    | pp_diagnostic
    | pp_region
    | pp_pragma
    ;

Die folgenden Vorverarbeitungs Direktiven sind verfügbar:The following pre-processing directives are available:

  • #define und #undef , die zum definieren bzw. Aufheben der Definition von Symbolen für bedingte Kompilierung (Deklarations Anweisungen) verwendet werden.#define and #undef, which are used to define and undefine, respectively, conditional compilation symbols (Declaration directives).
  • #if, #elif , #else und #endif , die verwendet werden, um Abschnitte des Quellcodes bedingt zu überspringen (bedingte Kompilierungs Direktiven).#if, #elif, #else, and #endif, which are used to conditionally skip sections of source code (Conditional compilation directives).
  • #line, der verwendet wird, um Zeilennummern zu steuern, die für Fehler und Warnungen ausgegeben werden (Zeilen Anweisungen).#line, which is used to control line numbers emitted for errors and warnings (Line directives).
  • #error und #warning , die verwendet werden, um Fehler und Warnungen bzw. (Diagnose Direktiven) auszugeben.#error and #warning, which are used to issue errors and warnings, respectively (Diagnostic directives).
  • #region und #endregion , die verwendet werden, um Abschnitte des Quellcodes (Regions Direktiven) explizit zu markieren.#region and #endregion, which are used to explicitly mark sections of source code (Region directives).
  • #pragma, der verwendet wird, um optionale Kontextinformationen für den Compiler anzugeben (pragma-Direktiven).#pragma, which is used to specify optional contextual information to the compiler (Pragma directives).

Eine Vorverarbeitungs Direktive belegt immer eine separate Zeile des Quellcodes und beginnt immer mit einem # Zeichen und einem Vorverarbeitungs-Direktivennamen.A pre-processing directive always occupies a separate line of source code and always begins with a # character and a pre-processing directive name. Leerräume können vor dem # Zeichen und zwischen dem # Zeichen und dem Direktivennamen auftreten.White space may occur before the # character and between the # character and the directive name.

Eine Quellzeile, die eine-,-,-,-,- #define #undef ,-oder- #if #elif Direktive enthält, #else #endif #line #endregion kann mit einem einzeiligen Kommentar enden.A source line containing a #define, #undef, #if, #elif, #else, #endif, #line, or #endregion directive may end with a single-line comment. Durch Trennzeichen getrennte Kommentare (der /* */ Stil von Kommentaren) sind in Quellzeilen mit Vorverarbeitungs Direktiven nicht zulässig.Delimited comments (the /* */ style of comments) are not permitted on source lines containing pre-processing directives.

Vorverarbeitungs Direktiven sind keine Token und sind nicht Teil der syntaktischen Grammatik von c#.Pre-processing directives are not tokens and are not part of the syntactic grammar of C#. Allerdings können Vorverarbeitungs Direktiven verwendet werden, um Sequenzen von Token einzuschließen oder auszuschließen, und sich auf diese Weise auf die Bedeutung eines c#-Programms auswirken.However, pre-processing directives can be used to include or exclude sequences of tokens and can in that way affect the meaning of a C# program. Bei der Kompilierung wird das Programm z. b.:For example, when compiled, the program:

#define A
#undef B

class C
{
#if A
    void F() {}
#else
    void G() {}
#endif

#if B
    void H() {}
#else
    void I() {}
#endif
}

ergibt genau dieselbe Sequenz von Token wie das Programm:results in the exact same sequence of tokens as the program:

class C
{
    void F() {}
    void I() {}
}

Im Gegensatz dazu sind die beiden Programme ganz anders, syntaktisch, Sie sind jedoch identisch.Thus, whereas lexically, the two programs are quite different, syntactically, they are identical.

Symbole für bedingte KompilierungConditional compilation symbols

Die Funktionen für die bedingte Kompilierung, die von den #if Direktiven,, und bereitgestellt werden, werden #elif #else #endif durch Vorverarbeitungs Ausdrücke (Vorverarbeitungs Ausdrücke) und bedingte Kompilierungs Symbole gesteuert.The conditional compilation functionality provided by the #if, #elif, #else, and #endif directives is controlled through pre-processing expressions (Pre-processing expressions) and conditional compilation symbols.

conditional_symbol
    : '<Any identifier_or_keyword except true or false>'
    ;

Ein Symbol für die bedingte Kompilierung hat zwei mögliche Zustände: defined _ oder _ * nicht definiert *.A conditional compilation symbol has two possible states: defined _ or _undefined**. Am Anfang der lexikalischen Verarbeitung einer Quelldatei ist ein Symbol für die bedingte Kompilierung nicht definiert, es sei denn, es wurde explizit durch einen externen Mechanismus definiert (z. b. eine Befehlszeilen-Compileroption).At the beginning of the lexical processing of a source file, a conditional compilation symbol is undefined unless it has been explicitly defined by an external mechanism (such as a command-line compiler option). Wenn eine #define Direktive verarbeitet wird, wird das in dieser Direktive benannte bedingte Kompilierungs Symbol in dieser Quelldatei definiert.When a #define directive is processed, the conditional compilation symbol named in that directive becomes defined in that source file. Das Symbol bleibt so lange definiert, bis eine- #undef Direktive für das gleiche Symbol verarbeitet wird oder bis das Ende der Quelldatei erreicht wird.The symbol remains defined until an #undef directive for that same symbol is processed, or until the end of the source file is reached. Dies bedeutet, dass die #define -und- #undef Direktiven in einer Quelldatei keine Auswirkung auf andere Quelldateien im gleichen Programm haben.An implication of this is that #define and #undef directives in one source file have no effect on other source files in the same program.

Wenn in einem Vorverarbeitungs Ausdruck darauf verwiesen wird, hat ein definiertes bedingtes Kompilierungs Symbol den booleschen Wert true , und ein nicht definiertes bedingtes Kompilierungs Symbol weist den booleschen Wert auf false .When referenced in a pre-processing expression, a defined conditional compilation symbol has the boolean value true, and an undefined conditional compilation symbol has the boolean value false. Es ist nicht erforderlich, dass bedingte Kompilierungs Symbole explizit deklariert werden, bevor in Vorverarbeitungs Ausdrücken auf Sie verwiesen wird.There is no requirement that conditional compilation symbols be explicitly declared before they are referenced in pre-processing expressions. Stattdessen sind nicht deklarierte Symbole einfach undefiniert und verfügen daher über den Wert false .Instead, undeclared symbols are simply undefined and thus have the value false.

Der Namespace für Symbole für die bedingte Kompilierung ist eindeutig und von allen anderen benannten Entitäten in einem c#-Programm getrennt.The name space for conditional compilation symbols is distinct and separate from all other named entities in a C# program. Auf Symbole für die bedingte Kompilierung kann nur in #define -und #undef -Direktiven und in Vorverarbeitungs Ausdrücken verwiesen werden.Conditional compilation symbols can only be referenced in #define and #undef directives and in pre-processing expressions.

Vorverarbeiten von AusdrückenPre-processing expressions

Vorverarbeitungs Ausdrücke können in #if -und- #elif Direktiven auftreten.Pre-processing expressions can occur in #if and #elif directives. Die Operatoren, ! == , != && und || sind in Vorverarbeitungs Ausdrücken zulässig, und für die Gruppierung können Klammern verwendet werden.The operators !, ==, !=, && and || are permitted in pre-processing expressions, and parentheses may be used for grouping.

pp_expression
    : whitespace? pp_or_expression whitespace?
    ;

pp_or_expression
    : pp_and_expression
    | pp_or_expression whitespace? '||' whitespace? pp_and_expression
    ;

pp_and_expression
    : pp_equality_expression
    | pp_and_expression whitespace? '&&' whitespace? pp_equality_expression
    ;

pp_equality_expression
    : pp_unary_expression
    | pp_equality_expression whitespace? '==' whitespace? pp_unary_expression
    | pp_equality_expression whitespace? '!=' whitespace? pp_unary_expression
    ;

pp_unary_expression
    : pp_primary_expression
    | '!' whitespace? pp_unary_expression
    ;

pp_primary_expression
    : 'true'
    | 'false'
    | conditional_symbol
    | '(' whitespace? pp_expression whitespace? ')'
    ;

Wenn in einem Vorverarbeitungs Ausdruck darauf verwiesen wird, hat ein definiertes bedingtes Kompilierungs Symbol den booleschen Wert true , und ein nicht definiertes bedingtes Kompilierungs Symbol weist den booleschen Wert auf false .When referenced in a pre-processing expression, a defined conditional compilation symbol has the boolean value true, and an undefined conditional compilation symbol has the boolean value false.

Bei der Auswertung eines Vorverarbeitungs Ausdrucks ergibt sich immer ein boolescher Wert.Evaluation of a pre-processing expression always yields a boolean value. Die Regeln für die Auswertung eines Vorverarbeitungs Ausdrucks sind identisch mit denen für einen konstanten Ausdruck (Konstante Ausdrücke), mit dem Unterschied, dass nur benutzerdefinierte Entitäten, auf die verwiesen werden kann, Symbole für die bedingte Kompilierung sind.The rules of evaluation for a pre-processing expression are the same as those for a constant expression (Constant expressions), except that the only user-defined entities that can be referenced are conditional compilation symbols.

Deklarations DirektivenDeclaration directives

Die Deklarations Anweisungen werden verwendet, um Symbole für die bedingte Kompilierung zu definieren oder zu deaktivieren.The declaration directives are used to define or undefine conditional compilation symbols.

pp_declaration
    : whitespace? '#' whitespace? 'define' whitespace conditional_symbol pp_new_line
    | whitespace? '#' whitespace? 'undef' whitespace conditional_symbol pp_new_line
    ;

pp_new_line
    : whitespace? single_line_comment? new_line
    ;

Die Verarbeitung einer- #define Direktive bewirkt, dass das angegebene bedingte Kompilierungs Symbol definiert wird, beginnend mit der Quellzeile, die auf die-Direktive folgt.The processing of a #define directive causes the given conditional compilation symbol to become defined, starting with the source line that follows the directive. Entsprechend bewirkt die Verarbeitung einer- #undef Direktive, dass das angegebene bedingte Kompilierungs Symbol undefiniert wird, beginnend mit der Quellzeile, die auf die-Direktive folgt.Likewise, the processing of an #undef directive causes the given conditional compilation symbol to become undefined, starting with the source line that follows the directive.

Alle #define -und- #undef Direktiven in einer Quelldatei müssen vor dem ersten Token (Tokens) in der Quelldatei auftreten; andernfalls tritt ein Kompilierzeitfehler auf.Any #define and #undef directives in a source file must occur before the first token (Tokens) in the source file; otherwise a compile-time error occurs. In intuitiver Hinsicht #define müssen-und- #undef Direktiven allen "echten Code" in der Quelldatei vorangestellt sein.In intuitive terms, #define and #undef directives must precede any "real code" in the source file.

Beispiel:The example:

#define Enterprise

#if Professional || Enterprise
    #define Advanced
#endif

namespace Megacorp.Data
{
    #if Advanced
    class PivotTable {...}
    #endif
}

ist gültig, da die- #define Anweisungen dem ersten Token (dem- namespace Schlüsselwort) in der Quelldatei vorangestellt sind.is valid because the #define directives precede the first token (the namespace keyword) in the source file.

Das folgende Beispiel führt zu einem Kompilierzeitfehler, da ein #define echter Code befolgt:The following example results in a compile-time error because a #define follows real code:

#define A
namespace N
{
    #define B
    #if B
    class Class1 {}
    #endif
}

Ein #define kann ein Symbol für die bedingte Kompilierung definieren, das bereits definiert ist, ohne #undef dass ein Eingreifen für dieses Symbol vorliegt.A #define may define a conditional compilation symbol that is already defined, without there being any intervening #undef for that symbol. Im folgenden Beispiel wird ein Symbol für die bedingte Kompilierung definiert A und dann wieder definiert.The example below defines a conditional compilation symbol A and then defines it again.

#define A
#define A

Ein #undef kann ein bedingtes Kompilierungs Symbol, das nicht definiert ist, nicht definieren.A #undef may "undefine" a conditional compilation symbol that is not defined. Im folgenden Beispiel wird ein Symbol für die bedingte Kompilierung definiert A und dann zweimal wieder definiert. das zweite #undef hat jedoch keine Auswirkung, aber es ist noch gültig.The example below defines a conditional compilation symbol A and then undefines it twice; although the second #undef has no effect, it is still valid.

#define A
#undef A
#undef A

Bedingte Kompilierungs DirektivenConditional compilation directives

Die Direktiven für die bedingte Kompilierung werden verwendet, um Teile einer Quelldatei bedingt einzuschließen oder auszuschließen.The conditional compilation directives are used to conditionally include or exclude portions of a source file.

pp_conditional
    : pp_if_section pp_elif_section* pp_else_section? pp_endif
    ;

pp_if_section
    : whitespace? '#' whitespace? 'if' whitespace pp_expression pp_new_line conditional_section?
    ;

pp_elif_section
    : whitespace? '#' whitespace? 'elif' whitespace pp_expression pp_new_line conditional_section?
    ;

pp_else_section:
    | whitespace? '#' whitespace? 'else' pp_new_line conditional_section?
    ;

pp_endif
    : whitespace? '#' whitespace? 'endif' pp_new_line
    ;

conditional_section
    : input_section
    | skipped_section
    ;

skipped_section
    : skipped_section_part+
    ;

skipped_section_part
    : skipped_characters? new_line
    | pp_directive
    ;

skipped_characters
    : whitespace? not_number_sign input_character*
    ;

not_number_sign
    : '<Any input_character except #>'
    ;

Wie durch die-Syntax angegeben, müssen bedingte Kompilierungs Direktiven als Sätze geschrieben werden, die aus, in Reihenfolge, einer- #if Direktive, NULL oder mehr #elif -Direktiven, keiner oder einer-Direktive #else und einer- #endif Direktive bestehenAs indicated by the syntax, conditional compilation directives must be written as sets consisting of, in order, an #if directive, zero or more #elif directives, zero or one #else directive, and an #endif directive. Zwischen den Direktiven bestehen bedingte Abschnitte des Quellcodes.Between the directives are conditional sections of source code. Jeder Abschnitt wird von der unmittelbar vorangehenden-Direktive gesteuert.Each section is controlled by the immediately preceding directive. Ein bedingter Abschnitt kann selbst ggf. ggf. ggfA conditional section may itself contain nested conditional compilation directives provided these directives form complete sets.

Ein pp_conditional wählt höchstens eine der enthaltenen conditional_section s für die normale lexikalische Verarbeitung aus:A pp_conditional selects at most one of the contained conditional_section s for normal lexical processing:

  • Die pp_expression s der #if -und- #elif Direktiven werden in der Reihenfolge ausgewertet, bis ein Ergebnis ergibt true .The pp_expression s of the #if and #elif directives are evaluated in order until one yields true. Wenn ein Ausdruck ergibt true , wird der conditional_section der entsprechenden Direktive ausgewählt.If an expression yields true, the conditional_section of the corresponding directive is selected.
  • Wenn alle pp_expression s ergeben false und eine- #else Direktive vorhanden ist, wird der conditional_section der #else Direktive ausgewählt.If all pp_expression s yield false, and if an #else directive is present, the conditional_section of the #else directive is selected.
  • Andernfalls ist keine conditional_section ausgewählt.Otherwise, no conditional_section is selected.

Der ausgewählte conditional_section wird, sofern vorhanden, als normaler input_section verarbeitet: der im Abschnitt enthaltene Quellcode muss der lexikalischen Grammatik entsprechen. Token werden aus dem Quellcode im-Abschnitt generiert. und Vorverarbeitungs Direktiven im-Abschnitt haben die vorgeschriebenen Auswirkungen.The selected conditional_section, if any, is processed as a normal input_section: the source code contained in the section must adhere to the lexical grammar; tokens are generated from the source code in the section; and pre-processing directives in the section have the prescribed effects.

Die verbleibenden conditional_section s, sofern vorhanden, werden als skipped_section s verarbeitet: mit Ausnahme von Vorverarbeitungs Direktiven muss der Quellcode im-Abschnitt nicht der lexikalischen Grammatik entsprechen. aus dem Quellcode im-Abschnitt werden keine Token generiert. und Vorverarbeitungs Direktiven im Abschnitt müssen lexikalisch korrigiert werden, werden jedoch nicht anderweitig verarbeitet.The remaining conditional_section s, if any, are processed as skipped_section s: except for pre-processing directives, the source code in the section need not adhere to the lexical grammar; no tokens are generated from the source code in the section; and pre-processing directives in the section must be lexically correct but are not otherwise processed. Innerhalb einer conditional_section , die als skipped_section verarbeitet wird, werden alle geschachtelten conditional_section s (die in geschachtelten #if ... #endif -und #region ...- #endregion Konstrukten enthalten sind) ebenfalls als skipped_section s verarbeitet.Within a conditional_section that is being processed as a skipped_section, any nested conditional_section s (contained in nested #if...#endif and #region...#endregion constructs) are also processed as skipped_section s.

Im folgenden Beispiel wird veranschaulicht, wie bedingte Kompilierungs Direktiven schachteln können:The following example illustrates how conditional compilation directives can nest:

#define Debug       // Debugging on
#undef Trace        // Tracing off

class PurchaseTransaction
{
    void Commit() {
        #if Debug
            CheckConsistency();
            #if Trace
                WriteToLog(this.ToString());
            #endif
        #endif
        CommitHelper();
    }
}

Mit Ausnahme von Vorverarbeitungs Direktiven unterliegt der übersprungene Quellcode nicht der lexikalischen Analyse.Except for pre-processing directives, skipped source code is not subject to lexical analysis. Beispielsweise ist Folgendes gültig, obwohl der nicht abgeschlossener Kommentar im Abschnitt lautet #else :For example, the following is valid despite the unterminated comment in the #else section:

#define Debug        // Debugging on

class PurchaseTransaction
{
    void Commit() {
        #if Debug
            CheckConsistency();
        #else
            /* Do something else
        #endif
    }
}

Beachten Sie jedoch, dass Vorverarbeitungs Direktiven auch in übersprungenen Abschnitten des Quellcodes lexikalisch korrigiert werden müssen.Note, however, that pre-processing directives are required to be lexically correct even in skipped sections of source code.

Vorverarbeitungs Direktiven werden nicht verarbeitet, wenn Sie in mehrzeiligen Eingabe Elementen angezeigt werden.Pre-processing directives are not processed when they appear inside multi-line input elements. Das Programm lautet z. b.:For example, the program:

class Hello
{
    static void Main() {
        System.Console.WriteLine(@"hello, 
#if Debug
        world
#else
        Nebraska
#endif
        ");
    }
}

Ergebnisse in der Ausgabe:results in the output:

hello,
#if Debug
        world
#else
        Nebraska
#endif

In besonderen Fällen hängt der Satz der verarbeiteten Vorverarbeitungs Direktiven möglicherweise von der Auswertung der pp_expression ab.In peculiar cases, the set of pre-processing directives that is processed might depend on the evaluation of the pp_expression. Beispiel:The example:

#if X
    /*
#else
    /* */ class Q { }
#endif

erzeugt immer denselben Tokenstream ( class Q { } ), unabhängig davon, ob X definiert ist oder nicht.always produces the same token stream (class Q { }), regardless of whether or not X is defined. Wenn X definiert ist, sind die einzigen verarbeiteten Direktiven #if und #endif , aufgrund des mehrzeiligen Kommentars.If X is defined, the only processed directives are #if and #endif, due to the multi-line comment. Wenn nicht X definiert ist, sind drei-Direktiven ( #if , #else , #endif ) Teil der direktivenmenge.If X is undefined, then three directives (#if, #else, #endif) are part of the directive set.

Diagnose DirektivenDiagnostic directives

Die Diagnose Direktiven werden verwendet, um Fehler-und Warnmeldungen explizit zu generieren, die auf die gleiche Weise wie andere Kompilierzeitfehler und-Warnungen gemeldet werden.The diagnostic directives are used to explicitly generate error and warning messages that are reported in the same way as other compile-time errors and warnings.

pp_diagnostic
    : whitespace? '#' whitespace? 'error' pp_message
    | whitespace? '#' whitespace? 'warning' pp_message
    ;

pp_message
    : new_line
    | whitespace input_character* new_line
    ;

Beispiel:The example:

#warning Code review needed before check-in

#if Debug && Retail
    #error A build can't be both debug and retail
#endif

class Test {...}

erzeugt immer eine Warnung ("Code Review ist vor dem Einchecken erforderlich") und erzeugt einen Kompilierzeitfehler ("ein Build kann nicht gleichzeitig Debuggen und Einzelhandel sein"), wenn die bedingten Symbole Debug und Retail definiert sind.always produces a warning ("Code review needed before check-in"), and produces a compile-time error ("A build can't be both debug and retail") if the conditional symbols Debug and Retail are both defined. Beachten Sie, dass ein pp_message beliebigen Text enthalten kann. insbesondere muss Sie keine wohlgeformten Token enthalten, wie durch das einfache Anführungszeichen im Wort gezeigt can't .Note that a pp_message can contain arbitrary text; specifically, it need not contain well-formed tokens, as shown by the single quote in the word can't.

Regions DirektivenRegion directives

Die Regions Direktiven werden verwendet, um Bereiche des Quellcodes explizit zu markieren.The region directives are used to explicitly mark regions of source code.

pp_region
    : pp_start_region conditional_section? pp_end_region
    ;

pp_start_region
    : whitespace? '#' whitespace? 'region' pp_message
    ;

pp_end_region
    : whitespace? '#' whitespace? 'endregion' pp_message
    ;

An einen Bereich ist keine semantische Bedeutung angefügt. Regionen sind für die Verwendung durch den Programmierer oder automatisierte Tools vorgesehen, um einen Abschnitt des Quellcodes zu markieren.No semantic meaning is attached to a region; regions are intended for use by the programmer or by automated tools to mark a section of source code. Die in einer- #region oder- #endregion Direktive angegebene Meldung hat ebenfalls keine semantische Bedeutung; Sie dient lediglich zur Identifizierung der Region.The message specified in a #region or #endregion directive likewise has no semantic meaning; it merely serves to identify the region. Übereinstimmende #region -und- #endregion Direktiven haben möglicherweise andere pp_message sMatching #region and #endregion directives may have different pp_message s.

Die lexikalische Verarbeitung einer Region:The lexical processing of a region:

#region
...
#endregion

entspricht genau der lexikalischen Verarbeitung einer Direktive für die bedingte Kompilierung in der Form:corresponds exactly to the lexical processing of a conditional compilation directive of the form:

#if true
...
#endif

Line-DirektivenLine directives

Zeilen Anweisungen können verwendet werden, um die Zeilennummern und Quell Dateinamen zu ändern, die vom Compiler in Ausgabe wie Warnungen und Fehlern gemeldet werden, und die von Aufrufer-Informations Attributen (aufruferinformationsattribute) verwendet werden.Line directives may be used to alter the line numbers and source file names that are reported by the compiler in output such as warnings and errors, and that are used by caller info attributes (Caller info attributes).

Zeilen Direktiven werden am häufigsten in metaprogrammierungs Tools verwendet, die c#-Quellcode aus einer anderen Texteingabe generieren.Line directives are most commonly used in meta-programming tools that generate C# source code from some other text input.

pp_line
    : whitespace? '#' whitespace? 'line' whitespace line_indicator pp_new_line
    ;

line_indicator
    : decimal_digit+ whitespace file_name
    | decimal_digit+
    | 'default'
    | 'hidden'
    ;

file_name
    : '"' file_name_character+ '"'
    ;

file_name_character
    : '<Any input_character except ">'
    ;

Wenn keine #line -Direktiven vorhanden sind, meldet der Compiler echte Zeilennummern und Quell Dateinamen in der Ausgabe.When no #line directives are present, the compiler reports true line numbers and source file names in its output. Bei der Verarbeitung einer- #line Direktive, die eine line_indicator enthält, die nicht ist default , behandelt der Compiler die Zeile nach der-Direktive als mit der angegebenen Zeilennummer (und dem Dateinamen, falls angegeben).When processing a #line directive that includes a line_indicator that is not default, the compiler treats the line after the directive as having the given line number (and file name, if specified).

Eine- #line default Direktive kehrt die Auswirkungen aller vorangehenden #line Direktiven um.A #line default directive reverses the effect of all preceding #line directives. Der Compiler meldet echte Zeilen Informationen für nachfolgende Zeilen, genau so, als ob keine #line Direktiven verarbeitet wurden.The compiler reports true line information for subsequent lines, precisely as if no #line directives had been processed.

Eine #line hidden -Direktive hat keine Auswirkung auf die Datei-und Zeilennummern, die in Fehlermeldungen gemeldet werden, wirkt sich aber auf das Debugging auf Quell Ebene ausA #line hidden directive has no effect on the file and line numbers reported in error messages, but does affect source level debugging. Beim Debuggen verfügen alle Zeilen zwischen einer #line hidden -Direktive und der nachfolgenden #line Direktive (das nicht #line hidden ) über keine Zeilennummern Informationen.When debugging, all lines between a #line hidden directive and the subsequent #line directive (that is not #line hidden) have no line number information. Wenn Sie Code im Debugger schrittweise durchlaufen, werden diese Zeilen vollständig übersprungen.When stepping through code in the debugger, these lines will be skipped entirely.

Beachten Sie, dass sich ein file_name von einem regulären Zeichenfolgenliterals unterscheidet, da Escapezeichen nicht verarbeitet Das \ Zeichen "" bezeichnet einfach einen normalen umgekehrten Schrägstrich innerhalb eines file_name.Note that a file_name differs from a regular string literal in that escape characters are not processed; the "\" character simply designates an ordinary backslash character within a file_name.

Pragma-AnweisungenPragma directives

Die #pragma Vorverarbeitungs Direktive wird verwendet, um dem Compiler optionale Kontextinformationen anzugeben.The #pragma preprocessing directive is used to specify optional contextual information to the compiler. Die in einer- #pragma Direktive angegebenen Informationen ändern die Programm Semantik nie.The information supplied in a #pragma directive will never change program semantics.

pp_pragma
    : whitespace? '#' whitespace? 'pragma' whitespace pragma_body pp_new_line
    ;

pragma_body
    : pragma_warning_body
    ;

C# stellt #pragma Anweisungen zum Steuern von Compilerwarnungen bereit.C# provides #pragma directives to control compiler warnings. Zukünftige Versionen der Sprache können zusätzliche Anweisungen enthalten #pragma .Future versions of the language may include additional #pragma directives. Um die Interoperabilität mit anderen c#-Compilern sicherzustellen, gibt der Microsoft c#-Compiler keine Kompilierungsfehler für unbekannte #pragma Direktiven aus. solche Direktiven generieren jedoch Warnungen.To ensure interoperability with other C# compilers, the Microsoft C# compiler does not issue compilation errors for unknown #pragma directives; such directives do however generate warnings.

Pragma-WarnungPragma warning

Die- #pragma warning Anweisung wird verwendet, um alle oder einen bestimmten Satz von Warnmeldungen während der Kompilierung des nachfolgenden Programm Texts zu deaktivieren oder wiederherzustellen.The #pragma warning directive is used to disable or restore all or a particular set of warning messages during compilation of the subsequent program text.

pragma_warning_body
    : 'warning' whitespace warning_action
    | 'warning' whitespace warning_action whitespace warning_list
    ;

warning_action
    : 'disable'
    | 'restore'
    ;

warning_list
    : decimal_digit+ (whitespace? ',' whitespace? decimal_digit+)*
    ;

Eine #pragma warning Anweisung, die die Warnungs Liste auslässt, wirkt sich auf alle Warnungen aus.A #pragma warning directive that omits the warning list affects all warnings. Eine #pragma warning Anweisung, die eine Warnungs Liste enthält, wirkt sich nur auf die Warnungen aus, die in der Liste angegeben sind.A #pragma warning directive that includes a warning list affects only those warnings that are specified in the list.

Eine- #pragma warning disable Direktive deaktiviert alle oder den angegebenen Satz von Warnungen.A #pragma warning disable directive disables all or the given set of warnings.

Eine- #pragma warning restore Direktive stellt alle oder den angegebenen Satz von Warnungen in dem Zustand wieder her, der am Anfang der Kompilierungseinheit wirksam war.A #pragma warning restore directive restores all or the given set of warnings to the state that was in effect at the beginning of the compilation unit. Beachten Sie Folgendes: Wenn eine bestimmte Warnung extern deaktiviert wurde, #pragma warning restore wird diese Warnung von a (ob für alle oder eine bestimmte Warnung) nicht erneut aktiviert.Note that if a particular warning was disabled externally, a #pragma warning restore (whether for all or the specific warning) will not re-enable that warning.

Das folgende Beispiel zeigt die Verwendung von #pragma warning , um die Warnung, die bei referenzierten Membern verwiesen wird, vorübergehend zu deaktivieren. dabei wird die Warnungs Nummer des Microsoft c#-Compilers verwendet.The following example shows use of #pragma warning to temporarily disable the warning reported when obsoleted members are referenced, using the warning number from the Microsoft C# compiler.

using System;

class Program
{
    [Obsolete]
    static void Foo() {}

    static void Main() {
#pragma warning disable 612
    Foo();
#pragma warning restore 612
    }
}