C# generic enum приведение к определенному перечислению

у меня есть общий метод, который принимает "T" type и это перечислитель. Внутри метода я должен вызвать вспомогательные методы класса и depands имени метода по типу перечислителя.

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);
    }    
}

4 ответов


нет допустимого приведения от произвольного типа к типу перечисления, поэтому это не разрешено. Сначала вам нужно бросить объект:

FirstEnumType t = (FirstEnumType)(object)type;

это "трюки" компилятора путем передачи в object (что всегда допустимо), затем вниз-приводит к типу перечисления. Предполагая, что вы выполнили проверку типа среды выполнения, downcast никогда не завершится неудачей. Однако реализация этого в ветке else, как указано, не гарантируется.

можно было бы спросить, почему метод даже общий в во-первых, но именно так вы можете заставить этот конкретный метод работать.


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

это нечто dynamic очень полезно:

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
}

это позволяет избежать необходимости писать все эти if (typeof(T) == typeof(...)) и все - вы позволяете динамической диспетчерской обрабатывать выбор лучшей перегрузки во время выполнения. The object перегрузка существует, если все остальные терпят неудачу, так что вы можете, например, бросить исключение.


попробуйте определить вспомогательный метод:

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;
}

это преобразует значения двух перечислений, учитывая, что в выходном перечислении есть значение, равное входному значению.

и в вашем коде вы бы назвали это следующим образом:

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);
    }    
}