2012-01-18 13 views
8

Są to najbardziej popularne i tylko wzory, które widziałem do tej pory:Jaka składnia jest dozwolona podczas stosowania atrybutów C#?

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

Składnia wygląda jak atrybut jesteś wywołanie konstruktora. A zanim C# obsługiwał argumenty opcjonalne i nazwane, jedynymi widocznymi różnicami były parametry nazwane dla atrybutów.

Czy kompilator C# zezwala na cokolwiek innego? Podobnie jak w przypadku argumentów lub inicjalizatorów obiektów/kolekcji?

Zobacz także: Applying Attributes na MSDN są wymagane

+0

Raz wstawiłem inicjator 'string []' w atrybut. – JohnL

Odpowiedz

3

AFAIK, parametry o nazwach dopuszczają tylko typy całkowe. Niestety nie mam żadnego odniesienia, aby tego poprzeć, nauczyłem się tego tylko dzięki własnym eksperymentom.

Gdy próbuje użyć incjalizatory obiektów, mam ten błąd z kompilatora:

Argument atrybut musi być stałym wyrażeniem, typeof ekspresji lub tworzenia tablicy wyrażenia typu parametru atrybut

Chociaż documentation to kilka lat, że ma informacje referencyjne szukałem: p

Attribute arameters są ograniczone do stałych wartościach następujących typów:

  • typów prostych (Bool, byte, char, short, int, long, float, i podwójne)
  • smyczkowych
  • System.Type
  • wylicza obiekt
  • (Argument parametru atrybutu obiektu typu musi być stałą wartością jednego z powyższych typów.) Jednowymiarowe tablice któregokolwiek z powyższych typów

Tak to działa:

//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 

niniejsza nie będzie:

//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: właśnie opracowanie, atrybuty stanowią część metadanych dla konstruktów, do których są stosowane (w obrębie wygenerowanego IL), zatem członkowie klasy atrybutów muszą być określani w czasie kompilacji; stąd ograniczenie parametrów atrybutów do stałych wartości.

0

parametry pozycyjne i musi przyjść przed wszelkimi nazwanych parametrów; odpowiadają one parametrom jednego z konstruktorów atrybutów. Nazwane parametry są opcjonalne i odpowiadają właściwościom odczytu/zapisu atrybutu. W C++, C# i J # podaj nazwę = wartość dla każdego opcjonalnego parametru, gdzie name jest nazwą właściwości. W języku Visual Basic określ nazwę: = wartość.

Z podanego linku. Wygląda na to, że są to jedyne rzeczy dozwolone. Zasadniczo łączysz konstruktor z logiką inicjalizacji właściwości osadzonych, jak wspomniałeś.

3

Oprócz tego, co powiedzieli inni, chciałbym podkreślić, że atrybuty można również rozdzielać przecinkami.

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

To jest zła praktyka; jest mniej czytelny. – Jowen

Powiązane problemy