2016-09-08 44 views
5

Biorąc konstruktorGeneric enum jako parametr metoda

public MyObject(int id){ 
    ID = id; 
} 

A dwa teksty stałe:

public enum MyEnum1{ 
    Something = 1, 
    Anotherthing = 2 
} 

public enum MyEnum2{ 
    Dodo = 1, 
    Moustache= 2 
} 

Czy to możliwe, aby przejść w rodzajowe enum jako parametr konstruktora? Szukam rozwiązania wzdłuż linii:

public MyObject(enum someEnum){ 
    ID = (int)someEnum; 
} 

Więc można zrobić:

var newObject = new MyObject(MyEnum1.Something); 
var anotherObject = new MyObject(MyEnum2.Dodo); 
+5

można otrzymać parametr jako liczba całkowita, i konwertować teksty stałe do liczb całkowitych, gdy je przekazać. –

+0

[Nie można wykonać generycznego konstruktora w języku C#] (http://stackoverflow.com/a/3606951/424129). Najlepsze, co można zrobić, to napisać niegeniczną klasę podstawową z ogólną podklasą, a następnie dokonać typu wyliczeniowego jako parametru typu dla ogólnej podklasy. Niezręczny.'MyBase b = new MySub (EnumA.SomeValue); int n = b.ID; ' –

+0

MyObject (MyEnum1 enum1Selection) {}, ale liczba całkowita jest lepsza –

Odpowiedz

4

Dlaczego chcesz przekazać teksty stałe, podczas gdy można przekazać liczb całkowitych?

var newObject = new MyObject((int)MyEnum1.Something); 
var anotherObject = new MyObject((int)MyEnum2.Dodo); 

i wykorzystywać swój pierwszy konstruktor:

public MyObject(int id){ 
    ID = id; 
} 
+0

Tak, to było to, co robiłem już, byłoby po prostu bardziej czytelne, gdybym mógł podać enum bezpośrednio –

+0

Jeśli chodzi o czytelność, możesz użyć @HimBromBeere [rozwiązanie] (http://stackoverflow.com/a/39392579/5897829) z generycznym konstruktorem, musisz dwukrotnie wpisać nazwę wyliczeniową, ale wygląda to dobrze ... Wszystko zależy od tego, co chcesz –

3

Innym rozwiązaniem byłoby:

public MyObject(Enum someEnum){ 
    ID = Convert.ToInt32(someEnum); 
} 

ten sposób można go używać jak prosiłeś bez konieczności oddanych do int każdorazowym zadzwoń do swoich konstruktorów:

var newObject = new MyObject(MyEnum1.Something); 
var anotherObject = new MyObject(MyEnum2.Dodo); 
3

Wystarczy użyć rodzajowe konstruktora:

class MyObject<T> { 

    public MyObject(T someEnum) where T : struct, IConvertible 
    { 
     if (!typeof(T).IsEnum) 
      throw new ArgumentException("Not an enum"); 
     ID = Convert.ToInt32(someEnum); 
    } 
} 

Teraz można łatwo nazwać tak:

var m = new MyObject<MyEnum>(MyEnum1.Something); 

Ale łatwiej byłoby przekazać enum jako liczba całkowita do konstruktora, jak wspomniano w innych odpowiedzi.

+0

Wiesz, że nie możesz używać Enum jako ograniczenia? Życie byłoby łatwiejsze, gdybyś mógł, ale nie skompiluje się. – Ben

+0

@Ben Masz rację, odpowiednio zaktualizowałem odpowiedź. Niestety tracisz sprawdzanie typu kompilatora przed 'Enum' dzięki temu podejściu, dzięki czemu możliwe jest również przekazywanie instancji' int' do metody. – HimBromBeere

+0

Jestem boleśnie świadomy tego. Mój dzień spędziłem na szukaniu tak mocnego rozwiązania, jak to tylko możliwe. Ale niestety powyższe jest tak dobre, jak tylko dostaniesz! – Ben

-2

Czy używasz wyliczenia właściwości lub parametrów.

public enum Enum1{} 
public Enum1 enum1 { get;set; } 
public MyObject() 
{ 
    ID = (int)enum1; 
} 

Po prostu spróbuj. Mam nadzieję, że jest to przydatne.

+0

Jak dokładnie odpowiada na to pytanie? –

+0

A co uzyskasz dostęp do właściwości członka z konstruktora? –

0

Dobrze, jeśli naprawdę potrzebujesz, aby ta rozmowa rodzajowy dla szerokiej gamy typów, to IMHO należy użyć:

  1. Type.IsEnum aby sprawdzić, czy argument jest naprawdę Enum;
  2. Enum.GetUnderlyingType wiedzieć, na jakim typie argumentu jest oparty (niekoniecznie musi to być Int32);
  3. Teraz rzuć swój obiekt.

    public static Int32 GetAnInt<T>(T arg) where T : struct 
    { 
        if ((typeof(T).IsEnum)) 
        { 
         var underlyingType = typeof(T).GetEnumUnderlyingType(); 
         if (underlyingType == typeof(Int32) 
         || underlyingType == typeof(Int16)) //etc. 
         { 
          try 
          { 
           dynamic value = arg; 
           var result = (Int32)value; // can throw InvalidCast! 
           return result; 
          } 
          catch 
          { 
           throw; 
          } 
         } 
         else 
         { 
          throw new InvalidCastException("Underlying type 
             is certainly not castable to Int32!"); 
         } 
        } 
        else 
        { 
         throw new InvalidCastException("Not an Enum!"); 
        } 
    } 
    

    W ten sposób można osiągnąć piękny składnię: var j = GetAnInt(MyEnum.FirstValue);

+0

I jestem prawie pewien, że możesz dodać wiele różnych sprawdzeń i wypolerować ten kod przez lata =) –

+0

I tak, łatwiej jest przekazać liczbę całkowitą. –