AtributosAttributes

Gran parte del lenguaje C# permite al programador especificar información declarativa sobre las entidades definidas en el programa.Much of the C# language enables the programmer to specify declarative information about the entities defined in the program. Por ejemplo, la accesibilidad de un método en una clase se especifica al decorarlo con el method_modifier s public , protected , internal y private .For example, the accessibility of a method in a class is specified by decorating it with the method_modifier s public, protected, internal, and private.

C# permite a los programadores inventar nuevos tipos de información declarativa, denominados atributos.C# enables programmers to invent new kinds of declarative information, called attributes. Después, los programadores pueden asociar atributos a varias entidades de programa y recuperar información de atributos en un entorno en tiempo de ejecución.Programmers can then attach attributes to various program entities, and retrieve attribute information in a run-time environment. Por ejemplo, un marco podría definir un HelpAttribute atributo que se puede colocar en determinados elementos del programa (como clases y métodos) para proporcionar una asignación de esos elementos de programa a su documentación.For instance, a framework might define a HelpAttribute attribute that can be placed on certain program elements (such as classes and methods) to provide a mapping from those program elements to their documentation.

Los atributos se definen a través de la declaración de clases de atributos (clases de atributos), que pueden tener parámetros con nombre y de posición (parámetros posicionales y con nombre).Attributes are defined through the declaration of attribute classes (Attribute classes), which may have positional and named parameters (Positional and named parameters). Los atributos se asocian a entidades en un programa de C# mediante especificaciones de atributo (especificación de atributo) y se pueden recuperar en tiempo de ejecución como instancias de atributo (instancias de atributo).Attributes are attached to entities in a C# program using attribute specifications (Attribute specification), and can be retrieved at run-time as attribute instances (Attribute instances).

Clases de atributosAttribute classes

Una clase que deriva de la clase abstracta System.Attribute , ya sea directa o indirectamente, es una clase * Attribute _.A class that derives from the abstract class System.Attribute, whether directly or indirectly, is an *attribute class _. La declaración de una clase de atributo define un nuevo tipo de _ Attribute* que se puede colocar en una declaración.The declaration of an attribute class defines a new kind of _ attribute* that can be placed on a declaration. Por Convención, las clases de atributo se denominan con el sufijo Attribute .By convention, attribute classes are named with a suffix of Attribute. Los usos de un atributo pueden incluir u omitir este sufijo.Uses of an attribute may either include or omit this suffix.

Uso de atributosAttribute usage

El atributo AttributeUsage (el atributo AttributeUsage) se usa para describir cómo se puede utilizar una clase de atributo.The attribute AttributeUsage (The AttributeUsage attribute) is used to describe how an attribute class can be used.

AttributeUsage tiene un parámetro posicional (parámetros posicionales y con nombre) que permite que una clase de atributo especifique los tipos de declaraciones en las que se puede usar.AttributeUsage has a positional parameter (Positional and named parameters) that enables an attribute class to specify the kinds of declarations on which it can be used. En el ejemploThe example

using System;

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)]
public class SimpleAttribute: Attribute 
{
    ...
}

define una clase de atributo denominada SimpleAttribute que se puede colocar solo en class_declaration s y interface_declaration s.defines an attribute class named SimpleAttribute that can be placed on class_declaration s and interface_declaration s only. En el ejemploThe example

[Simple] class Class1 {...}

[Simple] interface Interface1 {...}

muestra varios usos del Simple atributo.shows several uses of the Simple attribute. Aunque este atributo se define con el nombre SimpleAttribute , cuando se utiliza este atributo, Attribute se puede omitir el sufijo, lo que da lugar a un nombre corto Simple .Although this attribute is defined with the name SimpleAttribute, when this attribute is used, the Attribute suffix may be omitted, resulting in the short name Simple. Por lo tanto, el ejemplo anterior es semánticamente equivalente a lo siguiente:Thus, the example above is semantically equivalent to the following:

[SimpleAttribute] class Class1 {...}

[SimpleAttribute] interface Interface1 {...}

AttributeUsage tiene un parámetro con nombre (parámetros posicionales y con nombre) denominado AllowMultiple , que indica si el atributo se puede especificar más de una vez para una entidad determinada.AttributeUsage has a named parameter (Positional and named parameters) called AllowMultiple, which indicates whether the attribute can be specified more than once for a given entity. Si AllowMultiple para una clase de atributo es true, esa clase de atributo es una clase de atributo * de uso múltiple _ y se puede especificar más de una vez en una entidad.If AllowMultiple for an attribute class is true, then that attribute class is a *multi-use attribute class _, and can be specified more than once on an entity. Si AllowMultiple para una clase de atributo es false o no se especifica, esa clase de atributo es una clase de atributo de un solo uso* * y se puede especificar como máximo una vez en una entidad.If AllowMultiple for an attribute class is false or it is unspecified, then that attribute class is a _*single-use attribute class**, and can be specified at most once on an entity.

En el ejemploThe example

using System;

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class AuthorAttribute: Attribute
{
    private string name;

    public AuthorAttribute(string name) {
        this.name = name;
    }

    public string Name {
        get { return name; }
    }
}

define una clase de atributo de varios usos denominada AuthorAttribute .defines a multi-use attribute class named AuthorAttribute. En el ejemploThe example

[Author("Brian Kernighan"), Author("Dennis Ritchie")] 
class Class1
{
    ...
}

muestra una declaración de clase con dos usos del Author atributo.shows a class declaration with two uses of the Author attribute.

AttributeUsage tiene otro parámetro con nombre llamado Inherited , que indica si el atributo, cuando se especifica en una clase base, también es heredado por las clases que derivan de esa clase base.AttributeUsage has another named parameter called Inherited, which indicates whether the attribute, when specified on a base class, is also inherited by classes that derive from that base class. Si Inherited para una clase de atributo es true, se hereda ese atributo.If Inherited for an attribute class is true, then that attribute is inherited. Si Inherited para una clase de atributo es false, ese atributo no se hereda.If Inherited for an attribute class is false then that attribute is not inherited. Si no se especifica, su valor predeterminado es true.If it is unspecified, its default value is true.

Una clase de atributo que X no tiene un AttributeUsage atributo asociado, como enAn attribute class X not having an AttributeUsage attribute attached to it, as in

using System;

class X: Attribute {...}

es equivalente a lo siguiente:is equivalent to the following:

using System;

[AttributeUsage(
    AttributeTargets.All,
    AllowMultiple = false,
    Inherited = true)
]
class X: Attribute {...}

Parámetros posicionales y con nombrePositional and named parameters

Las clases de atributos pueden tener *parámetros posicionales _ y _ parámetros con nombre *.Attribute classes can have positional parameters _ and _named parameters**. Cada constructor de instancia público para una clase de atributo define una secuencia válida de parámetros posicionales para esa clase de atributo.Each public instance constructor for an attribute class defines a valid sequence of positional parameters for that attribute class. Cada propiedad y campo de lectura y escritura público no estático para una clase de atributo define un parámetro con nombre para la clase de atributo.Each non-static public read-write field and property for an attribute class defines a named parameter for the attribute class.

En el ejemploThe example

using System;

[AttributeUsage(AttributeTargets.Class)]
public class HelpAttribute: Attribute
{
    public HelpAttribute(string url) {        // Positional parameter
        ...
    }

    public string Topic {                     // Named parameter
        get {...}
        set {...}
    }

    public string Url {
        get {...}
    }
}

define una clase de atributo denominada HelpAttribute que tiene un parámetro posicional, url , y un parámetro con nombre, Topic .defines an attribute class named HelpAttribute that has one positional parameter, url, and one named parameter, Topic. Aunque no es estático y público, la propiedad no Url define un parámetro con nombre, ya que no es de lectura y escritura.Although it is non-static and public, the property Url does not define a named parameter, since it is not read-write.

Esta clase de atributo se puede utilizar como sigue:This attribute class might be used as follows:

[Help("http://www.mycompany.com/.../Class1.htm")]
class Class1
{
    ...
}

[Help("http://www.mycompany.com/.../Misc.htm", Topic = "Class2")]
class Class2
{
    ...
}

Tipos de parámetros de atributoAttribute parameter types

Los tipos de parámetros posicionales y con nombre para una clase de atributo se limitan a los tipos de parámetro de atributo, que son:The types of positional and named parameters for an attribute class are limited to the attribute parameter types, which are:

  • Uno de los tipos siguientes: bool , byte , char , double , float , int , long , sbyte , short , string , uint , ulong , ushort .One of the following types: bool, byte, char, double, float, int, long, sbyte, short, string, uint, ulong, ushort.
  • El tipo object.The type object.
  • El tipo System.Type.The type System.Type.
  • Un tipo de enumeración, siempre que tenga accesibilidad pública y los tipos en los que está anidado (si los hubiera) también tengan accesibilidad pública (especificación de atributo).An enum type, provided it has public accessibility and the types in which it is nested (if any) also have public accessibility (Attribute specification).
  • Matrices unidimensionales de los tipos anteriores.Single-dimensional arrays of the above types.
  • Un argumento de constructor o un campo público que no tiene uno de estos tipos, no se puede usar como un parámetro posicional o con nombre en una especificación de atributo.A constructor argument or public field which does not have one of these types, cannot be used as a positional or named parameter in an attribute specification.

Especificación de atributoAttribute specification

*Especificación de atributo _ es la aplicación de un atributo definido previamente a una declaración.*Attribute specification _ is the application of a previously defined attribute to a declaration. Un atributo es un fragmento de información declarativa adicional que se especifica para una declaración.An attribute is a piece of additional declarative information that is specified for a declaration. Los atributos se pueden especificar en el ámbito global (para especificar atributos en el ensamblado o módulo contenedor) y para _type_declaration * s (declaraciones de tipos). class_member_declaration s (restricciones de parámetros de tipo), interface_member_declaration s (miembros de interfaz), struct_member_declaration s (miembros de struct), enum_member_declaration s (miembros de enumeración), accessor_declarations (descriptores de acceso), event_accessor_declarations (eventos similares a campos) y formal_parameter_list s (parámetros de método).Attributes can be specified at global scope (to specify attributes on the containing assembly or module) and for _type_declaration*s (Type declarations), class_member_declaration s (Type parameter constraints), interface_member_declaration s (Interface members), struct_member_declaration s (Struct members), enum_member_declaration s (Enum members), accessor_declarations (Accessors), event_accessor_declarations (Field-like events), and formal_parameter_list s (Method parameters).

Los atributos se especifican en las secciones de atributos.Attributes are specified in attribute sections. Una sección de atributos consta de un par de corchetes, que rodean una lista separada por comas de uno o más atributos.An attribute section consists of a pair of square brackets, which surround a comma-separated list of one or more attributes. El orden en que se especifican los atributos en esta lista y el orden en el que se organizan las secciones asociadas a la misma entidad de programa no es significativo.The order in which attributes are specified in such a list, and the order in which sections attached to the same program entity are arranged, is not significant. Por ejemplo, las especificaciones de atributo [A][B] ,, [B][A] [A,B] y [B,A] son equivalentes.For instance, the attribute specifications [A][B], [B][A], [A,B], and [B,A] are equivalent.

global_attributes
    : global_attribute_section+
    ;

global_attribute_section
    : '[' global_attribute_target_specifier attribute_list ']'
    | '[' global_attribute_target_specifier attribute_list ',' ']'
    ;

global_attribute_target_specifier
    : global_attribute_target ':'
    ;

global_attribute_target
    : 'assembly'
    | 'module'
    ;

attributes
    : attribute_section+
    ;

attribute_section
    : '[' attribute_target_specifier? attribute_list ']'
    | '[' attribute_target_specifier? attribute_list ',' ']'
    ;

attribute_target_specifier
    : attribute_target ':'
    ;

attribute_target
    : 'field'
    | 'event'
    | 'method'
    | 'param'
    | 'property'
    | 'return'
    | 'type'
    ;

attribute_list
    : attribute (',' attribute)*
    ;

attribute
    : attribute_name attribute_arguments?
    ;

attribute_name
    : type_name
    ;

attribute_arguments
    : '(' positional_argument_list? ')'
    | '(' positional_argument_list ',' named_argument_list ')'
    | '(' named_argument_list ')'
    ;

positional_argument_list
    : positional_argument (',' positional_argument)*
    ;

positional_argument
    : attribute_argument_expression
    ;

named_argument_list
    : named_argument (','  named_argument)*
    ;

named_argument
    : identifier '=' attribute_argument_expression
    ;

attribute_argument_expression
    : expression
    ;

Un atributo consta de un attribute_name y una lista opcional de argumentos posicionales y con nombre.An attribute consists of an attribute_name and an optional list of positional and named arguments. Los argumentos posicionales (si existen) preceden a los argumentos con nombre.The positional arguments (if any) precede the named arguments. Un argumento posicional consta de un attribute_argument_expression; un argumento con nombre se compone de un nombre seguido de un signo igual, seguido de una attribute_argument_expression, que, juntos, están restringidas por las mismas reglas que la asignación simple.A positional argument consists of an attribute_argument_expression; a named argument consists of a name, followed by an equal sign, followed by an attribute_argument_expression, which, together, are constrained by the same rules as simple assignment. El orden de los argumentos con nombre no es significativo.The order of named arguments is not significant.

El attribute_name identifica una clase de atributo.The attribute_name identifies an attribute class. Si el formato de attribute_name es type_name , este nombre debe hacer referencia a una clase de atributo.If the form of attribute_name is type_name then this name must refer to an attribute class. De lo contrario, se produce un error en tiempo de compilación.Otherwise, a compile-time error occurs. En el ejemploThe example

class Class1 {}

[Class1] class Class2 {}    // Error

produce un error en tiempo de compilación porque intenta utilizar Class1 como una clase de atributos cuando Class1 no es una clase de atributos.results in a compile-time error because it attempts to use Class1 as an attribute class when Class1 is not an attribute class.

Algunos contextos permiten la especificación de un atributo en más de un destino.Certain contexts permit the specification of an attribute on more than one target. Un programa puede especificar explícitamente el destino incluyendo un attribute_target_specifier.A program can explicitly specify the target by including an attribute_target_specifier. Cuando se coloca un atributo en el nivel global, se requiere un global_attribute_target_specifier .When an attribute is placed at the global level, a global_attribute_target_specifier is required. En todas las demás ubicaciones, se aplica un valor predeterminado razonable, pero se puede usar un attribute_target_specifier para confirmar o invalidar el valor predeterminado en determinados casos ambiguos (o simplemente se confirma el valor predeterminado en casos no ambiguos).In all other locations, a reasonable default is applied, but an attribute_target_specifier can be used to affirm or override the default in certain ambiguous cases (or to just affirm the default in non-ambiguous cases). Por lo tanto, normalmente attribute_target_specifier s se pueden omitir, excepto en el nivel global.Thus, typically, attribute_target_specifier s can be omitted except at the global level. Los contextos potencialmente ambiguos se resuelven de la siguiente manera:The potentially ambiguous contexts are resolved as follows:

  • Un atributo especificado en el ámbito global puede aplicarse al ensamblado de destino o al módulo de destino.An attribute specified at global scope can apply either to the target assembly or the target module. No existe ningún valor predeterminado para este contexto, por lo que siempre se requiere un attribute_target_specifier en este contexto.No default exists for this context, so an attribute_target_specifier is always required in this context. La presencia de la assembly attribute_target_specifier indica que el atributo se aplica al ensamblado de destino; la presencia del module attribute_target_specifier indica que el atributo se aplica al módulo de destino.The presence of the assembly attribute_target_specifier indicates that the attribute applies to the target assembly; the presence of the module attribute_target_specifier indicates that the attribute applies to the target module.
  • Un atributo especificado en una declaración de delegado se puede aplicar al delegado que se está declarando o a su valor devuelto.An attribute specified on a delegate declaration can apply either to the delegate being declared or to its return value. En ausencia de un attribute_target_specifier, el atributo se aplica al delegado.In the absence of an attribute_target_specifier, the attribute applies to the delegate. La presencia de la type attribute_target_specifier indica que el atributo se aplica al delegado; la presencia del return attribute_target_specifier indica que el atributo se aplica al valor devuelto.The presence of the type attribute_target_specifier indicates that the attribute applies to the delegate; the presence of the return attribute_target_specifier indicates that the attribute applies to the return value.
  • Un atributo especificado en una declaración de método se puede aplicar al método que se declara o a su valor devuelto.An attribute specified on a method declaration can apply either to the method being declared or to its return value. En ausencia de un attribute_target_specifier, el atributo se aplica al método.In the absence of an attribute_target_specifier, the attribute applies to the method. La presencia de la method attribute_target_specifier indica que el atributo se aplica al método; la presencia del return attribute_target_specifier indica que el atributo se aplica al valor devuelto.The presence of the method attribute_target_specifier indicates that the attribute applies to the method; the presence of the return attribute_target_specifier indicates that the attribute applies to the return value.
  • Un atributo especificado en una declaración de operador puede aplicarse al operador que se declara o a su valor devuelto.An attribute specified on an operator declaration can apply either to the operator being declared or to its return value. En ausencia de un attribute_target_specifier, el atributo se aplica al operador.In the absence of an attribute_target_specifier, the attribute applies to the operator. La presencia de la method attribute_target_specifier indica que el atributo se aplica al operador; la presencia del return attribute_target_specifier indica que el atributo se aplica al valor devuelto.The presence of the method attribute_target_specifier indicates that the attribute applies to the operator; the presence of the return attribute_target_specifier indicates that the attribute applies to the return value.
  • Un atributo especificado en una declaración de evento que omite los descriptores de acceso de eventos se puede aplicar al evento que se está declarando, al campo asociado (si el evento no es abstracto) o a los métodos Add y Remove asociados.An attribute specified on an event declaration that omits event accessors can apply to the event being declared, to the associated field (if the event is not abstract), or to the associated add and remove methods. En ausencia de un attribute_target_specifier, el atributo se aplica al evento.In the absence of an attribute_target_specifier, the attribute applies to the event. La presencia de la event attribute_target_specifier indica que el atributo se aplica al evento; la presencia del field attribute_target_specifier indica que el atributo se aplica al campo; y la presencia de la method attribute_target_specifier indica que el atributo se aplica a los métodos.The presence of the event attribute_target_specifier indicates that the attribute applies to the event; the presence of the field attribute_target_specifier indicates that the attribute applies to the field; and the presence of the method attribute_target_specifier indicates that the attribute applies to the methods.
  • Un atributo especificado en una declaración de descriptor de acceso get para una declaración de propiedad o indizador se puede aplicar al método asociado o a su valor devuelto.An attribute specified on a get accessor declaration for a property or indexer declaration can apply either to the associated method or to its return value. En ausencia de un attribute_target_specifier, el atributo se aplica al método.In the absence of an attribute_target_specifier, the attribute applies to the method. La presencia de la method attribute_target_specifier indica que el atributo se aplica al método; la presencia del return attribute_target_specifier indica que el atributo se aplica al valor devuelto.The presence of the method attribute_target_specifier indicates that the attribute applies to the method; the presence of the return attribute_target_specifier indicates that the attribute applies to the return value.
  • Un atributo especificado en un descriptor de acceso set para una declaración de propiedad o indizador se puede aplicar al método asociado o a su propio parámetro implícito.An attribute specified on a set accessor for a property or indexer declaration can apply either to the associated method or to its lone implicit parameter. En ausencia de un attribute_target_specifier, el atributo se aplica al método.In the absence of an attribute_target_specifier, the attribute applies to the method. La presencia de la method attribute_target_specifier indica que el atributo se aplica al método; la presencia del param attribute_target_specifier indica que el atributo se aplica al parámetro; la presencia del return attribute_target_specifier indica que el atributo se aplica al valor devuelto.The presence of the method attribute_target_specifier indicates that the attribute applies to the method; the presence of the param attribute_target_specifier indicates that the attribute applies to the parameter; the presence of the return attribute_target_specifier indicates that the attribute applies to the return value.
  • Un atributo especificado en una declaración de descriptor de acceso Add o Remove para una declaración de evento se puede aplicar al método asociado o a su propio parámetro.An attribute specified on an add or remove accessor declaration for an event declaration can apply either to the associated method or to its lone parameter. En ausencia de un attribute_target_specifier, el atributo se aplica al método.In the absence of an attribute_target_specifier, the attribute applies to the method. La presencia de la method attribute_target_specifier indica que el atributo se aplica al método; la presencia del param attribute_target_specifier indica que el atributo se aplica al parámetro; la presencia del return attribute_target_specifier indica que el atributo se aplica al valor devuelto.The presence of the method attribute_target_specifier indicates that the attribute applies to the method; the presence of the param attribute_target_specifier indicates that the attribute applies to the parameter; the presence of the return attribute_target_specifier indicates that the attribute applies to the return value.

En otros contextos, se permite la inclusión de un attribute_target_specifier , pero no es necesario.In other contexts, inclusion of an attribute_target_specifier is permitted but unnecessary. Por ejemplo, una declaración de clase puede incluir u omitir el especificador type :For instance, a class declaration may either include or omit the specifier type:

[type: Author("Brian Kernighan")]
class Class1 {}

[Author("Dennis Ritchie")]
class Class2 {}

Es un error especificar una attribute_target_specifier no válida.It is an error to specify an invalid attribute_target_specifier. Por ejemplo, el especificador param no se puede usar en una declaración de clase:For instance, the specifier param cannot be used on a class declaration:

[param: Author("Brian Kernighan")]        // Error
class Class1 {}

Por Convención, las clases de atributo se denominan con el sufijo Attribute .By convention, attribute classes are named with a suffix of Attribute. Un attribute_name del formulario type_name puede incluir u omitir este sufijo.An attribute_name of the form type_name may either include or omit this suffix. Si se encuentra una clase de atributo con y sin este sufijo, existe una ambigüedad y se produce un error en tiempo de compilación.If an attribute class is found both with and without this suffix, an ambiguity is present, and a compile-time error results. Si el attribute_name está escrito de modo que su identificador situado más a la derecha sea un identificador textual (identificadores), solo se hace coincidir un atributo sin sufijo, lo que permite resolver este tipo de ambigüedad.If the attribute_name is spelled such that its right-most identifier is a verbatim identifier (Identifiers), then only an attribute without a suffix is matched, thus enabling such an ambiguity to be resolved. En el ejemploThe example

using System;

[AttributeUsage(AttributeTargets.All)]
public class X: Attribute
{}

[AttributeUsage(AttributeTargets.All)]
public class XAttribute: Attribute
{}

[X]                     // Error: ambiguity
class Class1 {}

[XAttribute]            // Refers to XAttribute
class Class2 {}

[@X]                    // Refers to X
class Class3 {}

[@XAttribute]           // Refers to XAttribute
class Class4 {}

muestra dos clases de atributos denominadas X y XAttribute .shows two attribute classes named X and XAttribute. El atributo [X] es ambiguo, ya que podría hacer referencia a X o XAttribute .The attribute [X] is ambiguous, since it could refer to either X or XAttribute. El uso de un identificador textual permite especificar la intención exacta en estos casos raros.Using a verbatim identifier allows the exact intent to be specified in such rare cases. El atributo [XAttribute] no es ambiguo (aunque sería si hubiera una clase de atributo denominada XAttributeAttribute !).The attribute [XAttribute] is not ambiguous (although it would be if there was an attribute class named XAttributeAttribute!). Si se quita la declaración de la clase X , ambos atributos hacen referencia a la clase de atributo denominada XAttribute , como se indica a continuación:If the declaration for class X is removed, then both attributes refer to the attribute class named XAttribute, as follows:

using System;

[AttributeUsage(AttributeTargets.All)]
public class XAttribute: Attribute
{}

[X]                     // Refers to XAttribute
class Class1 {}

[XAttribute]            // Refers to XAttribute
class Class2 {}

[@X]                    // Error: no attribute named "X"
class Class3 {}

Es un error en tiempo de compilación utilizar una clase de atributo de un solo uso más de una vez en la misma entidad.It is a compile-time error to use a single-use attribute class more than once on the same entity. En el ejemploThe example

using System;

[AttributeUsage(AttributeTargets.Class)]
public class HelpStringAttribute: Attribute
{
    string value;

    public HelpStringAttribute(string value) {
        this.value = value;
    }

    public string Value {
        get {...}
    }
}

[HelpString("Description of Class1")]
[HelpString("Another description of Class1")]
public class Class1 {}

produce un error en tiempo de compilación porque intenta utilizar HelpString , que es una clase de atributo de un solo uso, más de una vez en la declaración de Class1 .results in a compile-time error because it attempts to use HelpString, which is a single-use attribute class, more than once on the declaration of Class1.

Una expresión E es una attribute_argument_expression si se cumplen todas las instrucciones siguientes:An expression E is an attribute_argument_expression if all of the following statements are true:

  • El tipo de E es un tipo de parámetro de atributo (tipos de parámetro de atributo).The type of E is an attribute parameter type (Attribute parameter types).
  • En tiempo de compilación, el valor de E se puede resolver como uno de los siguientes:At compile-time, the value of E can be resolved to one of the following:
    • Valor constanteA constant value.
    • Un objeto System.Type.A System.Type object.
    • Matriz unidimensional de attribute_argument_expression s.A one-dimensional array of attribute_argument_expression s.

Por ejemplo:For example:

using System;

[AttributeUsage(AttributeTargets.Class)]
public class TestAttribute: Attribute
{
    public int P1 {
        get {...}
        set {...}
    }

    public Type P2 {
        get {...}
        set {...}
    }

    public object P3 {
        get {...}
        set {...}
    }
}

[Test(P1 = 1234, P3 = new int[] {1, 3, 5}, P2 = typeof(float))]
class MyClass {}

Una typeof_expression (el operador typeof) utilizada como expresión de argumento de atributo puede hacer referencia a un tipo no genérico, un tipo construido cerrado o un tipo genérico sin enlazar, pero no puede hacer referencia a un tipo abierto.A typeof_expression (The typeof operator) used as an attribute argument expression can reference a non-generic type, a closed constructed type, or an unbound generic type, but it cannot reference an open type. Esto es para asegurarse de que la expresión se puede resolver en tiempo de compilación.This is to ensure that the expression can be resolved at compile-time.

class A: Attribute
{
    public A(Type t) {...}
}

class G<T>
{
    [A(typeof(T))] T t;                  // Error, open type in attribute
}

class X
{
    [A(typeof(List<int>))] int x;        // Ok, closed constructed type
    [A(typeof(List<>))] int y;           // Ok, unbound generic type
}

Instancias de atributosAttribute instances

Una instancia de atributo es una instancia de que representa un atributo en tiempo de ejecución.An attribute instance is an instance that represents an attribute at run-time. Un atributo se define con una clase de atributo, argumentos posicionales y argumentos con nombre.An attribute is defined with an attribute class, positional arguments, and named arguments. Una instancia de atributo es una instancia de la clase de atributos que se inicializa con los argumentos posicionales y con nombre.An attribute instance is an instance of the attribute class that is initialized with the positional and named arguments.

La recuperación de una instancia de atributo implica el procesamiento en tiempo de compilación y en tiempo de ejecución, como se describe en las secciones siguientes.Retrieval of an attribute instance involves both compile-time and run-time processing, as described in the following sections.

Compilación de un atributoCompilation of an attribute

La compilación de un atributo con la clase de atributo T , positional_argument_list P y named_argument_list N , consta de los siguientes pasos:The compilation of an attribute with attribute class T, positional_argument_list P and named_argument_list N, consists of the following steps:

  • Siga los pasos de procesamiento en tiempo de compilación para compilar un object_creation_expression del formulario new T(P) .Follow the compile-time processing steps for compiling an object_creation_expression of the form new T(P). Estos pasos dan como resultado un error en tiempo de compilación o determinan un constructor C de instancia en T que se puede invocar en tiempo de ejecución.These steps either result in a compile-time error, or determine an instance constructor C on T that can be invoked at run-time.
  • Si no C tiene accesibilidad pública, se produce un error en tiempo de compilación.If C does not have public accessibility, then a compile-time error occurs.
  • Para cada named_argument Arg en N :For each named_argument Arg in N:
    • Supongamos que Name es el identificador de la named_argument Arg .Let Name be the identifier of the named_argument Arg.
    • Name debe identificar una propiedad o un campo público de lectura/escritura no estático en T .Name must identify a non-static read-write public field or property on T. Si T no tiene este campo o propiedad, se produce un error en tiempo de compilación.If T has no such field or property, then a compile-time error occurs.
  • Mantenga la siguiente información para la creación de instancias en tiempo de ejecución del atributo: la clase de atributo T , el constructor C de instancia en T , el positional_argument_list P y el named_argument_list N .Keep the following information for run-time instantiation of the attribute: the attribute class T, the instance constructor C on T, the positional_argument_list P and the named_argument_list N.

Recuperación en tiempo de ejecución de una instancia de atributoRun-time retrieval of an attribute instance

La compilación de un atributo produce una clase de atributo T , un constructor C de instancia en T , un positional_argument_list P y un named_argument_list N .Compilation of an attribute yields an attribute class T, an instance constructor C on T, a positional_argument_list P, and a named_argument_list N. Dada esta información, una instancia de atributo se puede recuperar en tiempo de ejecución mediante los pasos siguientes:Given this information, an attribute instance can be retrieved at run-time using the following steps:

  • Siga los pasos de procesamiento en tiempo de ejecución para ejecutar una object_creation_expression del formulario new T(P) , mediante el constructor de instancia, C tal y como se determina en tiempo de compilación.Follow the run-time processing steps for executing an object_creation_expression of the form new T(P), using the instance constructor C as determined at compile-time. Estos pasos dan como resultado una excepción o producen una instancia O de T .These steps either result in an exception, or produce an instance O of T.
  • Para cada named_argument Arg en N , en orden:For each named_argument Arg in N, in order:
    • Supongamos que Name es el identificador de la named_argument Arg .Let Name be the identifier of the named_argument Arg. Si Name no identifica una propiedad o un campo de lectura/escritura público no estático en O , se produce una excepción.If Name does not identify a non-static public read-write field or property on O, then an exception is thrown.
    • Supongamos Value el resultado de evaluar el attribute_argument_expression de Arg .Let Value be the result of evaluating the attribute_argument_expression of Arg.
    • Si Name identifica un campo en O , establezca este campo en Value .If Name identifies a field on O, then set this field to Value.
    • De lo contrario, Name identifica una propiedad en O .Otherwise, Name identifies a property on O. Establezca esta propiedad en Value.Set this property to Value.
    • El resultado es O , una instancia de la clase de atributos que se ha T inicializado con el positional_argument_list P y el named_argument_list N .The result is O, an instance of the attribute class T that has been initialized with the positional_argument_list P and the named_argument_list N.

Atributos reservadosReserved attributes

Un pequeño número de atributos afecta al lenguaje de alguna manera.A small number of attributes affect the language in some way. Estos atributos incluyen lo siguiente:These attributes include:

  • System.AttributeUsageAttribute (El atributo AttributeUsage), que se usa para describir las maneras en las que se puede usar una clase de atributo.System.AttributeUsageAttribute (The AttributeUsage attribute), which is used to describe the ways in which an attribute class can be used.
  • System.Diagnostics.ConditionalAttribute (El atributo Conditional), que se usa para definir métodos condicionales.System.Diagnostics.ConditionalAttribute (The Conditional attribute), which is used to define conditional methods.
  • System.ObsoleteAttribute (El atributo obsoleto), que se usa para marcar un miembro como obsoleto.System.ObsoleteAttribute (The Obsolete attribute), which is used to mark a member as obsolete.
  • System.Runtime.CompilerServices.CallerLineNumberAttribute, System.Runtime.CompilerServices.CallerFilePathAttribute y System.Runtime.CompilerServices.CallerMemberNameAttribute (atributos de información del llamador), que se usan para proporcionar información sobre el contexto de llamada a los parámetros opcionales.System.Runtime.CompilerServices.CallerLineNumberAttribute, System.Runtime.CompilerServices.CallerFilePathAttribute and System.Runtime.CompilerServices.CallerMemberNameAttribute (Caller info attributes), which are used to supply information about the calling context to optional parameters.

El atributo AttributeUsageThe AttributeUsage attribute

El atributo AttributeUsage se utiliza para describir la forma en que se puede usar la clase de atributo.The attribute AttributeUsage is used to describe the manner in which the attribute class can be used.

Una clase que se decora con el AttributeUsage atributo debe derivarse de System.Attribute , ya sea directa o indirectamente.A class that is decorated with the AttributeUsage attribute must derive from System.Attribute, either directly or indirectly. De lo contrario, se produce un error en tiempo de compilación.Otherwise, a compile-time error occurs.

namespace System
{
    [AttributeUsage(AttributeTargets.Class)]
    public class AttributeUsageAttribute: Attribute
    {
        public AttributeUsageAttribute(AttributeTargets validOn) {...}
        public virtual bool AllowMultiple { get {...} set {...} }
        public virtual bool Inherited { get {...} set {...} }
        public virtual AttributeTargets ValidOn { get {...} }
    }

    public enum AttributeTargets
    {
        Assembly     = 0x0001,
        Module       = 0x0002,
        Class        = 0x0004,
        Struct       = 0x0008,
        Enum         = 0x0010,
        Constructor  = 0x0020,
        Method       = 0x0040,
        Property     = 0x0080,
        Field        = 0x0100,
        Event        = 0x0200,
        Interface    = 0x0400,
        Parameter    = 0x0800,
        Delegate     = 0x1000,
        ReturnValue  = 0x2000,

        All = Assembly | Module | Class | Struct | Enum | Constructor | 
            Method | Property | Field | Event | Interface | Parameter | 
            Delegate | ReturnValue
    }
}

El atributo ConditionalThe Conditional attribute

El atributo Conditional habilita la definición de *métodos condicionales _ y _ clases de atributos condicionales *.The attribute Conditional enables the definition of conditional methods _ and _conditional attribute classes**.

namespace System.Diagnostics
{
    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true)]
    public class ConditionalAttribute: Attribute
    {
        public ConditionalAttribute(string conditionString) {...}
        public string ConditionString { get {...} }
    }
}

Métodos condicionalesConditional methods

Un método decorado con el Conditional atributo es un método condicional.A method decorated with the Conditional attribute is a conditional method. El Conditional atributo indica una condición mediante la prueba de un símbolo de compilación condicional.The Conditional attribute indicates a condition by testing a conditional compilation symbol. Las llamadas a un método condicional se incluyen o se omiten en función de si este símbolo se define en el punto de la llamada.Calls to a conditional method are either included or omitted depending on whether this symbol is defined at the point of the call. Si se define el símbolo, se incluye la llamada; de lo contrario, se omite la llamada (incluida la evaluación del receptor y los parámetros de la llamada).If the symbol is defined, the call is included; otherwise, the call (including evaluation of the receiver and parameters of the call) is omitted.

Un método condicional está sujeto a las siguientes restricciones:A conditional method is subject to the following restrictions:

  • El método condicional debe ser un método en un class_declaration o struct_declaration.The conditional method must be a method in a class_declaration or struct_declaration. Se produce un error en tiempo de compilación si el Conditional atributo se especifica en un método en una declaración de interfaz.A compile-time error occurs if the Conditional attribute is specified on a method in an interface declaration.
  • El método condicional debe tener un tipo de valor devuelto de void .The conditional method must have a return type of void.
  • El método condicional no debe estar marcado con el override modificador.The conditional method must not be marked with the override modifier. Sin embargo, un método condicional se puede marcar con el virtual modificador.A conditional method may be marked with the virtual modifier, however. Las invalidaciones de este tipo de método son implícitamente condicionales y no deben marcarse explícitamente con un Conditional atributo.Overrides of such a method are implicitly conditional, and must not be explicitly marked with a Conditional attribute.
  • El método condicional no debe ser una implementación de un método de interfaz.The conditional method must not be an implementation of an interface method. De lo contrario, se produce un error en tiempo de compilación.Otherwise, a compile-time error occurs.

Además, se produce un error en tiempo de compilación si se utiliza un método condicional en una delegate_creation_expression.In addition, a compile-time error occurs if a conditional method is used in a delegate_creation_expression. En el ejemploThe example

#define DEBUG

using System;
using System.Diagnostics;

class Class1 
{
    [Conditional("DEBUG")]
    public static void M() {
        Console.WriteLine("Executed Class1.M");
    }
}

class Class2
{
    public static void Test() {
        Class1.M();
    }
}

declara Class1.M como un método condicional.declares Class1.M as a conditional method. Class2``Testel método de llama a este método.Class2's Test method calls this method. Dado que se define el símbolo de compilación condicional DEBUG , si Class2.Test se llama a, se llamará a M .Since the conditional compilation symbol DEBUG is defined, if Class2.Test is called, it will call M. Si DEBUG no se ha definido el símbolo, Class2.Test no llamará a Class1.M .If the symbol DEBUG had not been defined, then Class2.Test would not call Class1.M.

Es importante tener en cuenta que la inclusión o exclusión de una llamada a un método condicional se controla mediante los símbolos de compilación condicional en el punto de la llamada.It is important to note that the inclusion or exclusion of a call to a conditional method is controlled by the conditional compilation symbols at the point of the call. En el ejemploIn the example

Archivo class1.cs :File class1.cs:

using System.Diagnostics;

class Class1 
{
    [Conditional("DEBUG")]
    public static void F() {
        Console.WriteLine("Executed Class1.F");
    }
}

Archivo class2.cs :File class2.cs:

#define DEBUG

class Class2
{
    public static void G() {
        Class1.F();                // F is called
    }
}

Archivo class3.cs :File class3.cs:

#undef DEBUG

class Class3
{
    public static void H() {
        Class1.F();                // F is not called
    }
}

las clases Class2 y Class3 cada una contienen llamadas al método condicional Class1.F , que es condicional en función de si se ha definido o no DEBUG .the classes Class2 and Class3 each contain calls to the conditional method Class1.F, which is conditional based on whether or not DEBUG is defined. Puesto que este símbolo se define en el contexto de Class2 pero no Class3 , se incluye la llamada a F en Class2 , mientras que la llamada a F en Class3 se omite.Since this symbol is defined in the context of Class2 but not Class3, the call to F in Class2 is included, while the call to F in Class3 is omitted.

El uso de métodos condicionales en una cadena de herencia puede ser confuso.The use of conditional methods in an inheritance chain can be confusing. Las llamadas realizadas a un método condicional a través base de, del formulario base.M , están sujetas a las reglas de llamada de método condicional normales.Calls made to a conditional method through base, of the form base.M, are subject to the normal conditional method call rules. En el ejemploIn the example

Archivo class1.cs :File class1.cs:

using System;
using System.Diagnostics;

class Class1 
{
    [Conditional("DEBUG")]
    public virtual void M() {
        Console.WriteLine("Class1.M executed");
    }
}

Archivo class2.cs :File class2.cs:

using System;

class Class2: Class1
{
    public override void M() {
        Console.WriteLine("Class2.M executed");
        base.M();                        // base.M is not called!
    }
}

Archivo class3.cs :File class3.cs:

#define DEBUG

using System;

class Class3
{
    public static void Test() {
        Class2 c = new Class2();
        c.M();                            // M is called
    }
}

Class2 incluye una llamada al M definido en su clase base.Class2 includes a call to the M defined in its base class. Esta llamada se omite porque el método base es condicional en función de la presencia del símbolo DEBUG , que no está definida.This call is omitted because the base method is conditional based on the presence of the symbol DEBUG, which is undefined. Por lo tanto, el método solo escribe en la consola " Class2.M executed ".Thus, the method writes to the console "Class2.M executed" only. El uso prudente de pp_declaration s puede eliminar tales problemas.Judicious use of pp_declaration s can eliminate such problems.

Clases de atributos condicionalesConditional attribute classes

Una clase de atributo (clases de atributos) decorada con uno o varios Conditional atributos es una clase de atributo condicional.An attribute class (Attribute classes) decorated with one or more Conditional attributes is a conditional attribute class. Por tanto, una clase de atributo condicional está asociada a los símbolos de compilación condicional declarados en sus Conditional atributos.A conditional attribute class is thus associated with the conditional compilation symbols declared in its Conditional attributes. En este ejemplo:This example:

using System;
using System.Diagnostics;
[Conditional("ALPHA")]
[Conditional("BETA")]
public class TestAttribute : Attribute {}

declara TestAttribute como una clase de atributo condicional asociada a los símbolos de compilaciones condicionales ALPHA y BETA .declares TestAttribute as a conditional attribute class associated with the conditional compilations symbols ALPHA and BETA.

Las especificaciones de atributo (especificación de atributo) de un atributo condicional se incluyen si uno o varios de sus símbolos de compilación condicional asociados se definen en el punto de especificación; de lo contrario, se omite la especificación de atributo.Attribute specifications (Attribute specification) of a conditional attribute are included if one or more of its associated conditional compilation symbols is defined at the point of specification, otherwise the attribute specification is omitted.

Es importante tener en cuenta que la inclusión o exclusión de una especificación de atributo de una clase de atributo condicional se controla mediante los símbolos de compilación condicional en el punto de la especificación.It is important to note that the inclusion or exclusion of an attribute specification of a conditional attribute class is controlled by the conditional compilation symbols at the point of the specification. En el ejemploIn the example

Archivo test.cs :File test.cs:

using System;
using System.Diagnostics;

[Conditional("DEBUG")]

public class TestAttribute : Attribute {}

Archivo class1.cs :File class1.cs:

#define DEBUG

[Test]                // TestAttribute is specified

class Class1 {}

Archivo class2.cs :File class2.cs:

#undef DEBUG

[Test]                 // TestAttribute is not specified

class Class2 {}

cada una de las clases Class1 y Class2 se decoran con el atributo Test , que es condicional en función de si se ha definido o no DEBUG .the classes Class1 and Class2 are each decorated with attribute Test, which is conditional based on whether or not DEBUG is defined. Puesto que este símbolo se define en el contexto de Class1 pero no Class2 , se incluye la especificación del Test atributo en Class1 , mientras que la especificación del Test atributo en Class2 se omite.Since this symbol is defined in the context of Class1 but not Class2, the specification of the Test attribute on Class1 is included, while the specification of the Test attribute on Class2 is omitted.

El atributo ObsoleteThe Obsolete attribute

El atributo Obsolete se usa para marcar tipos y miembros de tipos que ya no se deben usar.The attribute Obsolete is used to mark types and members of types that should no longer be used.

namespace System
{
    [AttributeUsage(
        AttributeTargets.Class | 
        AttributeTargets.Struct |
        AttributeTargets.Enum | 
        AttributeTargets.Interface | 
        AttributeTargets.Delegate |
        AttributeTargets.Method | 
        AttributeTargets.Constructor |
        AttributeTargets.Property | 
        AttributeTargets.Field |
        AttributeTargets.Event,
        Inherited = false)
    ]
    public class ObsoleteAttribute: Attribute
    {
        public ObsoleteAttribute() {...}
        public ObsoleteAttribute(string message) {...}
        public ObsoleteAttribute(string message, bool error) {...}
        public string Message { get {...} }
        public bool IsError { get {...} }
    }
}

Si un programa utiliza un tipo o un miembro que se decora con el Obsolete atributo, el compilador emite una advertencia o un error.If a program uses a type or member that is decorated with the Obsolete attribute, the compiler issues a warning or an error. En concreto, el compilador emite una advertencia si no se proporciona ningún parámetro de error, o si se proporciona el parámetro de error y tiene el valor false .Specifically, the compiler issues a warning if no error parameter is provided, or if the error parameter is provided and has the value false. El compilador emite un error si se especifica el parámetro de error y tiene el valor true .The compiler issues an error if the error parameter is specified and has the value true.

En el ejemploIn the example

[Obsolete("This class is obsolete; use class B instead")]
class A
{
    public void F() {}
}

class B
{
    public void F() {}
}

class Test
{
    static void Main() {
        A a = new A();         // Warning
        a.F();
    }
}

la clase A se decora con el Obsolete atributo.the class A is decorated with the Obsolete attribute. Cada uso de A en Main genera una advertencia que incluye el mensaje especificado, "esta clase está obsoleta; Use la clase B en su lugar ".Each use of A in Main results in a warning that includes the specified message, "This class is obsolete; use class B instead."

Atributos de información del llamadorCaller info attributes

Para fines como registro e informes, a veces resulta útil que un miembro de función obtenga determinada información en tiempo de compilación sobre el código de llamada.For purposes such as logging and reporting, it is sometimes useful for a function member to obtain certain compile-time information about the calling code. Los atributos de información del llamador proporcionan una manera de pasar tal información de forma transparente.The caller info attributes provide a way to pass such information transparently.

Cuando un parámetro opcional se anota con uno de los atributos de información del llamador, la omisión del argumento correspondiente en una llamada no hace que el valor del parámetro predeterminado se sustituya.When an optional parameter is annotated with one of the caller info attributes, omitting the corresponding argument in a call does not necessarily cause the default parameter value to be substituted. En su lugar, si la información especificada sobre el contexto de la llamada está disponible, esa información se pasará como el valor del argumento.Instead, if the specified information about the calling context is available, that information will be passed as the argument value.

Por ejemplo:For example:

using System.Runtime.CompilerServices

...

public void Log(
    [CallerLineNumber] int line = -1,
    [CallerFilePath]   string path = null,
    [CallerMemberName] string name = null
)
{
    Console.WriteLine((line < 0) ? "No line" : "Line "+ line);
    Console.WriteLine((path == null) ? "No file path" : path);
    Console.WriteLine((name == null) ? "No member name" : name);
}

Una llamada a Log() sin argumentos imprimiría el número de línea y la ruta de acceso del archivo de la llamada, así como el nombre del miembro en el que se produjo la llamada.A call to Log() with no arguments would print the line number and file path of the call, as well as the name of the member within which the call occurred.

Los atributos de información del llamador se pueden producir en parámetros opcionales en cualquier parte, incluidas en las declaraciones de delegado.Caller info attributes can occur on optional parameters anywhere, including in delegate declarations. Sin embargo, los atributos de información del llamador específico tienen restricciones en los tipos de los parámetros que pueden atribuir, de modo que siempre habrá una conversión implícita de un valor sustituido al tipo de parámetro.However, the specific caller info attributes have restrictions on the types of the parameters they can attribute, so that there will always be an implicit conversion from a substituted value to the parameter type.

Es un error tener el mismo atributo de información de llamador en un parámetro de la parte de definición e implementación de una declaración de método parcial.It is an error to have the same caller info attribute on a parameter of both the defining and implementing part of a partial method declaration. Solo se aplican los atributos de información de llamador en el elemento de definición, mientras que los atributos de información de llamador que se producen solo en la parte de implementación se omiten.Only caller info attributes in the defining part are applied, whereas caller info attributes occurring only in the implementing part are ignored.

La información del llamador no afecta a la resolución de sobrecarga.Caller information does not affect overload resolution. Como los parámetros opcionales con atributos se siguen omitiendo del código fuente del llamador, la resolución de sobrecarga omite esos parámetros de la misma manera que omite otros parámetros opcionales omitidos (resolución de sobrecarga).As the attributed optional parameters are still omitted from the source code of the caller, overload resolution ignores those parameters in the same way it ignores other omitted optional parameters (Overload resolution).

La información del llamador solo se sustituye cuando una función se invoca explícitamente en el código fuente.Caller information is only substituted when a function is explicitly invoked in source code. Las invocaciones implícitas como las llamadas a un constructor primario implícito no tienen una ubicación de origen y no sustituyen la información del llamador.Implicit invocations such as implicit parent constructor calls do not have a source location and will not substitute caller information. Además, las llamadas que se enlazan dinámicamente no sustituirán la información del llamador.Also, calls that are dynamically bound will not substitute caller information. Cuando se omite un parámetro con atributos de información de llamador en estos casos, se utiliza en su lugar el valor predeterminado especificado del parámetro.When a caller info attributed parameter is omitted in such cases, the specified default value of the parameter is used instead.

Una excepción son las expresiones de consulta.One exception is query-expressions. Se consideran expansiones sintácticas y, si las llamadas se expanden para omitir los parámetros opcionales con atributos de información de llamador, se sustituirá la información del llamador.These are considered syntactic expansions, and if the calls they expand to omit optional parameters with caller info attributes, caller information will be substituted. La ubicación usada es la ubicación de la cláusula de consulta a partir de la cual se generó la llamada.The location used is the location of the query clause which the call was generated from.

Si se especifica más de un atributo de información de llamador en un parámetro determinado, se prefieren en el orden siguiente: CallerLineNumber , CallerFilePath , CallerMemberName .If more than one caller info attribute is specified on a given parameter, they are preferred in the following order: CallerLineNumber, CallerFilePath, CallerMemberName.

El atributo CallerLineNumberThe CallerLineNumber attribute

System.Runtime.CompilerServices.CallerLineNumberAttributeSe permite en parámetros opcionales cuando hay una conversión implícita estándar (conversiones implícitas estándar) del valor constante int.MaxValue al tipo del parámetro.The System.Runtime.CompilerServices.CallerLineNumberAttribute is allowed on optional parameters when there is a standard implicit conversion (Standard implicit conversions) from the constant value int.MaxValue to the parameter's type. Esto garantiza que cualquier número de línea no negativo hasta ese valor se puede pasar sin errores.This ensures that any non-negative line number up to that value can be passed without error.

Si una invocación de función de una ubicación en el código fuente omite un parámetro opcional con CallerLineNumberAttribute , se usa un literal numérico que representa el número de línea de la ubicación como argumento para la invocación en lugar del valor de parámetro predeterminado.If a function invocation from a location in source code omits an optional parameter with the CallerLineNumberAttribute, then a numeric literal representing that location's line number is used as an argument to the invocation instead of the default parameter value.

Si la invocación abarca varias líneas, la línea elegida depende de la implementación.If the invocation spans multiple lines, the line chosen is implementation-dependent.

Tenga en cuenta que el número de línea puede verse afectado por las #line directivas (directivas de línea).Note that the line number may be affected by #line directives (Line directives).

El atributo CallerFilePathThe CallerFilePath attribute

System.Runtime.CompilerServices.CallerFilePathAttributeSe permite en parámetros opcionales cuando hay una conversión implícita estándar (conversiones implícitas estándar) de string en el tipo del parámetro.The System.Runtime.CompilerServices.CallerFilePathAttribute is allowed on optional parameters when there is a standard implicit conversion (Standard implicit conversions) from string to the parameter's type.

Si una invocación de función de una ubicación en el código fuente omite un parámetro opcional con CallerFilePathAttribute , entonces se usa un literal de cadena que representa la ruta de acceso del archivo de la ubicación como argumento para la invocación en lugar del valor del parámetro predeterminado.If a function invocation from a location in source code omits an optional parameter with the CallerFilePathAttribute, then a string literal representing that location's file path is used as an argument to the invocation instead of the default parameter value.

El formato de la ruta de acceso del archivo depende de la implementación.The format of the file path is implementation-dependent.

Tenga en cuenta que la ruta de acceso al archivo puede verse afectada por las #line directivas (directivas de línea).Note that the file path may be affected by #line directives (Line directives).

El atributo CallerMemberNameThe CallerMemberName attribute

System.Runtime.CompilerServices.CallerMemberNameAttributeSe permite en parámetros opcionales cuando hay una conversión implícita estándar (conversiones implícitas estándar) de string en el tipo del parámetro.The System.Runtime.CompilerServices.CallerMemberNameAttribute is allowed on optional parameters when there is a standard implicit conversion (Standard implicit conversions) from string to the parameter's type.

Si una invocación de función desde una ubicación dentro del cuerpo de un miembro de función o dentro de un atributo aplicado al propio miembro de la función o a su tipo de valor devuelto, parámetros o parámetros de tipo en el código fuente omite un parámetro opcional con CallerMemberNameAttribute , se usa un literal de cadena que representa el nombre de ese miembro como argumento para la invocación en lugar del valor del parámetro predeterminadoIf a function invocation from a location within the body of a function member or within an attribute applied to the function member itself or its return type, parameters or type parameters in source code omits an optional parameter with the CallerMemberNameAttribute, then a string literal representing the name of that member is used as an argument to the invocation instead of the default parameter value.

En el caso de las invocaciones que se producen dentro de métodos genéricos, solo se usa el nombre del método en sí, sin la lista de parámetros de tipo.For invocations that occur within generic methods, only the method name itself is used, without the type parameter list.

En el caso de las invocaciones que se producen dentro de implementaciones explícitas de miembros de interfaz, solo se usa el nombre del método en sí, sin la calificación de interfaz anterior.For invocations that occur within explicit interface member implementations, only the method name itself is used, without the preceding interface qualification.

En el caso de las invocaciones que se producen dentro de los descriptores de acceso de propiedades o eventos, el nombre de miembro utilizado es el de la propiedad o el propio evento.For invocations that occur within property or event accessors, the member name used is that of the property or event itself.

En el caso de las invocaciones que se producen dentro de los descriptores de acceso del indizador, el nombre de miembro utilizado es el proporcionado por un IndexerNameAttribute (el atributo IndexerName) en el miembro del indexador, si está presente, o el nombre predeterminado Item en caso contrario.For invocations that occur within indexer accessors, the member name used is that supplied by an IndexerNameAttribute (The IndexerName attribute) on the indexer member, if present, or the default name Item otherwise.

En el caso de las invocaciones que se producen dentro de las declaraciones de constructores de instancias, constructores estáticos, destructores y operadores, el nombre de miembro utilizado depende de la implementación.For invocations that occur within declarations of instance constructors, static constructors, destructors and operators the member name used is implementation-dependent.

Atributos para la interoperaciónAttributes for Interoperation

Nota: esta sección solo es aplicable a la implementación de Microsoft .NET de C#.Note: This section is applicable only to the Microsoft .NET implementation of C#.

Interoperación con componentes COM y Win32Interoperation with COM and Win32 components

El tiempo de ejecución de .NET proporciona un gran número de atributos que permiten a los programas de C# interoperar con los componentes escritos mediante archivos dll de Win32 y COM.The .NET run-time provides a large number of attributes that enable C# programs to interoperate with components written using COM and Win32 DLLs. Por ejemplo, el DllImport atributo se puede utilizar en un static extern método para indicar que la implementación del método se va a encontrar en un archivo dll de Win32.For example, the DllImport attribute can be used on a static extern method to indicate that the implementation of the method is to be found in a Win32 DLL. Estos atributos se encuentran en el System.Runtime.InteropServices espacio de nombres y la documentación detallada de estos atributos se encuentra en la documentación de .net Runtime.These attributes are found in the System.Runtime.InteropServices namespace, and detailed documentation for these attributes is found in the .NET runtime documentation.

Interoperación con otros lenguajes .NETInteroperation with other .NET languages

El atributo IndexerNameThe IndexerName attribute

Los indizadores se implementan en .NET mediante propiedades indizadas y tienen un nombre en los metadatos de .NET.Indexers are implemented in .NET using indexed properties, and have a name in the .NET metadata. Si no hay ningún IndexerName atributo presente para un indexador, se usa el nombre de Item forma predeterminada.If no IndexerName attribute is present for an indexer, then the name Item is used by default. El IndexerName atributo permite a un desarrollador reemplazar este valor predeterminado y especificar otro nombre.The IndexerName attribute enables a developer to override this default and specify a different name.

namespace System.Runtime.CompilerServices.CSharp
{
    [AttributeUsage(AttributeTargets.Property)]
    public class IndexerNameAttribute: Attribute
    {
        public IndexerNameAttribute(string indexerName) {...}
        public string Value { get {...} } 
    }
}