Estructura léxicaLexical structure
ProgramasPrograms
Un programa de C# * _ consta de uno o varios archivos de código fuente, conocido formalmente como unidades de compilación* (unidades de compilación).A C# program _ consists of one or more _source files_, known formally as _ compilation units (Compilation units). Un archivo de origen es una secuencia ordenada de caracteres Unicode.A source file is an ordered sequence of Unicode characters. Los archivos de origen suelen tener una correspondencia uno a uno con los archivos de un sistema de archivos, pero esta correspondencia no es necesaria.Source files typically have a one-to-one correspondence with files in a file system, but this correspondence is not required. Para obtener la máxima portabilidad, se recomienda codificar los archivos de un sistema de archivos con la codificación UTF-8.For maximal portability, it is recommended that files in a file system be encoded with the UTF-8 encoding.
En términos conceptuales, un programa se compila mediante tres pasos:Conceptually speaking, a program is compiled using three steps:
- Transformación, que convierte un archivo de un repertorio de caracteres determinado y un esquema de codificación en una secuencia de caracteres Unicode.Transformation, which converts a file from a particular character repertoire and encoding scheme into a sequence of Unicode characters.
- Análisis léxico, que convierte una secuencia de caracteres de entrada Unicode en una secuencia de tokens.Lexical analysis, which translates a stream of Unicode input characters into a stream of tokens.
- Análisis sintáctico, que convierte el flujo de tokens en código ejecutable.Syntactic analysis, which translates the stream of tokens into executable code.
GramáticasGrammars
Esta especificación presenta la sintaxis del lenguaje de programación C# con dos gramáticas.This specification presents the syntax of the C# programming language using two grammars. La gramática léxica _ (gramática léxica) define cómo se combinan los caracteres Unicode para formar terminadores de línea, espacios en blanco, comentarios, tokens y directivas de procesamiento previo.The *lexical grammar _ (Lexical grammar) defines how Unicode characters are combined to form line terminators, white space, comments, tokens, and pre-processing directives. La _ gramática sintáctica* (gramática sintáctica) define el modo en que los tokens resultantes de la gramática léxica se combinan para formar programas de C#.The _ syntactic grammar* (Syntactic grammar) defines how the tokens resulting from the lexical grammar are combined to form C# programs.
Notación gramaticalGrammar notation
Las gramáticas léxicas y sintácticas se presentan en Backus-Naur formulario mediante la notación de la herramienta de gramática ANTLR.The lexical and syntactic grammars are presented in Backus-Naur form using the notation of the ANTLR grammar tool.
Gramática léxicaLexical grammar
La gramática léxica de C# se presenta en el análisis léxico, los tokensy las directivas de procesamiento previo.The lexical grammar of C# is presented in Lexical analysis, Tokens, and Pre-processing directives. Los símbolos de terminal de la gramática léxica son los caracteres del juego de caracteres Unicode y la gramática léxica especifica cómo se combinan los caracteres para formar tokens (tokens), espacios en blanco (espacio en blanco), comentarios (comentarios) y directivas de preprocesamiento (directivas de procesamiento previo).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 archivo de código fuente de un programa de C# debe ajustarse a la producción de entrada de la gramática léxica (análisis léxico).Every source file in a C# program must conform to the input production of the lexical grammar (Lexical analysis).
Gramática sintácticaSyntactic grammar
La gramática sintáctica de C# se presenta en los capítulos y los apéndices que siguen este capítulo.The syntactic grammar of C# is presented in the chapters and appendices that follow this chapter. Los símbolos de terminal de la gramática sintáctica son los tokens definidos por la gramática léxica y la gramática sintáctica especifica cómo se combinan los tokens para formar programas de 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 archivo de código fuente de un programa de C# debe ajustarse a la compilation_unit producción de la gramática sintáctica (unidades de compilación).Every source file in a C# program must conform to the compilation_unit production of the syntactic grammar (Compilation units).
Análisis léxicoLexical analysis
La producción de entrada define la estructura léxica de un archivo de código fuente de C#.The input production defines the lexical structure of a C# source file. Cada archivo de código fuente de un programa de C# debe ajustarse a esta producción de gramática léxica.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 componen la estructura léxica de un archivo de código fuente de C#: terminadores de línea (terminadores de línea), espacios en blanco (espacios en blanco), comentarios (comentarios), tokens (tokens) y directivas de preprocesamiento (directivas de procesamiento previo).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). De estos elementos básicos, solo los tokens son significativos en la gramática sintáctica de un programa de C# (gramática sintáctica).Of these basic elements, only tokens are significant in the syntactic grammar of a C# program (Syntactic grammar).
El procesamiento léxico de un archivo de código fuente de C# consiste en reducir el archivo en una secuencia de tokens que se convierte en la entrada del análisis sintáctico.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. Los terminadores de línea, los espacios en blanco y los comentarios pueden servir para separar los tokens y las directivas de procesamiento previo pueden provocar que se omitan las secciones del archivo de código fuente, pero, de lo contrario, estos elementos léxicos no tienen ningún impacto en la estructura sintáctica de un programa de 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.
En el caso de los literales de cadena interpolados (literales de cadena interpolados), un único token lo genera inicialmente el análisis léxico, pero se divide en varios elementos de entrada que se someten repetidamente al análisis léxico hasta que todos los literales de cadena interpolados se han resuelto.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. Los tokens resultantes sirven como entrada para el análisis sintáctico.The resulting tokens then serve as input to the syntactic analysis.
Cuando varias producciones de gramática léxica coinciden con una secuencia de caracteres de un archivo de código fuente, el procesamiento léxico siempre forma el elemento léxico más largo posible.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 ejemplo, la secuencia de caracteres // se procesa como el principio de un Comentario de una sola línea porque ese elemento léxico es más largo que un / token único.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 líneaLine terminators
Los terminadores de línea dividen los caracteres de un archivo de código fuente de C# en líneas.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)>'
;
Por compatibilidad con las herramientas de edición de código fuente que agregan marcadores de fin de archivo y para permitir que un archivo de código fuente se vea como una secuencia de líneas terminadas correctamente, se aplican las transformaciones siguientes, en orden, a cada archivo de código fuente de un programa de 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:
- Si el último carácter del archivo de código fuente es un carácter control-Z (
U+001A), este carácter se elimina.If the last character of the source file is a Control-Z character (U+001A), this character is deleted. - Un carácter de retorno de carro (
U+000D) se agrega al final del archivo de código fuente si ese archivo de código fuente no está vacío y si el último carácter del archivo de código fuente no es un retorno de carro ()U+000D, un salto de línea (U+000A), un separador de líneas (U+2028) o un separador de párrafo (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).
ComentariosComments
Se admiten dos formatos de comentarios: de una sola línea y delimitados.Two forms of comments are supported: single-line comments and delimited comments.\ Comentarios de una sola línea: empiece con los caracteres // y amplíe hasta el final de la línea de código fuente.\ Single-line comments _ start with the characters // and extend to the end of the source line. Los _comentarios delimitados_ comienzan con los caracteres /_ y terminan con los caracteres */ .Delimited comments start with the characters /_ and end with the characters */. Los comentarios delimitados pueden abarcar varias líneas.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 *>'
;
Los comentarios no se anidan.Comments do not nest. Las secuencias de caracteres /* y */ no tienen ningún significado especial dentro de un // Comentario y las secuencias de caracteres // y /* no tienen ningún significado especial dentro de un comentario 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.
Los comentarios no se procesan dentro de los literales de carácter y de cadena.Comments are not processed within character and string literals.
En el ejemploThe example
/* Hello, world program
This program writes "hello, world" to the console
*/
class Hello
{
static void Main() {
System.Console.WriteLine("hello, world");
}
}
se incluye un comentario delimitado.includes a delimited comment.
En el ejemploThe 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");
}
}
se muestran varios comentarios de una línea.shows several single-line comments.
Espacio en blancoWhite space
El espacio en blanco se define como cualquier carácter con la clase Unicode ZS (que incluye el carácter de espacio), así como el carácter de tabulación horizontal, el carácter de tabulación vertical y el carácter de avance de la forma.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
Hay varios tipos de tokens: identificadores, palabras clave, literales, operadores y signos de puntuación.There are several kinds of tokens: identifiers, keywords, literals, operators, and punctuators. Los espacios en blanco y los comentarios no son tokens, aunque actúan como separadores de 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
;
Secuencias de escape de caracteres UnicodeUnicode character escape sequences
Una secuencia de escape de caracteres Unicode representa un carácter Unicode.A Unicode character escape sequence represents a Unicode character. Las secuencias de escape de caracteres Unicode se procesan en identificadores (identificadores), literales de carácter (literales de carácter) y literales de cadena normales (literales de cadena).Unicode character escape sequences are processed in identifiers (Identifiers), character literals (Character literals), and regular string literals (String literals). Un escape de carácter Unicode no se procesa en ninguna otra ubicación (por ejemplo, para formar un operador, un signo de puntuación o una palabra clave).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
;
Una secuencia de escape Unicode representa el carácter Unicode que forma el número hexadecimal después de los \u caracteres "" o "" \U .A Unicode escape sequence represents the single Unicode character formed by the hexadecimal number following the "\u" or "\U" characters. Dado que C# usa una codificación de 16 bits de puntos de código Unicode en caracteres y valores de cadena, no se permite un carácter Unicode en el intervalo de U + 10000 a U + 10FFFF en un literal de carácter y se representa mediante un par suplente Unicode en un literal de cadena.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. No se admiten los caracteres Unicode con puntos de código anteriores a 0x10FFFF.Unicode characters with code points above 0x10FFFF are not supported.
No se realizan varias traducciones.Multiple translations are not performed. Por ejemplo, el literal de cadena " \u005Cu005C " es equivalente a " \u005C " en lugar de " \ ".For instance, the string literal "\u005Cu005C" is equivalent to "\u005C" rather than "\". El valor Unicode \u005C es el carácter " \ ".The Unicode value \u005C is the character "\".
En el ejemploThe example
class Class1
{
static void Test(bool \u0066) {
char c = '\u0066';
if (\u0066)
System.Console.WriteLine(c.ToString());
}
}
muestra varios usos de \u0066 , que es la secuencia de escape para la letra " f ".shows several uses of \u0066, which is the escape sequence for the letter "f". El programa es equivalente aThe program is equivalent to
class Class1
{
static void Test(bool f) {
char c = 'f';
if (f)
System.Console.WriteLine(c.ToString());
}
}
IdentificadoresIdentifiers
Las reglas para los identificadores que se proporcionan en esta sección corresponden exactamente a las recomendadas por el Anexo 31 del estándar Unicode, con la excepción de que el carácter de subrayado se permite como carácter inicial (como el tradicional en el lenguaje de programación C), las secuencias de escape Unicode se permiten en los identificadores y el @ carácter "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 obtener información sobre las clases de caracteres Unicode mencionadas anteriormente, vea el estándar Unicode, versión 3,0, sección 4,5.For information on the Unicode character classes mentioned above, see The Unicode Standard, Version 3.0, section 4.5.
Entre los ejemplos de identificadores válidos se incluyen " identifier1 ", " _identifier2 " y " @if ".Examples of valid identifiers include "identifier1", "_identifier2", and "@if".
Un identificador en un programa conforme debe estar en el formato canónico definido por la forma de normalización Unicode C, tal y como se define en el Anexo 15 del estándar 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. El comportamiento cuando se encuentra un identificador no en la forma de normalización C está definido por la implementación; sin embargo, no es necesario un diagnóstico.The behavior when encountering an identifier not in Normalization Form C is implementation-defined; however, a diagnostic is not required.
El prefijo " @ " permite el uso de palabras clave como identificadores, lo que resulta útil al interactuar con otros lenguajes de programación.The prefix "@" enables the use of keywords as identifiers, which is useful when interfacing with other programming languages. El carácter @ no es realmente parte del identificador, por lo que el identificador podría verse en otros idiomas como un identificador normal, sin el prefijo.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. Un identificador con un @ prefijo se denomina identificador textual.An identifier with an @ prefix is called a verbatim identifier. Se permite el uso del @ prefijo para los identificadores que no son palabras clave, pero se desaconseja encarecidamente como una cuestión de estilo.Use of the @ prefix for identifiers that are not keywords is permitted, but strongly discouraged as a matter of style.
El ejemplo: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 una clase denominada " class " con un método estático denominado " static " que toma un parámetro con el nombre " bool ".defines a class named "class" with a static method named "static" that takes a parameter named "bool". Tenga en cuenta que, puesto que no se permiten los escapes de Unicode en palabras clave, el token " cl\u0061ss " es un identificador y es el mismo identificador que " @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".
Dos identificadores se consideran iguales si son idénticos después de aplicar las transformaciones siguientes, en orden:Two identifiers are considered the same if they are identical after the following transformations are applied, in order:
- El prefijo "
@", si se utiliza, se quita.The prefix "@", if used, is removed. - Cada unicode_escape_sequence se transforma en el carácter Unicode correspondiente.Each unicode_escape_sequence is transformed into its corresponding Unicode character.
- Se quitan los formatting_character s.Any formatting_character s are removed.
Los identificadores que contienen dos caracteres de subrayado consecutivos ( U+005F ) se reservan para su uso por parte de la implementación.Identifiers containing two consecutive underscore characters (U+005F) are reserved for use by the implementation. Por ejemplo, una implementación podría proporcionar palabras clave extendidas que comienzan con dos guiones bajos.For example, an implementation might provide extended keywords that begin with two underscores.
Palabras claveKeywords
Una palabra clave es una secuencia similar a un identificador de caracteres que está reservada y no se puede usar como identificador excepto cuando está precedida por el @ carácter.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'
;
En algunos lugares de la gramática, los identificadores específicos tienen un significado especial, pero no son palabras clave.In some places in the grammar, specific identifiers have special meaning, but are not keywords. Dichos identificadores se denominan a veces "palabras clave contextuales".Such identifiers are sometimes referred to as "contextual keywords". Por ejemplo, dentro de una declaración de propiedad, los get identificadores "" y " set " tienen un significado especial (descriptores de acceso).For example, within a property declaration, the "get" and "set" identifiers have special meaning (Accessors). Un identificador distinto de get o set nunca se permite en estas ubicaciones, por lo que este uso no entra en conflicto con el uso de estas palabras 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. En otros casos, como con el identificador " var " en las declaraciones de variables locales con tipo implícito (declaraciones devariables locales), una palabra clave contextual puede entrar en conflicto con los nombres 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. En tales casos, el nombre declarado tiene prioridad sobre el uso del identificador como palabra clave contextual.In such cases, the declared name takes precedence over the use of the identifier as a contextual keyword.
LiteralesLiterals
Un literal es una representación de código fuente de un valor.A literal is a source code representation of a value.
literal
: boolean_literal
| integer_literal
| real_literal
| character_literal
| string_literal
| null_literal
;
booleanos, literalesBoolean literals
Hay dos valores literales booleanos: true y false .There are two boolean literal values: true and false.
boolean_literal
: 'true'
| 'false'
;
El tipo de una boolean_literal es bool .The type of a boolean_literal is bool.
Literales enterosInteger literals
Los literales enteros se utilizan para escribir valores de tipos int , uint , long y ulong .Integer literals are used to write values of types int, uint, long, and ulong. Los literales enteros tienen dos formas posibles: decimal y 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';
El tipo de un literal entero se determina de la siguiente manera:The type of an integer literal is determined as follows:
- Si el literal no tiene sufijo, tiene el primero de estos tipos en el que se puede representar su valor:
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. - Si el literal tiene el sufijo
Uou, tiene el primero de estos tipos en el que se puede representar su valor:uint,ulong.If the literal is suffixed byUoru, it has the first of these types in which its value can be represented:uint,ulong. - Si el literal tiene el sufijo
Lol, tiene el primero de estos tipos en el que se puede representar su valor:long,ulong.If the literal is suffixed byLorl, it has the first of these types in which its value can be represented:long,ulong. - Si el literal tiene el sufijo
UL,Ul,uL,ul,LU,Lu,lUolu, es de tipoulong.If the literal is suffixed byUL,Ul,uL,ul,LU,Lu,lU, orlu, it is of typeulong.
Si el valor representado por un literal entero está fuera del intervalo del ulong tipo, se produce un error en tiempo de compilación.If the value represented by an integer literal is outside the range of the ulong type, a compile-time error occurs.
Como cuestión de estilo, se sugiere que " L " se use en lugar de " l " cuando se escriben literales de tipo long , ya que es fácil confundir la letra " l " con el 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 los valores y más pequeños posibles int long se escriban como literales enteros decimales, existen las dos reglas siguientes:To permit the smallest possible int and long values to be written as decimal integer literals, the following two rules exist:
- Cuando un decimal_integer_literal con el valor 2147483648 (2 ^ 31) y no hay ningún integer_type_suffix aparece como el token inmediatamente después de un token de operador unario menos (operador unario menos), el resultado es una constante de tipo
intcon el 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 typeintwith the value -2147483648 (-2^31). En todas las demás situaciones, tal decimal_integer_literal es de tipouint.In all other situations, such a decimal_integer_literal is of typeuint. - Cuando un decimal_integer_literal con el valor 9223372036854775808 (2 ^ 63) y no integer_type_suffix o el integer_type_suffix
Lolaparece como el token inmediatamente después de un token de operador unario menos (operador unario menos), el resultado es una constante de tipolongcon el 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_suffixLorlappears as the token immediately following a unary minus operator token (Unary minus operator), the result is a constant of typelongwith the value -9223372036854775808 (-2^63). En todas las demás situaciones, tal decimal_integer_literal es de tipoulong.In all other situations, such a decimal_integer_literal is of typeulong.
Literales realesReal literals
Los literales reales se utilizan para escribir valores de tipos float , double y 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'
;
Si no se especifica ningún real_type_suffix , el tipo del literal real es double .If no real_type_suffix is specified, the type of the real literal is double. De lo contrario, el sufijo de tipo real determina el tipo del literal real, como se indica a continuación:Otherwise, the real type suffix determines the type of the real literal, as follows:
- Un literal real con sufijo
Fofes de tipofloat.A real literal suffixed byForfis of typefloat. Por ejemplo, los literales1f,1.5f,1e10fy123.456Fson de tipofloat.For example, the literals1f,1.5f,1e10f, and123.456Fare all of typefloat. - Un literal real con sufijo
Dodes de tipodouble.A real literal suffixed byDordis of typedouble. Por ejemplo, los literales1d,1.5d,1e10dy123.456Dson de tipodouble.For example, the literals1d,1.5d,1e10d, and123.456Dare all of typedouble. - Un literal real con sufijo
Momes de tipodecimal.A real literal suffixed byMormis of typedecimal. Por ejemplo, los literales1m,1.5m,1e10my123.456Mson de tipodecimal.For example, the literals1m,1.5m,1e10m, and123.456Mare all of typedecimal. Este literal se convierte en undecimalvalor mediante el uso del valor exacto, y, si es necesario, se redondea al valor representable más cercano mediante el redondeo bancario (el tipo decimal).This literal is converted to adecimalvalue by taking the exact value, and, if necessary, rounding to the nearest representable value using banker's rounding (The decimal type). Cualquier escala aparente en el literal se conserva a menos que el valor se redondee o el valor sea cero (en cuyo caso, el signo y la escala serán 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). Por lo tanto, el literal se2.900manalizará para formar el decimal con el signo0, el coeficiente2900y la escala3.Hence, the literal2.900mwill be parsed to form the decimal with sign0, coefficient2900, and scale3.
Si el literal especificado no se puede representar en el tipo indicado, se produce un error en tiempo de compilación.If the specified literal cannot be represented in the indicated type, a compile-time error occurs.
El valor de un literal real de tipo float o double se determina mediante el modo "redondeo al más cercano" de IEEE.The value of a real literal of type float or double is determined by using the IEEE "round to nearest" mode.
Tenga en cuenta que, en un literal real, siempre se requieren dígitos decimales después del separador decimal.Note that in a real literal, decimal digits are always required after the decimal point. Por ejemplo, 1.3F es un literal real pero 1.F no es.For example, 1.3F is a real literal but 1.F is not.
Literales de carácterCharacter literals
Un literal de carácter representa un carácter único y normalmente consta de un carácter entre comillas, como en 'a' .A character literal represents a single character, and usually consists of a character in quotes, as in 'a'.
Nota: la notación gramatical ANTLR hace que la siguiente confusión.Note: The ANTLR grammar notation makes the following confusing! En ANTLR, cuando escribe, \' representa una comilla simple ' .In ANTLR, when you write \' it stands for a single quote '. Y, cuando se escribe \\ , representa una sola barra diagonal inversa \ .And when you write \\ it stands for a single backslash \. Por lo tanto, la primera regla para un literal de carácter significa que empieza con una comilla simple, un carácter y, a continuación, una comilla simple.Therefore the first rule for a character literal means it starts with a single quote, then a character, then a single quote. Y las once secuencias de escape simples posibles son \' , \" , \\ , \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?;
Un carácter que sigue a un carácter de barra diagonal inversa ( \ ) en un carácter debe ser uno de los caracteres siguientes: ' , " , \ , 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. De lo contrario, se produce un error en tiempo de compilación.Otherwise, a compile-time error occurs.
Una secuencia de escape hexadecimal representa un único carácter Unicode, con el valor formado por el número hexadecimal siguiente a " \x ".A hexadecimal escape sequence represents a single Unicode character, with the value formed by the hexadecimal number following "\x".
Si el valor representado por un literal de carácter es mayor que U+FFFF , se produce un error en tiempo de compilación.If the value represented by a character literal is greater than U+FFFF, a compile-time error occurs.
Una secuencia de escape de caracteres Unicode (secuencias de escape de caracteres Unicode) en un literal de carácter debe estar en el intervalo de U+0000 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.
Una secuencia de escape simple representa una codificación de caracteres Unicode, tal y como se describe en la tabla siguiente.A simple escape sequence represents a Unicode character encoding, as described in the table below.
| Secuencia de escapeEscape sequence | Nombre de carácterCharacter name | Codificación UnicodeUnicode encoding |
|---|---|---|
\' |
Comilla simpleSingle quote | 0x0027 |
\" |
Comilla dobleDouble quote | 0x0022 |
\\ |
Barra diagonal inversaBackslash | 0x005C |
\0 |
NullNull | 0x0000 |
\a |
AlertaAlert | 0x0007 |
\b |
RetrocesoBackspace | 0x0008 |
\f |
Avance de páginaForm feed | 0x000C |
\n |
Nueva líneaNew line | 0x000A |
\r |
Retorno de carroCarriage return | 0x000D |
\t |
Tabulación horizontalHorizontal tab | 0x0009 |
\v |
Tabulación verticalVertical tab | 0x000B |
El tipo de una character_literal es char .The type of a character_literal is char.
Literales de cadenaString literals
C# admite dos formatos de literales de cadena: * literales de cadena normales _ y _ literales de cadena textuales *.C# supports two forms of string literals: regular string literals _ and _verbatim string literals**.
Un literal de cadena normal consta de cero o más caracteres entre comillas dobles, como en "hello" , y puede incluir secuencias de escape simples (por ejemplo, \t para el carácter de tabulación) y secuencias de escape hexadecimal y 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.
Un literal de cadena textual se compone de un @ carácter seguido de un carácter de comilla doble, cero o más caracteres, y un carácter de comilla doble de cierre.A verbatim string literal consists of an @ character followed by a double-quote character, zero or more characters, and a closing double-quote character. Un ejemplo sencillo es @"hello" .A simple example is @"hello". En un literal de cadena textual, los caracteres entre los delimitadores se interpretan literalmente, la única excepción es un quote_escape_sequence.In a verbatim string literal, the characters between the delimiters are interpreted verbatim, the only exception being a quote_escape_sequence. En concreto, las secuencias de escape simples, y las secuencias de escape hexadecimales y Unicode no se procesan en literales de cadena textuales.In particular, simple escape sequences, and hexadecimal and Unicode escape sequences are not processed in verbatim string literals. Un literal de cadena textual puede abarcar varias líneas.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
: '""'
;
Un carácter que sigue a un carácter de barra diagonal inversa ( \ ) en un regular_string_literal_character debe ser uno de los caracteres siguientes: ' , " , \ , 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. De lo contrario, se produce un error en tiempo de compilación.Otherwise, a compile-time error occurs.
En el ejemploThe 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";
muestra varios literales de cadena.shows a variety of string literals. El último literal de cadena, j , es un literal de cadena textual que abarca varias líneas.The last string literal, j, is a verbatim string literal that spans multiple lines. Los caracteres entre comillas, incluidos los espacios en blanco, como los caracteres de nueva línea, se conservan literalmente.The characters between the quotation marks, including white space such as new line characters, are preserved verbatim.
Dado que una secuencia de escape hexadecimal puede tener un número variable de dígitos hexadecimales, el literal de cadena "\x123" contiene un carácter único con el 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 crear una cadena que contenga el carácter con el valor hexadecimal 12 seguido del carácter 3, puede "\x00123" escribir "\x12" + "3" en su lugar o.To create a string containing the character with hex value 12 followed by the character 3, one could write "\x00123" or "\x12" + "3" instead.
El tipo de una string_literal es string .The type of a string_literal is string.
Cada literal de cadena no tiene necesariamente como resultado una nueva instancia de cadena.Each string literal does not necessarily result in a new string instance. Cuando dos o más literales de cadena que son equivalentes de acuerdo con el operador de igualdad de cadena (operadores de igualdad de cadena) aparecen en el mismo programa, estos literales de cadena hacen referencia a la misma instancia de cadena.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. Por ejemplo, la salida generada porFor instance, the output produced by
class Test
{
static void Main() {
object a = "hello";
object b = "hello";
System.Console.WriteLine(a == b);
}
}
se True debe a que los dos literales hacen referencia a la misma instancia de cadena.is True because the two literals refer to the same string instance.
Literales de cadena interpoladosInterpolated string literals
Los literales de cadena interpolados son similares a los literales de cadena, pero contienen huecos delimitados por { y } , donde se pueden producir expresiones.Interpolated string literals are similar to string literals, but contain holes delimited by { and }, wherein expressions can occur. En tiempo de ejecución, las expresiones se evalúan con el propósito de tener sus formularios de texto sustituidos en la cadena en el lugar donde se produce el agujero.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. La sintaxis y la semántica de la interpolación de cadenas se describen en la sección (cadenas interpoladas).The syntax and semantics of string interpolation are described in section (Interpolated strings).
Al igual que los literales de cadena, los literales de cadena interpolados pueden ser normales o literales.Like string literals, interpolated string literals can be either regular or verbatim. Los literales de cadena normales interpolados están delimitados por $" y " , y los literales de cadena textual interpolados están delimitados por $@" y " .Interpolated regular string literals are delimited by $" and ", and interpolated verbatim string literals are delimited by $@" and ".
Al igual que otros literales, el análisis léxico de un literal de cadena interpolada produce inicialmente un token único, según la gramática siguiente.Like other literals, lexical analysis of an interpolated string literal initially results in a single token, as per the grammar below. Sin embargo, antes del análisis sintáctico, el token único de un literal de cadena interpolada se divide en varios tokens para las partes de la cadena que los rodean, y los elementos de entrada que se producen en los huecos se analizan léxicamente de nuevo.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. Esto puede, a su vez, generar más literales de cadena interpolados que se van a procesar, pero, si léxicamente correcto, dará lugar a una secuencia de tokens para que los procese el análisis sintáctico.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)>'
;
Un token de interpolated_string_literal se interpreta como varios tokens y otros elementos de entrada como se indica a continuación, en el orden de aparición en el 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:
- Las apariciones de lo siguiente se interpretan como tokens individuales independientes: el
$signo inicial, la interpolated_regular_string_whole, la interpolated_regular_string_start, el interpolated_regular_string_mid, interpolated_regular_string_end, interpolated_verbatim_string_whole, interpolated_verbatim_string_start, interpolated_verbatim_string_mid y 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. - Las repeticiones de regular_balanced_text y verbatim_balanced_text entre ellas se reprocesan como un input_section (análisis léxico) y se reinterpretan como la secuencia resultante de los 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. A su vez, pueden incluir tokens literales de cadena interpolados que se van a reinterpretar.These may in turn include interpolated string literal tokens to be reinterpreted.
El análisis sintáctico volverá a combinar los tokens en un interpolated_string_expression (cadenas interpoladas).Syntactic analysis will recombine the tokens into an interpolated_string_expression (Interpolated strings).
Ejemplos TODOExamples TODO
El literal nullThe null literal
null_literal
: 'null'
;
El null_literal se puede convertir implícitamente a un tipo de referencia o a un tipo que acepta valores NULL.The null_literal can be implicitly converted to a reference type or nullable type.
Operadores y signos de puntuaciónOperators and punctuators
Hay varios tipos de operadores y signos de puntuación.There are several kinds of operators and punctuators. Los operadores se usan en expresiones para describir las operaciones con uno o varios operandos implicados.Operators are used in expressions to describe operations involving one or more operands. Por ejemplo, la expresión a + b usa el operador + para agregar los dos operandos a y b.For example, the expression a + b uses the + operator to add the two operands a and b. Los signos de puntuación se usan para agrupar y separar.Punctuators are for grouping and separating.
operator_or_punctuator
: '{' | '}' | '[' | ']' | '(' | ')' | '.' | ',' | ':' | ';'
| '+' | '-' | '*' | '/' | '%' | '&' | '|' | '^' | '!' | '~'
| '=' | '<' | '>' | '?' | '??' | '::' | '++' | '--' | '&&' | '||'
| '->' | '==' | '!=' | '<=' | '>=' | '+=' | '-=' | '*=' | '/=' | '%='
| '&=' | '|=' | '^=' | '<<' | '<<=' | '=>'
;
right_shift
: '>>'
;
right_shift_assignment
: '>>='
;
La barra vertical de las producciones RIGHT_SHIFT y right_shift_assignment se utiliza para indicar que, a diferencia de otras producciones en la gramática sintáctica, no se permiten caracteres de ningún tipo (ni siquiera espacios en blanco) entre los 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. Estas producciones se tratan de forma especial para habilitar el control correcto 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).
Directivas de procesamiento previoPre-processing directives
Las directivas de procesamiento previo proporcionan la capacidad de omitir condicionalmente las secciones de los archivos de código fuente, notificar las condiciones de error y ADVERTENCIA, y para delimitar distintas regiones del código fuente.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. El término "directivas de procesamiento previo" solo se usa para mantener la coherencia con los lenguajes de programación C y C++.The term "pre-processing directives" is used only for consistency with the C and C++ programming languages. En C#, no hay ningún paso de procesamiento previo independiente; las directivas de procesamiento previo se procesan como parte de la fase de análisis léxico.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
;
Están disponibles las siguientes directivas de procesamiento previo:The following pre-processing directives are available:
#definey#undef, que se usan para definir y anular la definición, respectivamente, de símbolos de compilación condicional (directivas de declaración).#defineand#undef, which are used to define and undefine, respectively, conditional compilation symbols (Declaration directives).#if,#elif,#elsey#endif, que se usan para omitir condicionalmente las secciones del código fuente (directivas de compilación condicional).#if,#elif,#else, and#endif, which are used to conditionally skip sections of source code (Conditional compilation directives).#line, que se usa para controlar los números de línea emitidos para errores y advertencias (directivas de línea).#line, which is used to control line numbers emitted for errors and warnings (Line directives).#errory#warning, que se usan para emitir errores y advertencias, respectivamente (directivas de diagnóstico).#errorand#warning, which are used to issue errors and warnings, respectively (Diagnostic directives).#regiony#endregion, que se usan para marcar explícitamente las secciones del código fuente (directivas de región).#regionand#endregion, which are used to explicitly mark sections of source code (Region directives).#pragma, que se usa para especificar información contextual opcional para el compilador (directivas pragma).#pragma, which is used to specify optional contextual information to the compiler (Pragma directives).
Una directiva de procesamiento previo siempre ocupa una línea de código fuente independiente y siempre comienza con un # carácter y un nombre de directiva de preprocesamiento.A pre-processing directive always occupies a separate line of source code and always begins with a # character and a pre-processing directive name. Los espacios en blanco pueden aparecer antes del # carácter y entre el # carácter y el nombre de la Directiva.White space may occur before the # character and between the # character and the directive name.
Una línea de código fuente que contiene una #define #undef Directiva,, #if , #elif , #else , #endif , #line o #endregion puede terminar con un Comentario de una sola línea.A source line containing a #define, #undef, #if, #elif, #else, #endif, #line, or #endregion directive may end with a single-line comment. Los comentarios delimitados (el /* */ estilo de los comentarios) no se permiten en líneas de código fuente que contengan directivas de procesamiento previo.Delimited comments (the /* */ style of comments) are not permitted on source lines containing pre-processing directives.
Las directivas de procesamiento previo no son tokens y no forman parte de la gramática sintáctica de C#.Pre-processing directives are not tokens and are not part of the syntactic grammar of C#. Sin embargo, las directivas de procesamiento previo se pueden usar para incluir o excluir secuencias de tokens y, de ese modo, pueden afectar al significado de un programa de 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 ejemplo, cuando se compila, el 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
}
da como resultado la misma secuencia de tokens que el programa:results in the exact same sequence of tokens as the program:
class C
{
void F() {}
void I() {}
}
Por lo tanto, mientras que los dos programas son bastante diferentes y sintácticamente, son idénticos.Thus, whereas lexically, the two programs are quite different, syntactically, they are identical.
Símbolos de compilación condicionalConditional compilation symbols
La funcionalidad de compilación condicional proporcionada por #if las #elif directivas,, #else y #endif se controla a través de expresiones de procesamiento previo (expresiones de procesamiento previo) y símbolos de compilación 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>'
;
Un símbolo de compilación condicional tiene dos Estados posibles: *Defined _ o _ undefined *.A conditional compilation symbol has two possible states: defined _ or _undefined**. Al principio del procesamiento léxico de un archivo de código fuente, un símbolo de compilación condicional es indefinido, a menos que se haya definido explícitamente mediante un mecanismo externo (como una opción del compilador de línea de comandos).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). Cuando #define se procesa una directiva, el símbolo de compilación condicional denominado en esa Directiva se define en ese archivo de código fuente.When a #define directive is processed, the conditional compilation symbol named in that directive becomes defined in that source file. El símbolo permanece definido hasta que #undef se procesa una directiva para el mismo símbolo, o hasta que se alcanza el final del archivo de código fuente.The symbol remains defined until an #undef directive for that same symbol is processed, or until the end of the source file is reached. Una implicación de esto es que #define #undef las directivas y de un archivo de código fuente no tienen ningún efecto en otros archivos de código fuente del mismo 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.
Cuando se hace referencia en una expresión de procesamiento previo, un símbolo de compilación condicional definido tiene el valor booleano true y un símbolo de compilación condicional sin definir tiene el valor booleano 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. No hay ningún requisito de que los símbolos de compilación condicional se declaren explícitamente antes de que se haga referencia a ellos en expresiones de procesamiento previo.There is no requirement that conditional compilation symbols be explicitly declared before they are referenced in pre-processing expressions. En su lugar, los símbolos no declarados simplemente están sin definir y, por tanto, tienen el valor false .Instead, undeclared symbols are simply undefined and thus have the value false.
El espacio de nombres de los símbolos de compilación condicional es distinto y separado de todas las demás entidades con nombre en un programa de C#.The name space for conditional compilation symbols is distinct and separate from all other named entities in a C# program. Solo se puede hacer referencia a los símbolos de compilación condicional en las #define #undef directivas y y en las expresiones de procesamiento previo.Conditional compilation symbols can only be referenced in #define and #undef directives and in pre-processing expressions.
Expresiones de procesamiento previoPre-processing expressions
Las expresiones de procesamiento previo pueden producirse en las #if #elif directivas y.Pre-processing expressions can occur in #if and #elif directives. Los operadores ! , == , != && y || se permiten en las expresiones de procesamiento previo y los paréntesis se pueden usar para la agrupación.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? ')'
;
Cuando se hace referencia en una expresión de procesamiento previo, un símbolo de compilación condicional definido tiene el valor booleano true y un símbolo de compilación condicional sin definir tiene el valor booleano 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.
La evaluación de una expresión de procesamiento previo siempre produce un valor booleano.Evaluation of a pre-processing expression always yields a boolean value. Las reglas de evaluación de una expresión de procesamiento previo son las mismas que las de una expresión constante (expresiones constantes), salvo que las únicas entidades definidas por el usuario a las que se puede hacer referencia son símbolos de compilación condicionales.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.
Directivas de declaraciónDeclaration directives
Las directivas de declaración se utilizan para definir o anular la definición de símbolos de compilación 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
;
El procesamiento de una #define Directiva hace que se defina el símbolo de compilación condicional dado, empezando por la línea de código fuente que sigue a la Directiva.The processing of a #define directive causes the given conditional compilation symbol to become defined, starting with the source line that follows the directive. Del mismo modo, el procesamiento de una #undef Directiva hace que el símbolo de compilación condicional dado quede sin definir, empezando por la línea de código fuente que sigue a la Directiva.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.
Las #define #undef directivas y de un archivo de código fuente deben aparecer antes del primer token (tokens) en el archivo de código fuente; de lo contrario, se produce un error en tiempo de compilación.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. En términos intuitivos, #define y #undef las directivas deben preceder a cualquier "código real" en el archivo de código fuente.In intuitive terms, #define and #undef directives must precede any "real code" in the source file.
El ejemplo:The example:
#define Enterprise
#if Professional || Enterprise
#define Advanced
#endif
namespace Megacorp.Data
{
#if Advanced
class PivotTable {...}
#endif
}
es válido porque las #define directivas preceden al primer token (la namespace palabra clave) en el archivo de código fuente.is valid because the #define directives precede the first token (the namespace keyword) in the source file.
En el ejemplo siguiente se produce un error en tiempo de compilación porque un #define sigue código real: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
}
#definePuede definir un símbolo de compilación condicional que ya esté definido, sin que intervenga ningún #undef símbolo.A #define may define a conditional compilation symbol that is already defined, without there being any intervening #undef for that symbol. En el ejemplo siguiente se define un símbolo de compilación condicional A y, a continuación, se define de nuevo.The example below defines a conditional compilation symbol A and then defines it again.
#define A
#define A
Un #undef puede "anular la definición" de un símbolo de compilación condicional que no está definido.A #undef may "undefine" a conditional compilation symbol that is not defined. En el ejemplo siguiente se define un símbolo de compilación condicional A y, a continuación, se anula su definición dos veces; aunque el segundo #undef no tiene ningún efecto, sigue siendo 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
Directivas de compilación condicionalConditional compilation directives
Las directivas de compilación condicional se usan para incluir o excluir de forma condicional partes de un archivo de código fuente.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 #>'
;
Como se indica en la sintaxis, las directivas de compilación condicional se deben escribir como conjuntos compuestos de, en orden, una #if Directiva, cero o más #elif directivas, cero o una #else Directiva y una #endif Directiva.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 las directivas se encuentran las secciones condicionales del código fuente.Between the directives are conditional sections of source code. Cada sección se controla mediante la Directiva inmediatamente anterior.Each section is controlled by the immediately preceding directive. Una sección condicional puede contener directivas de compilación condicional anidadas, siempre que estas directivas formen conjuntos completos.A conditional section may itself contain nested conditional compilation directives provided these directives form complete sets.
Un pp_conditional selecciona como máximo uno de los conditional_section s incluidos para el procesamiento léxico normal:A pp_conditional selects at most one of the contained conditional_section s for normal lexical processing:
- Los pp_expression s de las
#if#elifdirectivas y se evalúan en orden hasta que se produce unatrue.The pp_expression s of the#ifand#elifdirectives are evaluated in order until one yieldstrue. Si una expresión producetrue, se selecciona la conditional_section de la directiva correspondiente.If an expression yieldstrue, the conditional_section of the corresponding directive is selected. - Si todos los pp_expression producen
falsey, si una#elseDirectiva está presente, se selecciona el conditional_section de la#elseDirectiva.If all pp_expression s yieldfalse, and if an#elsedirective is present, the conditional_section of the#elsedirective is selected. - De lo contrario, no se selecciona ningún conditional_section .Otherwise, no conditional_section is selected.
La conditional_section seleccionada, si la hay, se procesa como una input_section normal: el código fuente contenido en la sección debe adherirse a la gramática léxica; los tokens se generan a partir del código fuente de la sección. y las directivas de procesamiento previo de la sección tienen los efectos 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.
El resto de conditional_section s, si los hay, se procesan como skipped_section s: excepto las directivas de procesamiento previo, el código fuente de la sección no necesita adherirse a la gramática léxica; no se generan tokens a partir del código fuente de la sección; y las directivas de procesamiento previo de la sección deben ser léxicamente correctas, pero no se procesan de otra manera.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. Dentro de un conditional_section que se está procesando como una skipped_section, cualquier conditional_section anidado (contenido en construcciones anidadas #if ... #endif y #region ... #endregion ) también se procesa 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.
En el ejemplo siguiente se muestra cómo se pueden anidar las directivas de compilación condicional: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();
}
}
Excepto en el caso de las directivas de procesamiento previo, el código fuente omitido no está sujeto al análisis léxico.Except for pre-processing directives, skipped source code is not subject to lexical analysis. Por ejemplo, lo siguiente es válido a pesar del comentario sin terminar en la #else sección: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
}
}
Sin embargo, tenga en cuenta que las directivas de procesamiento previo deben ser léxicamente correctas incluso en secciones omitidas del código fuente.Note, however, that pre-processing directives are required to be lexically correct even in skipped sections of source code.
Las directivas de procesamiento previo no se procesan cuando aparecen dentro de elementos de entrada de varias líneas.Pre-processing directives are not processed when they appear inside multi-line input elements. Por ejemplo, el programa:For example, the program:
class Hello
{
static void Main() {
System.Console.WriteLine(@"hello,
#if Debug
world
#else
Nebraska
#endif
");
}
}
da como resultado el resultado:results in the output:
hello,
#if Debug
world
#else
Nebraska
#endif
En casos peculiares, el conjunto de directivas de procesamiento previo que se procesa puede depender de la evaluación del pp_expression.In peculiar cases, the set of pre-processing directives that is processed might depend on the evaluation of the pp_expression. El ejemplo:The example:
#if X
/*
#else
/* */ class Q { }
#endif
siempre genera el mismo flujo de token ( class Q { } ), independientemente de si X está definido o no.always produces the same token stream (class Q { }), regardless of whether or not X is defined. Si X se define, las únicas directivas procesadas son #if y #endif , debido al comentario de varias líneas.If X is defined, the only processed directives are #if and #endif, due to the multi-line comment. Si X es undefined, tres directivas ( #if , #else , #endif ) forman parte del conjunto de directivas.If X is undefined, then three directives (#if, #else, #endif) are part of the directive set.
Directivas de diagnósticoDiagnostic directives
Las directivas de diagnóstico se utilizan para generar explícitamente mensajes de error y de advertencia que se detectan de la misma manera que otros errores y advertencias en tiempo de compilación.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
;
El ejemplo: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 {...}
siempre genera una advertencia ("se requiere una revisión del código antes de la inserción en el repositorio") y genera un error en tiempo de compilación ("una compilación no puede ser Debug and Retail") si se definen los símbolos condicionales Debug y Retail .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. Tenga en cuenta que un pp_message puede contener texto arbitrario; en concreto, no es necesario que los tokens sean correctos, tal y como se muestra en la palabra comilla simple 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.
Directivas de regiónRegion directives
Las directivas region se usan para marcar explícitamente las regiones del código fuente.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
;
No se adjunta ningún significado semántico a una región; las regiones están pensadas para que las use el programador o las herramientas automatizadas para marcar una sección del código fuente.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. El mensaje especificado en una #region Directiva o del #endregion mismo modo no tiene ningún significado semántico; simplemente sirve para identificar la región.The message specified in a #region or #endregion directive likewise has no semantic meaning; it merely serves to identify the region. La coincidencia #region de las #endregion directivas y puede tener distintos pp_message.Matching #region and #endregion directives may have different pp_message s.
El procesamiento léxico de una región:The lexical processing of a region:
#region
...
#endregion
corresponde exactamente al procesamiento léxico de una directiva de compilación condicional del formulario:corresponds exactly to the lexical processing of a conditional compilation directive of the form:
#if true
...
#endif
Directivas de líneaLine directives
Las directivas de línea se pueden usar para modificar los números de línea y los nombres de archivo de origen que el compilador indica en la salida, como advertencias y errores, y que se usan en los atributos de información de llamador (atributos de información de llamador).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).
Las directivas de línea se utilizan normalmente en herramientas de metaprogramaciones que generan código fuente de C# a partir de otra 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 ">'
;
Cuando no hay #line directivas presentes, el compilador informa de los números de línea verdaderos y los nombres de archivo de origen en su salida.When no #line directives are present, the compiler reports true line numbers and source file names in its output. Al procesar una #line Directiva que incluye un line_indicator que no es default , el compilador trata la línea después de la Directiva con el número de línea especificado (y el nombre de archivo, si se especifica).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).
Una #line default Directiva invierte el efecto de todas las directivas de #line anteriores.A #line default directive reverses the effect of all preceding #line directives. El compilador notifica la información de línea verdadera para las líneas siguientes, exactamente como si no #line se hubieran procesado directivas.The compiler reports true line information for subsequent lines, precisely as if no #line directives had been processed.
Una #line hidden Directiva no tiene ningún efecto en el archivo y los números de línea indicados en los mensajes de error, pero afecta a la depuración de nivel de origen.A #line hidden directive has no effect on the file and line numbers reported in error messages, but does affect source level debugging. Al depurar, todas las líneas entre una #line hidden Directiva y la #line Directiva subsiguiente (que no es #line hidden ) no tienen información de número de línea.When debugging, all lines between a #line hidden directive and the subsequent #line directive (that is not #line hidden) have no line number information. Al recorrer el código en el depurador, estas líneas se omitirán por completo.When stepping through code in the debugger, these lines will be skipped entirely.
Tenga en cuenta que un file_name difiere de un literal de cadena normal en el que no se procesan los caracteres de escape; el \ carácter "" simplemente designa un carácter de barra diagonal inversa normal dentro de un 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.
Directivas pragmaPragma directives
La #pragma Directiva de preprocesamiento se usa para especificar información contextual opcional para el compilador.The #pragma preprocessing directive is used to specify optional contextual information to the compiler. La información proporcionada en una #pragma directiva nunca cambiará la semántica del 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
;
C# proporciona #pragma directivas para controlar las advertencias del compilador.C# provides #pragma directives to control compiler warnings. Las versiones futuras del lenguaje pueden incluir #pragma directivas adicionales.Future versions of the language may include additional #pragma directives. Para garantizar la interoperabilidad con otros compiladores de C#, el compilador de Microsoft C# no emite errores de compilación para las directivas desconocidas #pragma ; sin embargo, estas directivas generan advertencias.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.
ADVERTENCIA de pragmaPragma warning
La #pragma warning Directiva se usa para deshabilitar o restaurar todo o un conjunto determinado de mensajes de advertencia durante la compilación del texto del programa subsiguiente.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+)*
;
Una #pragma warning Directiva que omite la lista de advertencias afecta a todas las advertencias.A #pragma warning directive that omits the warning list affects all warnings. Una #pragma warning Directiva que incluye una lista de advertencias afecta solo a las advertencias especificadas en la lista.A #pragma warning directive that includes a warning list affects only those warnings that are specified in the list.
Una #pragma warning disable Directiva deshabilita todos o el conjunto de advertencias especificado.A #pragma warning disable directive disables all or the given set of warnings.
Una #pragma warning restore Directiva restaura todos o el conjunto de advertencias especificado en el estado que estaba en vigor al principio de la unidad de compilación.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. Tenga en cuenta que si se ha deshabilitado una advertencia determinada externamente, una #pragma warning restore (ya sea para toda o la advertencia específica) no volverá a habilitar esa advertencia.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.
En el ejemplo siguiente se muestra el uso de #pragma warning para deshabilitar temporalmente la advertencia que se indica cuando se hace referencia a los miembros obsoletos, mediante el número de advertencia del compilador de 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
}
}