2015-07-16 11 views
9

Mam ogólną metodę, która akceptuje "T" type i jest to moduł wyliczający. Wewnątrz metody muszę wywołać metody klasy pomocniczej, a nazwa metody zależy od typu modułu wyliczającego.C# generyczne wyliczanie rzutowania do konkretnej wyliczki

public Meth<T> (T type) { 

    if (typeof(T) == typeof(FirstEnumType)) { 
     FirstEnumType t = ??? // I somehow need to convert T type to FirstEnumType 
     this.helperFirstCalcBll(t); 
    } 
    else 
    { 
     SecondEnumType t = ??? // I somehow need to convert T type to SecondEnumType 
     this.helperSecondCalcBll(t); 
    }  
} 
+1

Dlaczego nie można po prostu rzucić go? – cubrr

+1

'public Meth', ani razu. – Melvin

+0

Dlaczego używasz ogólnej metody, kiedy nie chcesz pisać ogólnego kodu? Jeśli znasz już prawidłowy typ wyliczenia w czasie kompilacji, dlaczego wyrzucasz go do wysyłki w czasie wykonywania? Dlaczego po prostu nie nazwać przeciążonej metody konkretnym typem wyliczenia? – Luaan

Odpowiedz

11

Nie ma ważne głosy z dowolnego typu do wyliczenia typu więc to nie jest dozwolone. Trzeba rzucić sprzeciwić pierwszy:

FirstEnumType t = (FirstEnumType)(object)type; 

tej „sztuczki” Kompilator przez upcasting do object (co jest zawsze ważne), a następnie w dół rzuca się do typu enum. Zakładając, że wykonałeś kontrolę typu środowiska wykonawczego, downcast nigdy nie zawiedzie. Jednak wdrożenie tego w innej gałęzi, jak podano, nie gwarantuje działania.

Można by zapytać, dlaczego metoda jest nawet ogólna, ale w ten sposób można wykonać tę konkretną metodę.

+0

Lepiej przejść przez 'int' zamiast' object' IMO. – atlaste

+4

@atlaste To też nie byłaby ważna obsada. –

+0

Och, czekaj, racja. Zawsze zapominam, że generics nie są szablonami :-) – atlaste

5
public void Meth(FirstEnumType type) { 
    this.helperFirstCalcBll(type); 
} 
public void Meth(SecondEnumType type) { 
    this.helperSecondCalcBll(type); 
} 
+0

Podaje "Nie można przekonwertować typu na <... enumname ...>" – renathy

+0

Zaktualizowaną odpowiedź za pomocą lepszego rozwiązania, biorąc pod uwagę prostotę żądania. –

+0

@RobertMcKee To najlepsze rozwiązanie, jeśli masz metodę; jednak dla mnie nie jest jasne, czy nasz OP ma konstruktor, czy metodę (jego obecny kod jest niepoprawny :-)). – atlaste

1

To jest coś dynamic jest bardzo przydatne dla:

public void Meth<T>(T enumValue) where T : struct 
{ 
    InternalMeth((dynamic)enumValue); 
} 

private void InternalMeth(FirstEnumType enumValue) 
{ 
    this.helperFirstCalcBll(enumValue); 
} 

private void InternalMeth(SecondEnumType enumValue) 
{ 
    this.helperSecondCalcBll(enumValue); 
} 

private void InternalMeth(object enumValue) 
{ 
    // Do whatever fallback you need 
} 

ten unika konieczności pisania tych wszystkich if (typeof(T) == typeof(...)) i wszystko - niech dynamiczny uchwyt wysyłki wybranie najlepszych przeciążenia przy starcie. Przeciążenie object występuje, jeśli wszystkie inne ulegają awarii, dzięki czemu można np. rzucić wyjątek.

+0

Może nie chce używać enum; enum jest zastrzeżonym słowem kluczowym – atlaste

+0

@atlaste Dobry punkt. Zwykle zapominam, które słowa kluczowe są zarezerwowane i które są wrażliwe na kontekst :)) – Luaan

0

Spróbuj definiowania metody pomocnika:

private TOutput Convert<TInput, TOutput>(TInput value) 
    where TInput : struct 
    where TOutput : struct 
{ 
    var matchingValues = Enum.GetValues(typeof(TOutput)) 
     .Cast<int>() 
     .Where(v => System.Convert.ToInt32(value) == v); 
    if(!matchingValues.Any()) 
    { 
     var message = String.Format("No matching value found in enum '{0}' for value '{1}'.", typeof(TOutput).Name, value); 
     throw new ArgumentException(message); 
    } 
var obj = (object)matchingValues.Single(); 
    return (TOutput)obj; 
} 

by to przeliczyć wartości z dwóch teksty stałe zważywszy, że istnieje wartość w enum wyjściowego jest równa wartości sygnału wejściowego.

I w kodzie można nazwać go w następujący sposób:

public Meth<T> (T type) 
{ 
    if (typeof(T) == typeof(FirstEnumType)) 
    { 
     FirstEnumType t = Convert(type); 
     this.helperFirstCalcBll(t); 
    } 
    else 
    { 
     SecondEnumType t = Convert(type); 
     this.helperSecondCalcBll(t); 
    }  
}