2009-09-12 10 views
20

Jeśli mam enum jak tenDlaczego Nullable <T> nie jest prawidłowym parametrem niestandardowego atrybutu, gdy T jest?

public enum Hungry 
{ 
    Somewhat, 
    Very, 
    CouldEatMySocks 
} 

i atrybut niestandardowy jak ten

public class HungerAttribute : Attribute 
{ 
    public Hungry HungerLevel { get; set; } 
    public Hungry? NullableHungerLevel { get; set; } 
} 

mogę zrobić to

[Hunger(HungerLevel = Hungry.CouldEatMySocks)] 
public class Thing1 

ale nie mogę zrobić tego

[Hunger(NullableHungerLevel = Hungry.CouldEatMySocks)] 
public class Thing2 

Generuje błąd, który mówi: "NullableHungerLevel" nie jest poprawnym argumentem o nazwie atrybutu, ponieważ nie jest prawidłowym typem parametru atrybutu ".

Dlaczego to nie jest dozwolone? Rozumiem, że zasadniczo nie ma go na liście akceptowanych typów. Poprawne typy wydają się być prymitywami, wyliczeniem, ciągiem znaków, typem i jednowymiarowymi tablicami poprzednich typów.

Czy to tylko stara zasada, która nie została zaktualizowana, gdy pojawił się Nullable?

+1

Chociaż pierwotnie natknąłem to w .NET 3.5 VS2008 to nadal nie działa w VS2010 Beta1. –

Odpowiedz

26

Głodny? jest równa pustych <Hungry>, która w ujęciu oznacza, że ​​

[Hunger(NullableHungerLevel = Hungry.CouldEatMySocks)] 

jest równa

[Hunger(NullableHungerLevel = new Nullable<Hungry>(Hungry.CouldEatMySocks))] 

Ponieważ można używać wyłącznie stałe wartości w wymienionych argumentów atrybut będzie trzeba uciekać się do rozwiązania shimmy jest.

+0

Teraz, kiedy to wyjaśnisz to jest oczywiste! Dzięki –

19

Aby obejść ten problem utworzyć inny inicjator w atrybut:

class Program 
{ 
    [Hunger()] 
    static void Main(string[] args) 
    { 
    } 

    public sealed class HungerAttribute : Attribute 
    { 
    private readonly Hungry? _HungerLevel; 
    public Hungry? HungerLevel { get { return _HungerLevel; } } 

    public bool IsNull { get { return !_HungerLevel.HasValue; } }   

    public HungerAttribute() 
    { 
    } 

    //Or: 
    public HungerAttribute(Hungry level) 
    { 
     _HungerLevel = level; 
    } 
    } 

    public enum Hungry { Somewhat, Very, CouldEatMySocks } 
} 

Rozumiem, że nie zamierzamy używać zarówno właściwości.

+0

Pytanie nie brzmiało "jak to zrobić", pytanie brzmiało "dlaczego".To w żaden sposób nie odpowiada na pytanie dlaczego. –

+0

Tak. To działa. Wiem, jak sobie z tym poradzić, ale jestem zdziwiony, dlaczego nie działa jako nazwany parametr. Wydaje mi się niespójne. –

+0

Czy mogę usunąć tę odpowiedź? Ponieważ niestety nie mam odpowiedzi na pytanie, dlaczego część :( – Shimmy

5

Atrybuty mogą mieć jako tylko prymitywy parametrów, wyrażenia typeof i wyrażenie tworzenia tablicy.

Nullable to struktura.

Dlatego nie jest dozwolone.

Podejrzewam, że sam format pliku zespołu nie pozwala na przechowywanie złożonych typów takich jak structs w miejscu, w którym są przechowywane wartości atrybutów.

Nie znam żadnych planów, aby to zmienić. Ale nie potrafię wyjaśnić, dlaczego to ograniczenie istnieje.

1

Zamiast tworzyć wyliczanie zerowujące, można utworzyć wartość domyślną dla tego wyliczenia. Domyślnym Enum pick od 1 wartości, tak ustawić enum jak ten

public enum Hungry 
{ 
    None, 
    Somewhat, 
    Very, 
    CouldEatMySocks 
} 

w kodzie można to zrobić, aby sprawdzić wartość null

if(default(Hungry) == HungerLevel)//no value has been set