2012-01-18 10 views
8

Estos son los patrones más comunes y sólo he visto hasta ahora:¿Qué sintaxis está permitida al aplicar los atributos de C#?

[AttributeFoo] 
[AttributeBar("Hello world!")] 
[AttributeBaz(foo=42,bar="Hello world!")] 
public class Example {} 

La sintaxis de atributo se parece que está llamando a un constructor. Y antes de que C# admitiera los argumentos opcionales y con nombre, los parámetros nombrados para los atributos eran la única diferencia visible.

¿El compilador C# permite algo más? Al igual que params argumentos o inicializadores objeto/colección?

Consulte también: Applying Attributes en MSDN se requieren

+0

Una vez puse un inicializador 'string []' en un atributo. – JohnL

Respuesta

3

AFAIK, los parámetros nombrados solo permiten tipos integrales. Desafortunadamente no tengo una referencia para respaldar esto, solo lo aprendí a través de mi propia experimentación.

Al intentar utilizar inicializadores de objetos, tengo este error del compilador:

Un argumento atributo debe ser una expresión constante, typeof expresión o la creación de la matriz expresión de un tipo de parámetro atributo

Aunque este documentation es un par de años de edad, tiene la información de referencia que estaba buscando:

Atributo p arámetros están restringidas a valores constantes de los siguientes tipos:

  • tipos simples (bool, byte, char, short, int, long, float, y dobles)
  • cadena
  • System.Type
  • enums
  • objeto (El argumento para un parámetro de atributo de tipo objeto debe ser un valor constante de uno de los tipos anteriores.) Unidimensionales matrices de cualquiera de los tipos

anteriores Así funciona esto:

//Test attribute class 
[AttributeUsage(AttributeTargets.All)] 
internal class TestAttribute : Attribute 
{ 
    public int[] Something { get; set; } 
} 

//Using an array initialiser - an array of integers 
[TestAttribute(Something = new int[]{1, 2, 3, 4, 5})] 
public abstract class Something 

Mientras que esto no haría:

//Test person class 
internal class Person 
{ 
    public string Name { get; set; } 

    public Person(string name) 
    { 
     this.Name = name; 
    } 
} 

//Test attribute class 
[AttributeUsage(AttributeTargets.All)] 
internal class TestAttribute : Attribute 
{ 
    public IEnumerable<Person> Something { get; set; } 
} 

//This won't work as Person is not an integral type 
[TestAttribute(Something = new Person[]{new Person("James")})] 

EDIT: sólo para elaborar, los atributos forman parte de los metadatos para las construcciones a las que se aplican (dentro del IL generado), por lo tanto los miembros de la clase de atributo deben determinarse en tiempo de compilación; de ahí la restricción de los parámetros de atributos a valores constantes.

0

parámetros posicionales y debe llegar antes de que los parámetros con nombre; corresponden a los parámetros de uno de los constructores del atributo. Los parámetros con nombre son opcionales y corresponden a las propiedades de lectura/escritura del atributo. En C++, C# y J #, especifique name = value para cada parámetro opcional, donde name es el nombre de la propiedad. En Visual Basic, especifique name: = value.

Desde el enlace que ya ha proporcionado. Parece que esas son las únicas cosas permitidas. Básicamente, está combinando el constructor con la lógica de inicialización de propiedades incorporadas, como mencionó.

3

Además de lo que otros han dicho, me gustaría señalar que los atributos también se pueden separar por comas.

[AttributeFoo, AttributeBar("Hello world!"), AttributeBaz(foo=42,bar="Hello world!")] 
public class Example {} 
+2

Esta es una mala práctica; es menos legible – Jowen

Cuestiones relacionadas