Estrutura lexicalLexical structure

ProgramasPrograms

Um programa em C# * é composto por um ou mais arquivos de origem, conhecidos formalmente como _ unidades de compilação* (unidades de compilação).A C# program _ consists of one or more _source files_, known formally as _ compilation units (Compilation units). Um arquivo de origem é uma sequência ordenada de caracteres Unicode.A source file is an ordered sequence of Unicode characters. Normalmente, os arquivos de origem têm uma correspondência um-para-um com arquivos em um sistema de arquivos, mas essa correspondência não é necessária.Source files typically have a one-to-one correspondence with files in a file system, but this correspondence is not required. Para portabilidade máxima, é recomendável que os arquivos em um sistema de arquivos sejam codificados com a codificação UTF-8.For maximal portability, it is recommended that files in a file system be encoded with the UTF-8 encoding.

Em termos conceituais, um programa é compilado usando três etapas:Conceptually speaking, a program is compiled using three steps:

  1. Transformação, que converte um arquivo de um repertório de caractere específico e esquema de codificação em uma sequência de caracteres Unicode.Transformation, which converts a file from a particular character repertoire and encoding scheme into a sequence of Unicode characters.
  2. Análise lexical, que traduz um fluxo de caracteres de entrada Unicode em um fluxo de tokens.Lexical analysis, which translates a stream of Unicode input characters into a stream of tokens.
  3. Análise sintática, que traduz o fluxo de tokens no código executável.Syntactic analysis, which translates the stream of tokens into executable code.

GramáticaGrammars

Essa especificação apresenta a sintaxe da linguagem de programação C# usando duas gramáticas.This specification presents the syntax of the C# programming language using two grammars. A *gramática lexical _ (gramática lexical) define como os caracteres Unicode são combinados em terminadores de linha de formulário, espaço em branco, comentários, tokens e diretivas de pré-processamento.The *lexical grammar _ (Lexical grammar) defines how Unicode characters are combined to form line terminators, white space, comments, tokens, and pre-processing directives. A sintaxe _ sintática* (gramática sintática) define como os tokens resultantes da gramática léxica são combinados para formar programas em C#.The _ syntactic grammar* (Syntactic grammar) defines how the tokens resulting from the lexical grammar are combined to form C# programs.

Notação gramaticalGrammar notation

As gramáticas léxicas e sintáticas são apresentadas no formulário Backus-Naur usando a notação da ferramenta gramática ANTLR.The lexical and syntactic grammars are presented in Backus-Naur form using the notation of the ANTLR grammar tool.

Gramática lexicalLexical grammar

A gramática lexical do C# é apresentada em análise lexical, tokense diretivas de pré-processamento.The lexical grammar of C# is presented in Lexical analysis, Tokens, and Pre-processing directives. Os símbolos de terminal da gramática lexical são os caracteres do conjunto de caracteres Unicode, e a gramática léxica especifica como os caracteres são combinados para tokens de formulário (tokens), espaços em branco (espaço em branco), comentários (comentários) e diretivas de pré-processamento (diretivas de pré-processamento).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).

Cada arquivo de origem em um programa C# deve estar de acordo com a produção de entrada da gramática léxica (análise lexical).Every source file in a C# program must conform to the input production of the lexical grammar (Lexical analysis).

Gramática sintáticaSyntactic grammar

A gramática sintática do C# é apresentada nos capítulos e apêndices que seguem este capítulo.The syntactic grammar of C# is presented in the chapters and appendices that follow this chapter. Os símbolos de terminal da gramática sintática são os tokens definidos pela gramática lexical e a gramática sintática especifica como os tokens são combinados para formar programas em C#.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.

Cada arquivo de origem em um programa C# deve estar de acordo com o compilation_unit produção da gramática sintática (unidades de compilação).Every source file in a C# program must conform to the compilation_unit production of the syntactic grammar (Compilation units).

Análise léxicaLexical analysis

A produção de entrada define a estrutura lexical de um arquivo de origem C#.The input production defines the lexical structure of a C# source file. Cada arquivo de origem em um programa C# deve estar de acordo com esta produção de gramática lexical.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
    ;

Cinco elementos básicos compõem a estrutura lexical de um arquivo de origem C#: terminadores de linha (terminadores de linha), espaço em branco (espaço em branco), comentários (comentários), tokens (tokens) e diretivas de pré-processamento (diretivas de pré-processamento).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). Desses elementos básicos, somente os tokens são significativos na gramática sintática de um programa C# (gramática sintática).Of these basic elements, only tokens are significant in the syntactic grammar of a C# program (Syntactic grammar).

O processamento lexical de um arquivo de origem C# consiste em reduzir o arquivo em uma sequência de tokens que se torna a entrada para a análise sintática.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. Terminadores de linha, espaços em branco e comentários podem servir a tokens separados, e diretivas de pré-processamento podem fazer com que as seções do arquivo de origem sejam ignoradas, mas, caso contrário, esses elementos léxicos não têm impacto sobre a estrutura sintática de um programa em C#.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.

No caso de literais de cadeia de caracteres interpolados (literais de cadeia de caracteres interpolados), um único token é produzido inicialmente pela análise lexical, mas é dividido em vários elementos de entrada que estão sujeitos repetidamente à análise lexical até que todos os literais de cadeia de caracteres interpolados tenham sido resolvidos.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. Os tokens resultantes servem como entrada para a análise sintática.The resulting tokens then serve as input to the syntactic analysis.

Quando várias produções de gramática léxicas correspondem a uma sequência de caracteres em um arquivo de origem, o processamento lexical sempre forma o mais longo possível elemento léxico.When several lexical grammar productions match a sequence of characters in a source file, the lexical processing always forms the longest possible lexical element. Por exemplo, a sequência de caracteres // é processada como o início de um comentário de linha única porque esse elemento léxico é maior do que um único / token.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.

Terminadores de linhaLine terminators

Terminadores de linha dividem os caracteres de um arquivo de origem C# em linhas.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)>'
    ;

Para compatibilidade com ferramentas de edição de código-fonte que adicionam marcadores de fim de arquivo e para permitir que um arquivo de origem seja exibido como uma sequência de linhas corretamente encerradas, as seguintes transformações são aplicadas, em ordem, a cada arquivo de origem em um programa em C#: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:

  • Se o último caractere do arquivo de origem for um caractere de controle Z ( U+001A ), esse caractere será excluído.If the last character of the source file is a Control-Z character (U+001A), this character is deleted.
  • Um caractere de retorno de carro ( U+000D ) é adicionado ao final do arquivo de origem se esse arquivo de origem não estiver vazio e se o último caractere do arquivo de origem não for um retorno de carro ( U+000D ), um feed de linha ( U+000A ), um separador de linha ( U+2028 ) ou um separador de parágrafo ( U+2029 ).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).

ComentáriosComments

Dois formulários de comentários são compatíveis: comentários de linha única e comentários delimitados.Two forms of comments are supported: single-line comments and delimited comments.\ Os comentários de linha única _ começam com os caracteres // e se estendem até o final da linha de origem.\ Single-line comments _ start with the characters // and extend to the end of the source line. Os _comentários delimitados_ começam com os caracteres /_ e terminam com os caracteres */ .Delimited comments start with the characters /_ and end with the characters */. Os comentários delimitados podem abranger várias linhas.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 *>'
    ;

Os comentários não podem ser aninhados.Comments do not nest. As sequências de caracteres /* e */ não têm um significado especial dentro de um // comentário e as sequências de caracteres // e /* não têm nenhum significado especial dentro de um comentário delimitado.The character sequences /* and */ have no special meaning within a // comment, and the character sequences // and /* have no special meaning within a delimited comment.

Os comentários não são processados em literais de caractere e de cadeia de caracteres.Comments are not processed within character and string literals.

O exemploThe example

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

inclui um comentário delimitado.includes a delimited comment.

O exemploThe 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");
    }
}

mostra vários comentários de linha única.shows several single-line comments.

Espaço em brancoWhite space

O espaço em branco é definido como qualquer caractere com a classe Unicode ZS (que inclui o caractere de espaço), bem como o caractere de tabulação horizontal, o caractere de tabulação vertical e o caractere de feed de formulário.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)>'
    ;

TokensTokens

Há vários tipos de tokens: identificadores, palavras-chave, literais, operadores e pontuadores.There are several kinds of tokens: identifiers, keywords, literals, operators, and punctuators. Os comentários e o espaço em branco não são tokens, embora atuem como separadores para tokens.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
    ;

Sequências de escape de caractere UnicodeUnicode character escape sequences

Uma sequência de escape de caractere Unicode representa um caractere Unicode.A Unicode character escape sequence represents a Unicode character. As sequências de escape de caractere Unicode são processadas em identificadores (identificadores), literais de caracteres (literaisde caracteres) e literais de cadeia de caracteres regulares (literais de cadeia de caracteres).Unicode character escape sequences are processed in identifiers (Identifiers), character literals (Character literals), and regular string literals (String literals). Um escape de caractere Unicode não é processado em nenhum outro local (por exemplo, para formar um operador, um pontuador ou uma palavra-chave).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
    ;

Uma sequência de escape Unicode representa o caractere Unicode único formado pelo número hexadecimal após os \u caracteres "" ou " \U ".A Unicode escape sequence represents the single Unicode character formed by the hexadecimal number following the "\u" or "\U" characters. Como o C# usa uma codificação de 16 bits de pontos de código Unicode em caracteres e valores de cadeia, um caractere Unicode no intervalo de U + 10000 a U + 10FFFF não é permitido em um literal de caractere e é representado usando um par substituto Unicode em um literal de cadeia de caracteres.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. Não há suporte para caracteres Unicode com pontos de código acima de 0x10FFFF.Unicode characters with code points above 0x10FFFF are not supported.

Várias traduções não são executadas.Multiple translations are not performed. Por exemplo, a cadeia de caracteres literal " \u005Cu005C " é equivalente a " \u005C " em vez de " \ ".For instance, the string literal "\u005Cu005C" is equivalent to "\u005C" rather than "\". O valor Unicode \u005C é o caractere " \ ".The Unicode value \u005C is the character "\".

O exemploThe example

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

mostra vários usos de \u0066 , que é a sequência de escape para a letra " f ".shows several uses of \u0066, which is the escape sequence for the letter "f". O programa é equivalente aThe program is equivalent to

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

IdentificadoresIdentifiers

As regras para identificadores fornecidos nesta seção correspondem exatamente às recomendadas pelo anexo 31 padrão Unicode, exceto que o sublinhado é permitido como um caractere inicial (como é tradicional na linguagem de programação C), as sequências de escape Unicode são permitidas em identificadores e o @ caractere "" é permitido como um prefixo para habilitar as palavras-chave a serem usadas como identificadores.The 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>'
    ;

Para obter informações sobre as classes de caracteres Unicode mencionadas acima, consulte o padrão Unicode, versão 3,0, seção 4,5.For information on the Unicode character classes mentioned above, see The Unicode Standard, Version 3.0, section 4.5.

Exemplos de identificadores válidos incluem " identifier1 ", " _identifier2 " e " @if ".Examples of valid identifiers include "identifier1", "_identifier2", and "@if".

Um identificador em um programa de conformidade deve estar no formato canônico definido pelo formulário de normalização Unicode C, conforme definido pelo anexo 15 padrão Unicode.An identifier in a conforming program must be in the canonical format defined by Unicode Normalization Form C, as defined by Unicode Standard Annex 15. O comportamento ao encontrar um identificador que não está no formato de normalização C é definido pela implementação; no entanto, um diagnóstico não é necessário.The behavior when encountering an identifier not in Normalization Form C is implementation-defined; however, a diagnostic is not required.

O prefixo " @ " permite o uso de palavras-chave como identificadores, o que é útil ao fazer a interface com outras linguagens de programação.The prefix "@" enables the use of keywords as identifiers, which is useful when interfacing with other programming languages. O caractere @ não é realmente parte do identificador, portanto, o identificador pode ser visto em outros idiomas como um identificador normal, sem o prefixo.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. Um identificador com um @ prefixo é chamado de identificador textual.An identifier with an @ prefix is called a verbatim identifier. O uso do @ prefixo para identificadores que não são palavras-chave é permitido, mas altamente desencorajado como uma questão de estilo.Use of the @ prefix for identifiers that are not keywords is permitted, but strongly discouraged as a matter of style.

O exemplo: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);
    }
}

define uma classe denominada " class " com um método estático chamado " static " que usa um parâmetro denominado " bool ".defines a class named "class" with a static method named "static" that takes a parameter named "bool". Observe que, como os escapes Unicode não são permitidos em palavras-chave, o token " cl\u0061ss " é um identificador e é o mesmo identificador de " @class ".Note that since Unicode escapes are not permitted in keywords, the token "cl\u0061ss" is an identifier, and is the same identifier as "@class".

Dois identificadores são considerados iguais se forem idênticos depois que as transformações a seguir forem aplicadas, na ordem:Two identifiers are considered the same if they are identical after the following transformations are applied, in order:

  • O prefixo " @ ", se usado, será removido.The prefix "@", if used, is removed.
  • Cada unicode_escape_sequence é transformada em seu caractere Unicode correspondente.Each unicode_escape_sequence is transformed into its corresponding Unicode character.
  • Todas as formatting_character s são removidas.Any formatting_character s are removed.

Os identificadores que contêm dois caracteres de sublinhado consecutivos ( U+005F ) são reservados para uso pela implementação.Identifiers containing two consecutive underscore characters (U+005F) are reserved for use by the implementation. Por exemplo, uma implementação pode fornecer palavras-chave estendidas que começam com dois sublinhados.For example, an implementation might provide extended keywords that begin with two underscores.

Palavras-chaveKeywords

Uma palavra-chave é uma sequência semelhante a identificador de caracteres que é reservada e não pode ser usada como um identificador, exceto quando precedida pelo @ caractere.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'
    ;

Em alguns lugares da gramática, os identificadores específicos têm um significado especial, mas não são palavras-chave.In some places in the grammar, specific identifiers have special meaning, but are not keywords. Esses identificadores são, às vezes, chamados de "palavras-chave contextuais".Such identifiers are sometimes referred to as "contextual keywords". Por exemplo, dentro de uma declaração de propriedade, os get identificadores "" e " set " têm significado especial (acessadores).For example, within a property declaration, the "get" and "set" identifiers have special meaning (Accessors). Um identificador diferente de get ou set nunca é permitido nesses locais, portanto, esse uso não entra em conflito com o uso dessas palavras como identificadores.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. Em outros casos, como com o identificador " var " em declarações de variáveis locais digitadas implicitamente (declarações de variáveis locais), uma palavra-chave contextual pode entrar em conflito com nomes declarados.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. Nesses casos, o nome declarado tem precedência sobre o uso do identificador como uma palavra-chave contextual.In such cases, the declared name takes precedence over the use of the identifier as a contextual keyword.

LiteraisLiterals

Um literal é uma representação de código-fonte de um valor.A literal is a source code representation of a value.

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

Literais boolianosBoolean literals

Há dois valores literais boolianos: true e false .There are two boolean literal values: true and false.

boolean_literal
    : 'true'
    | 'false'
    ;

O tipo de um boolean_literal é bool .The type of a boolean_literal is bool.

Literais inteirosInteger literals

Literais inteiros são usados para gravar valores de tipos int , uint ,, long e ulong .Integer literals are used to write values of types int, uint, long, and ulong. Os literais inteiros têm duas formas possíveis: decimal e hexadecimal.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';

O tipo de um literal inteiro é determinado da seguinte maneira:The type of an integer literal is determined as follows:

  • Se o literal não tiver nenhum sufixo, ele terá o primeiro desses tipos em que seu valor pode ser representado: 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.
  • Se o literal for sufixado pelo U ou u , ele terá o primeiro desses tipos em que seu valor pode ser representado: 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.
  • Se o literal for sufixado pelo L ou l , ele terá o primeiro desses tipos em que seu valor pode ser representado: 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.
  • Se o literal for sufixado por,,,,,, UL Ul uL ul LU Lu lU ou lu , será do tipo ulong .If the literal is suffixed by UL, Ul, uL, ul, LU, Lu, lU, or lu, it is of type ulong.

Se o valor representado por um literal inteiro estiver fora do intervalo do ulong tipo, ocorrerá um erro em tempo de compilação.If the value represented by an integer literal is outside the range of the ulong type, a compile-time error occurs.

Como uma questão de estilo, é recomendável que " L " seja usado em vez de " l " ao escrever literais do tipo long , já que é fácil confundir a letra " l " com o dígito " 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".

Para permitir que os menores int valores e possíveis long sejam gravados como literais inteiros decimais, existem as duas seguintes regras:To permit the smallest possible int and long values to be written as decimal integer literals, the following two rules exist:

  • Quando um decimal_integer_literal com o valor 2147483648 (2 ^ 31) e nenhum integer_type_suffix aparece como o token imediatamente após um token do operador menos unário (operador menos unário), o resultado é uma constante do tipo int com o valor-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). Em todas as outras situações, tal decimal_integer_literal é do tipo uint .In all other situations, such a decimal_integer_literal is of type uint.
  • Quando um decimal_integer_literal com o valor 9.223.372.036.854.775.808 (2 ^ 63) e nenhum integer_type_suffix ou o integer_type_suffix L ou l aparece como o token imediatamente após um token do operador de subtração unário (operador menos unário), o resultado é uma constante do tipo long com o valor-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). Em todas as outras situações, tal decimal_integer_literal é do tipo ulong .In all other situations, such a decimal_integer_literal is of type ulong.

Literais reaisReal literals

Os literais reais são usados para gravar valores de tipos float , double e 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'
    ;

Se nenhum real_type_suffix for especificado, o tipo do literal real será double .If no real_type_suffix is specified, the type of the real literal is double. Caso contrário, o sufixo de tipo real determina o tipo do literal real, da seguinte maneira:Otherwise, the real type suffix determines the type of the real literal, as follows:

  • Um literal real sufixado por F ou f é do tipo float .A real literal suffixed by F or f is of type float. Por exemplo, os literais 1f , 1.5f , 1e10f e 123.456F são todos do tipo float .For example, the literals 1f, 1.5f, 1e10f, and 123.456F are all of type float.
  • Um literal real sufixado por D ou d é do tipo double .A real literal suffixed by D or d is of type double. Por exemplo, os literais 1d , 1.5d , 1e10d e 123.456D são todos do tipo double .For example, the literals 1d, 1.5d, 1e10d, and 123.456D are all of type double.
  • Um literal real sufixado por M ou m é do tipo decimal .A real literal suffixed by M or m is of type decimal. Por exemplo, os literais 1m , 1.5m , 1e10m e 123.456M são todos do tipo decimal .For example, the literals 1m, 1.5m, 1e10m, and 123.456M are all of type decimal. Esse literal é convertido em um decimal valor usando o valor exato e, se necessário, arredondando para o valor representável mais próximo usando o arredondamento do banco (o tipo decimal).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). Qualquer escala aparente no literal é preservada, a menos que o valor seja arredondado ou o valor seja zero (nesse último caso, o sinal e a escala serão 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). Portanto, o literal 2.900m será analisado para formar o decimal com sinal 0 , coeficiente 2900 e escala 3 .Hence, the literal 2.900m will be parsed to form the decimal with sign 0, coefficient 2900, and scale 3.

Se o literal especificado não puder ser representado no tipo indicado, ocorrerá um erro em tempo de compilação.If the specified literal cannot be represented in the indicated type, a compile-time error occurs.

O valor de um literal real do tipo float ou double é determinado usando o modo IEEE "Round to mais próximo".The value of a real literal of type float or double is determined by using the IEEE "round to nearest" mode.

Observe que, em um literal real, os dígitos decimais sempre são necessários após o ponto decimal.Note that in a real literal, decimal digits are always required after the decimal point. Por exemplo, 1.3F é um literal real, mas 1.F não é.For example, 1.3F is a real literal but 1.F is not.

Literais de caracteresCharacter literals

Um literal de caractere representa um único caractere e geralmente consiste em um caractere entre aspas, como em 'a' .A character literal represents a single character, and usually consists of a character in quotes, as in 'a'.

Observação: a notação gramatical ANTLR torna o seguinte confuso!Note: The ANTLR grammar notation makes the following confusing! No ANTLR, quando você escreve, \' significa uma aspa simples ' .In ANTLR, when you write \' it stands for a single quote '. E quando você escrevê \\ -lo significa uma barra invertida única \ .And when you write \\ it stands for a single backslash \. Portanto, a primeira regra para um literal de caractere significa que ela começa com uma aspa simples, depois um caractere e uma aspa simples.Therefore the first rule for a character literal means it starts with a single quote, then a character, then a single quote. E as onze sequências de escape simples possíveis são,,,,,,,,, \' \" \\ \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?;

Um caractere que segue um caractere de barra invertida ( \ ) em um caractere deve ser um dos seguintes caracteres:,,,,,, ' ,,,, " ,, \ 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. Caso contrário, ocorrerá um erro de tempo de compilação.Otherwise, a compile-time error occurs.

Uma sequência de escape hexadecimal representa um único caractere Unicode, com o valor formado pelo número hexadecimal após " \x ".A hexadecimal escape sequence represents a single Unicode character, with the value formed by the hexadecimal number following "\x".

Se o valor representado por um literal de caractere for maior que U+FFFF , ocorrerá um erro em tempo de compilação.If the value represented by a character literal is greater than U+FFFF, a compile-time error occurs.

Uma sequência de escape de caractere Unicode (sequências de escape de caractere Unicode) em um literal de caractere deve estar no intervalo U+0000 para 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.

Uma sequência de escape simples representa uma codificação de caractere Unicode, conforme descrito na tabela a seguir.A simple escape sequence represents a Unicode character encoding, as described in the table below.

Sequência de escapeEscape sequence Nome do caractereCharacter name Codificação UnicodeUnicode encoding
\' Aspas simplesSingle quote 0x0027
\" Aspas duplasDouble quote 0x0022
\\ Barra invertidaBackslash 0x005C
\0 NuloNull 0x0000
\a AlertaAlert 0x0007
\b BackspaceBackspace 0x0008
\f Avanço de formulárioForm feed 0x000C
\n Nova linhaNew line 0x000A
\r Retorno de carroCarriage return 0x000D
\t Guia horizontalHorizontal tab 0x0009
\v Guia verticalVertical tab 0x000B

O tipo de um character_literal é char .The type of a character_literal is char.

Literais de cadeia de caracteresString literals

O C# dá suporte a duas formas de literais de cadeia de caracteres: * literais de cadeia de caracteres regulares _ e _ literais de cadeia de caracteres textuais *.C# supports two forms of string literals: regular string literals _ and _verbatim string literals**.

Um literal de cadeia de caracteres regular consiste em zero ou mais caracteres entre aspas duplas, como em "hello" , e pode incluir sequências de escape simples (como \t para o caractere de tabulação) e sequências de escape hexadecimal e Unicode.A 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.

Um literal de cadeia de caracteres textual consiste em um @ caractere seguido por um caractere de aspas duplas, zero ou mais caracteres e um caractere de aspas duplas de fechamento.A verbatim string literal consists of an @ character followed by a double-quote character, zero or more characters, and a closing double-quote character. Um exemplo simples é @"hello" .A simple example is @"hello". Em um literal de cadeia de caracteres textual, os caracteres entre os delimitadores são interpretados literalmente, a única exceção é um quote_escape_sequence.In a verbatim string literal, the characters between the delimiters are interpreted verbatim, the only exception being a quote_escape_sequence. Em particular, sequências de escape simples e sequências de escape hexadecimal e Unicode não são processadas em literais de cadeia de caracteres textuais.In particular, simple escape sequences, and hexadecimal and Unicode escape sequences are not processed in verbatim string literals. Um literal de cadeia de caracteres textual pode abranger várias linhas.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
    : '""'
    ;

Um caractere que segue um caractere de barra invertida ( \ ) em um regular_string_literal_character deve ser um dos seguintes caracteres:,,,,,, ' ,,,, " ,, \ 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. Caso contrário, ocorrerá um erro de tempo de compilação.Otherwise, a compile-time error occurs.

O exemploThe 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";

mostra uma variedade de literais de cadeia de caracteres.shows a variety of string literals. O último literal de cadeia de caracteres, j , é um literal de cadeia de caracteres textual que abrange várias linhas.The last string literal, j, is a verbatim string literal that spans multiple lines. Os caracteres entre as aspas, incluindo espaços em branco, como novos caracteres de linha, são preservados literalmente.The characters between the quotation marks, including white space such as new line characters, are preserved verbatim.

Como uma sequência de escape hexadecimal pode ter um número variável de dígitos hexadecimais, a cadeia de caracteres literal "\x123" contém um único caractere com o valor hexadecimal 123.Since a hexadecimal escape sequence can have a variable number of hex digits, the string literal "\x123" contains a single character with hex value 123. Para criar uma cadeia de caracteres que contém o caractere com o valor hexadecimal 12 seguido pelo caractere 3, é possível escrever "\x00123" ou "\x12" + "3" em vez disso.To create a string containing the character with hex value 12 followed by the character 3, one could write "\x00123" or "\x12" + "3" instead.

O tipo de um string_literaL é string .The type of a string_literal is string.

Cada literal de cadeia de caracteres não resulta necessariamente em uma nova instância de cadeia de caracteres.Each string literal does not necessarily result in a new string instance. Quando dois ou mais literais de cadeia de caracteres equivalentes de acordo com o operador de igualdade de cadeia de caracteres (operadores de igualdade de cadeiade caracteres) aparecem no mesmo programa, esses literais de cadeia de caracteres fazem referência à mesma instância de cadeia de caracteresWhen 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. Por exemplo, a saída produzida porFor instance, the output produced by

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

ocorre True porque os dois literais se referem à mesma instância de cadeia de caracteres.is True because the two literals refer to the same string instance.

Literais de cadeia de caracteres interpoladosInterpolated string literals

Literais de cadeia de caracteres interpolados são semelhantes a literais de cadeia de caracteres, mas contêm buracos delimitados por { e } , onde as expressões podem ocorrer.Interpolated string literals are similar to string literals, but contain holes delimited by { and }, wherein expressions can occur. Em tempo de execução, as expressões são avaliadas com a finalidade de ter seus formulários textuais substituídos na cadeia de caracteres no local onde o orifício ocorre.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. A sintaxe e a semântica da interpolação de cadeias de caracteres são descritas na seção (cadeias de caracteres interpoladas).The syntax and semantics of string interpolation are described in section (Interpolated strings).

Como literais de cadeia de caracteres, literais de cadeia de caracteres interpolados podem ser regulares ou textuais.Like string literals, interpolated string literals can be either regular or verbatim. Os literais de cadeia de caracteres regulares interpolados são delimitados por $" e " , e os literais de cadeia de caracteres textuais interpolados são delimitados por $@" e " .Interpolated regular string literals are delimited by $" and ", and interpolated verbatim string literals are delimited by $@" and ".

Assim como outros literais, a análise léxica de um literal de cadeia de caracteres interpolado inicialmente resulta em um único token, de acordo com a gramática abaixo.Like other literals, lexical analysis of an interpolated string literal initially results in a single token, as per the grammar below. No entanto, antes da análise sintática, o único token de um literal de cadeia de caracteres interpolado é dividido em vários tokens para as partes da cadeia de caracteres que envolvem os orifícios, e os elementos de entrada que ocorrem nos orifícios são analisados lexicalmente de novo.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. Isso pode, por sua vez, produzir mais literais de cadeia de caracteres interpolados a serem processados, mas, se for lexicalmente correto, eventualmente levará a uma sequência de tokens para que a análise sintática seja processada.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)>'
    ;

Um token de interpolated_string_literal é reinterpretado como vários tokens e outros elementos de entrada da seguinte maneira, em ordem de ocorrência no interpolated_string_literal: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:

  • As ocorrências dos seguintes são reinterpretadas como tokens individuais separados: o $ sinal à esquerda, 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 e 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.
  • Ocorrências de regular_balanced_text e verbatim_balanced_text entre elas são reprocessadas como um input_section (análise lexical) e são reinterpretadas como a sequência resultante de elementos de entrada.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. Isso pode, por sua vez, incluir tokens literais de cadeia de caracteres interpolados a serem reinterpretados.These may in turn include interpolated string literal tokens to be reinterpreted.

A análise sintática recombinará os tokens em um interpolated_string_expression (cadeias de caracteres interpoladas).Syntactic analysis will recombine the tokens into an interpolated_string_expression (Interpolated strings).

Exemplos de TODOExamples TODO

O literal nuloThe null literal

null_literal
    : 'null'
    ;

O null_literal pode ser convertido implicitamente em um tipo de referência ou um tipo anulável.The null_literal can be implicitly converted to a reference type or nullable type.

Operadores e pontuadoresOperators and punctuators

Há vários tipos de operadores e pontuadores.There are several kinds of operators and punctuators. Os operadores são usados em expressões para descrever as operações que envolvem um ou mais operandos.Operators are used in expressions to describe operations involving one or more operands. Por exemplo, a expressão a + b usa o operador + para adicionar os dois operandos a e b.For example, the expression a + b uses the + operator to add the two operands a and b. Os pontuadores servem para agrupamento e separação.Punctuators are for grouping and separating.

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

right_shift
    : '>>'
    ;

right_shift_assignment
    : '>>='
    ;

A barra vertical nas produções right_shift e right_shift_assignment são usadas para indicar que, ao contrário de outras produções na gramática sintática, nenhum caractere de qualquer tipo (nem mesmo espaço em branco) é permitido entre os tokens.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. Essas produções são tratadas especialmente para habilitar a manipulação correta de type_parameter_list s (parâmetros de tipo).These productions are treated specially in order to enable the correct handling of type_parameter_list s (Type parameters).

Pré-processando diretivasPre-processing directives

As diretivas de pré-processamento fornecem a capacidade de ignorar condicionalmente seções de arquivos de origem, relatar condições de erro e aviso e delinear regiões distintas de código-fonte.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. O termo "diretivas de pré-processamento" é usado apenas para consistência com as linguagens de programação C e C++.The term "pre-processing directives" is used only for consistency with the C and C++ programming languages. No C#, não há uma etapa de pré-processamento separada; as diretivas de pré-processamento são processadas como parte da fase de análise lexical.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
    ;

As seguintes diretivas de pré-processamento estão disponíveis:The following pre-processing directives are available:

  • #define e #undef , que são usados para definir e desdefinir, respectivamente, símbolos de compilação condicional(diretivas de declaração).#define and #undef, which are used to define and undefine, respectively, conditional compilation symbols (Declaration directives).
  • #if, #elif , #else e #endif , que são usados para ignorar seções de código-fonte (diretivas decompilação condicional) condicionalmente.#if, #elif, #else, and #endif, which are used to conditionally skip sections of source code (Conditional compilation directives).
  • #line, que é usado para controlar os números de linha emitidos para erros e avisos (diretivas de linha).#line, which is used to control line numbers emitted for errors and warnings (Line directives).
  • #error e #warning , que são usados para emitir erros e avisos, respectivamente (diretivas de diagnóstico).#error and #warning, which are used to issue errors and warnings, respectively (Diagnostic directives).
  • #region e #endregion , que são usados para marcar explicitamente as seções do código-fonte (diretivas de região).#region and #endregion, which are used to explicitly mark sections of source code (Region directives).
  • #pragma, que é usado para especificar informações contextuais opcionais para o compilador (diretivas pragma).#pragma, which is used to specify optional contextual information to the compiler (Pragma directives).

Uma diretiva de pré-processamento sempre ocupa uma linha separada do código-fonte e sempre começa com um # caractere e um nome de diretiva de pré-processamento.A pre-processing directive always occupies a separate line of source code and always begins with a # character and a pre-processing directive name. Pode ocorrer espaço em branco antes do # caractere e entre o # caractere e o nome da diretiva.White space may occur before the # character and between the # character and the directive name.

Uma linha de origem contendo #define uma #undef diretiva,,,,, #if #elif #else #endif #line ou #endregion pode terminar com um comentário de linha única.A source line containing a #define, #undef, #if, #elif, #else, #endif, #line, or #endregion directive may end with a single-line comment. Comentários delimitados (o /* */ estilo de comentários) não são permitidos em linhas de origem que contêm diretivas de pré-processamento.Delimited comments (the /* */ style of comments) are not permitted on source lines containing pre-processing directives.

As diretivas de pré-processamento não são tokens e não fazem parte da gramática sintática do C#.Pre-processing directives are not tokens and are not part of the syntactic grammar of C#. No entanto, as diretivas de pré-processamento podem ser usadas para incluir ou excluir sequências de tokens e podem, dessa forma, afetar o significado de um programa em C#.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. Por exemplo, quando compilado, o programa: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
}

resulta na mesma sequência de tokens que o programa:results in the exact same sequence of tokens as the program:

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

Portanto, embora lexicalmente, os dois programas são bem diferentes, sintaticamente, são idênticos.Thus, whereas lexically, the two programs are quite different, syntactically, they are identical.

Símbolos de compilação condicionalConditional compilation symbols

A funcionalidade de compilação condicional fornecida pelas #if diretivas,, #elif #else e #endif é controlada por expressões de pré-processamento (expressões de pré-processamento) e símbolos de compilação condicional.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>'
    ;

Um símbolo de compilação condicional tem dois Estados possíveis: *defined _ ou _ undefined *.A conditional compilation symbol has two possible states: defined _ or _undefined**. No início do processamento lexical de um arquivo de origem, um símbolo de compilação condicional é indefinido, a menos que tenha sido explicitamente definido por um mecanismo externo (como uma opção de compilador de linha de comando).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). Quando uma #define diretiva é processada, o símbolo de compilação condicional chamado nessa diretiva é definido nesse arquivo de origem.When a #define directive is processed, the conditional compilation symbol named in that directive becomes defined in that source file. O símbolo permanece definido até que uma #undef diretiva para o mesmo símbolo seja processada ou até que o final do arquivo de origem seja atingido.The symbol remains defined until an #undef directive for that same symbol is processed, or until the end of the source file is reached. Uma implicação disso é que #define as #undef diretivas e em um arquivo de origem não têm nenhum efeito sobre outros arquivos de origem no mesmo programa.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.

Quando referenciado em uma expressão de pré-processamento, um símbolo de compilação condicional definido tem o valor booliano true e um símbolo de compilação condicional indefinido tem o valor booliano 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. Não há nenhum requisito de que os símbolos de compilação condicional sejam declarados explicitamente antes de serem referenciados em expressões de pré-processamento.There is no requirement that conditional compilation symbols be explicitly declared before they are referenced in pre-processing expressions. Em vez disso, os símbolos não declarados são simplesmente indefinidos e, portanto, têm o valor false .Instead, undeclared symbols are simply undefined and thus have the value false.

O espaço de nome para símbolos de compilação condicional é distinto e separado de todas as outras entidades nomeadas em um programa em C#.The name space for conditional compilation symbols is distinct and separate from all other named entities in a C# program. Símbolos de compilação condicional só podem ser referenciados em #define #undef diretivas e em expressões de pré-processamento.Conditional compilation symbols can only be referenced in #define and #undef directives and in pre-processing expressions.

Pré-processando expressõesPre-processing expressions

Expressões de pré-processamento podem ocorrer em #if diretivas e #elif .Pre-processing expressions can occur in #if and #elif directives. Os operadores ! , == , != , && e || são permitidos em expressões de pré-processamento, e os parênteses podem ser usados para Agrupamento.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? ')'
    ;

Quando referenciado em uma expressão de pré-processamento, um símbolo de compilação condicional definido tem o valor booliano true e um símbolo de compilação condicional indefinido tem o valor booliano 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.

A avaliação de uma expressão de pré-processamento sempre gera um valor booliano.Evaluation of a pre-processing expression always yields a boolean value. As regras de avaliação para uma expressão de pré-processamento são as mesmas que aquelas para uma expressão constante (expressões constantes), exceto que as únicas entidades definidas pelo usuário que podem ser referenciadas são símbolos de compilação condicional.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.

Diretivas de declaraçãoDeclaration directives

As diretivas de declaração são usadas para definir ou não definir símbolos de compilação condicional.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
    ;

O processamento de uma #define diretiva faz com que o símbolo de compilação condicional fornecido se torne definido, começando com a linha de origem que segue a diretiva.The processing of a #define directive causes the given conditional compilation symbol to become defined, starting with the source line that follows the directive. Da mesma forma, o processamento de uma #undef diretiva faz com que o símbolo de compilação condicional fornecido se torne indefinido, começando pela linha de origem que segue a diretiva.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.

As #define #undef diretivas e em um arquivo de origem devem ocorrer antes do primeiro token (tokens) no arquivo de origem; caso contrário, ocorrerá um erro em tempo de compilação.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. Em termos intuitivos #define , #undef as diretivas devem preceder qualquer "código real" no arquivo de origem.In intuitive terms, #define and #undef directives must precede any "real code" in the source file.

O exemplo:The example:

#define Enterprise

#if Professional || Enterprise
    #define Advanced
#endif

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

é válido porque as #define diretivas precedem o primeiro token (a namespace palavra-chave) no arquivo de origem.is valid because the #define directives precede the first token (the namespace keyword) in the source file.

O exemplo a seguir resulta em um erro de tempo de compilação porque um #define código real a seguir: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
}

Um #define pode definir um símbolo de compilação condicional que já está definido, sem que haja nenhum intervir #undef para esse símbolo.A #define may define a conditional compilation symbol that is already defined, without there being any intervening #undef for that symbol. O exemplo a seguir define um símbolo de compilação condicional A e, em seguida, define-o novamente.The example below defines a conditional compilation symbol A and then defines it again.

#define A
#define A

R #undef pode "desdefinir" um símbolo de compilação condicional que não está definido.A #undef may "undefine" a conditional compilation symbol that is not defined. O exemplo a seguir define um símbolo de compilação condicional A e, em seguida, a define duas vezes; embora o segundo #undef não tenha efeito, ele ainda é válido.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

Diretivas de compilação condicionalConditional compilation directives

As diretivas de compilação condicional são usadas para incluir ou excluir de forma condicional partes de um arquivo de origem.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 #>'
    ;

Conforme indicado pela sintaxe, as diretivas de compilação condicional devem ser escritas como conjuntos que consistem em, em ordem, em uma #if diretiva, zero ou mais #elif diretivas, zero ou uma #else diretiva e uma #endif diretiva.As 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. Entre as diretivas estão seções condicionais do código-fonte.Between the directives are conditional sections of source code. Cada seção é controlada pela diretiva imediatamente anterior.Each section is controlled by the immediately preceding directive. Uma seção condicional pode conter, por si só, diretivas de compilação condicional aninhadas desde que essas diretivas sejam conjuntos completos.A conditional section may itself contain nested conditional compilation directives provided these directives form complete sets.

Um pp_conditional seleciona no máximo um dos conditional_section s contidos para o processamento lexical normal:A pp_conditional selects at most one of the contained conditional_section s for normal lexical processing:

  • As pp_expression s das #if diretivas e #elif são avaliadas na ordem até que um resulte true .The pp_expression s of the #if and #elif directives are evaluated in order until one yields true. Se uma expressão produz true , a conditional_section da diretiva correspondente é selecionada.If an expression yields true, the conditional_section of the corresponding directive is selected.
  • Se todos os pp_expression s produzem false e se uma #else diretiva estiver presente, a conditional_section da #else diretiva será selecionada.If all pp_expression s yield false, and if an #else directive is present, the conditional_section of the #else directive is selected.
  • Caso contrário, nenhum conditional_section será selecionado.Otherwise, no conditional_section is selected.

O conditional_section selecionado, se houver, é processado como um input_section normal: o código-fonte contido na seção deve aderir à gramática léxica; os tokens são gerados a partir do código-fonte na seção; e as diretivas de pré-processamento na seção têm os efeitos prescritos.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.

Os conditional_section s restantes, se houver, são processados como skipped_section s: exceto pelas diretivas de pré-processamento, o código-fonte na seção não precisa aderir à gramática léxica; nenhum token é gerado a partir do código-fonte na seção; e as diretivas de pré-processamento na seção devem estar lexicalmente corretas, mas não são processadas de outra forma.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. Em um conditional_section que está sendo processado como um skipped_section, quaisquer conditional_section s aninhados (contidos em #if construções aninhadas... #endif e #region ... #endregion ) também são processados como skipped_section s.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.

O exemplo a seguir ilustra como as diretivas de compilação condicional podem ser aninhadas: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();
    }
}

Com exceção das diretivas de pré-processamento, o código-fonte ignorado não está sujeito à análise léxica.Except for pre-processing directives, skipped source code is not subject to lexical analysis. Por exemplo, o seguinte é válido apesar do comentário não finalizado na #else seção: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
    }
}

No entanto, observe que as diretivas de pré-processamento precisam ser lexicalmente corretas mesmo em seções ignoradas do código-fonte.Note, however, that pre-processing directives are required to be lexically correct even in skipped sections of source code.

As diretivas de pré-processamento não são processadas quando aparecem dentro de elementos de entrada de várias linhas.Pre-processing directives are not processed when they appear inside multi-line input elements. Por exemplo, o programa:For example, the program:

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

resulta na saída:results in the output:

hello,
#if Debug
        world
#else
        Nebraska
#endif

Em casos peculiares, o conjunto de diretivas de pré-processamento processadas pode depender da avaliação do pp_expression.In peculiar cases, the set of pre-processing directives that is processed might depend on the evaluation of the pp_expression. O exemplo:The example:

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

sempre produz o mesmo fluxo de token ( class Q { } ), independentemente de X ser definido ou não.always produces the same token stream (class Q { }), regardless of whether or not X is defined. Se X for definido, as únicas diretivas processadas serão #if e #endif , devido ao comentário de várias linhas.If X is defined, the only processed directives are #if and #endif, due to the multi-line comment. Se X for indefinido, três diretivas ( #if , #else , #endif ) fazem parte do conjunto de diretivas.If X is undefined, then three directives (#if, #else, #endif) are part of the directive set.

Diretivas de diagnósticoDiagnostic directives

As diretivas de diagnóstico são usadas para gerar explicitamente mensagens de erro e de aviso que são relatadas da mesma maneira que outros erros e avisos em tempo de compilação.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
    ;

O exemplo: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 {...}

sempre produz um aviso ("revisão de código necessária antes do check-in") e produz um erro de tempo de compilação ("uma compilação não pode ser depuração e varejo") se os símbolos condicionais Debug e Retail forem ambos definidos.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. Observe que um pp_message pode conter texto arbitrário; especificamente, ele não precisa conter tokens bem formados, conforme mostrado pelas aspas simples na palavra 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.

Diretivas de regiãoRegion directives

As diretivas de região são usadas para marcar explicitamente regiões do código-fonte.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
    ;

Nenhum significado semântico é anexado a uma região; as regiões são destinadas ao uso pelo programador ou por ferramentas automatizadas para marcar uma seção do código-fonte.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. A mensagem especificada em uma #region #endregion diretiva ou, da mesma forma, não tem significado semântico; ela simplesmente serve para identificar a região.The message specified in a #region or #endregion directive likewise has no semantic meaning; it merely serves to identify the region. A correspondência #region e as #endregion diretivas podem ter diferentes pp_message s.Matching #region and #endregion directives may have different pp_message s.

O processamento lexical de uma região:The lexical processing of a region:

#region
...
#endregion

corresponde exatamente ao processamento lexical de uma diretiva de compilação condicional do formulário:corresponds exactly to the lexical processing of a conditional compilation directive of the form:

#if true
...
#endif

Diretivas de linhaLine directives

As diretivas de linha podem ser usadas para alterar os números de linha e os nomes de arquivo de origem que são relatados pelo compilador em saída, como avisos e erros, e que são usados por atributos de informações do chamador (atributos de informações do chamador).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).

As diretivas de linha são usadas com mais frequência em ferramentas de metaprogramação que geram código-fonte C# de alguma outra entrada de texto.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 ">'
    ;

Quando não há #line diretivas presentes, o compilador relata os números de linha verdadeiros e os nomes de arquivo de origem em sua saída.When no #line directives are present, the compiler reports true line numbers and source file names in its output. Ao processar uma #line diretiva que inclui um line_indicator que não é default , o compilador trata a linha após a diretiva como tendo o número de linha fornecido (e o nome do arquivo, se especificado).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).

Uma #line default diretiva reverte o efeito de todas as diretivas de #line anteriores.A #line default directive reverses the effect of all preceding #line directives. O compilador relata informações de linha verdadeiras para linhas subsequentes, precisamente como se nenhuma das #line diretivas tivesse sido processada.The compiler reports true line information for subsequent lines, precisely as if no #line directives had been processed.

Uma #line hidden diretiva não tem efeito sobre o arquivo e os números de linha relatados em mensagens de erro, mas afeta a depuração de nível de origem.A #line hidden directive has no effect on the file and line numbers reported in error messages, but does affect source level debugging. Durante a depuração, todas as linhas entre uma #line hidden diretiva e a #line diretiva subsequente (que não é #line hidden ) não têm nenhuma informação de número de linha.When debugging, all lines between a #line hidden directive and the subsequent #line directive (that is not #line hidden) have no line number information. Ao percorrer o código no depurador, essas linhas serão ignoradas inteiramente.When stepping through code in the debugger, these lines will be skipped entirely.

Observe que uma file_name difere de um literal de cadeia de caracteres regular, pois os caracteres de escape não são processados; o \ caractere "" simplesmente designa um caractere de barra invertida comum dentro de um 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.

Diretivas pragmaPragma directives

A #pragma diretiva de pré-processamento é usada para especificar informações contextuais opcionais para o compilador.The #pragma preprocessing directive is used to specify optional contextual information to the compiler. As informações fornecidas em uma #pragma diretiva nunca alterarão a semântica do programa.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
    ;

O C# fornece #pragma diretivas para controlar os avisos do compilador.C# provides #pragma directives to control compiler warnings. As versões futuras do idioma podem incluir #pragma diretivas adicionais.Future versions of the language may include additional #pragma directives. Para garantir a interoperabilidade com outros compiladores C#, o compilador do Microsoft C# não emite erros de compilação para diretivas desconhecidas #pragma ; no entanto, essas diretivas geram avisos.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.

Aviso de pragmaPragma warning

A #pragma warning diretiva é usada para desabilitar ou restaurar todos ou um determinado conjunto de mensagens de aviso durante a compilação do texto do programa subsequente.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+)*
    ;

Uma #pragma warning diretiva que omite a lista de avisos afeta todos os avisos.A #pragma warning directive that omits the warning list affects all warnings. Uma #pragma warning diretiva que inclui uma lista de avisos afeta apenas os avisos especificados na lista.A #pragma warning directive that includes a warning list affects only those warnings that are specified in the list.

Uma #pragma warning disable diretiva desabilita todos ou o conjunto de avisos fornecido.A #pragma warning disable directive disables all or the given set of warnings.

Uma #pragma warning restore diretiva restaura todos ou o conjunto determinado de avisos para o estado que estava em vigor no início da unidade de compilação.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. Observe que, se um aviso específico tiver sido desabilitado externamente, um #pragma warning restore (seja para todos ou o aviso específico) não reabilitará esse aviso.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.

O exemplo a seguir mostra o uso de #pragma warning para desabilitar temporariamente o aviso relatado quando membros obsoletos são referenciados, usando o número de aviso do compilador do Microsoft C#.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
    }
}