С# Кастинг с объектами в Enums

Этот вопрос связан с литьем перечислений в общих методах

Учитывая перечисление

public enum Crustaceans
{
    Frog = 1,
    Toad = 4
}

Я могу создать экземпляр моего перечисления достаточно просто

short val = 4;
Crustaceans crusty = (Crustaceans) val;

Однако, если

short val = 4;
object obj = (object) val;
Crustaceans crusty = (Crustaceans)obj;

исключение для выполнения запускается, пытаясь выполнить инициализацию crusty.

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

Не то, чтобы я действительно хотел это сделать, но я решаю проблему, пытаясь получить что-то подобное с дженериками, и эффективно это то, что происходит под обложками. то есть.

public T dosomething<T>(short val) where T : new()
{
    T result = (T)(object) val;
    return result;
}

Итак, что я пытаюсь сделать, это иметь общую функцию, которая работает с перечислениями и не-перечислениями (не так критична, но будет приятной), которая может быть установлена ​​на короткое значение, не вызывая исключения и фактически инициализируя правильную значение перечисления.

Ответы

Ответ 1

Что-то вроде этого возможно поможет вам:

public T dosomething<T>(object o)
{
   T enumVal= (T)Enum.Parse(typeof(T), o.ToString());
   return enumVal;
}

Но это будет работать только с перечислениями, по понятной причине использования Enum.Parse(..)

И используйте это, например:

object o = 4;
dosomething<Crustaceans>(o);

Это вернет Toad в вашем случае.

Ответ 2

По умолчанию цифры перечисления имеют тип = int. В вашем коде вы хотите указать значение, которое имеет короткий тип для типа перечисления. Для этого вам нужно задать короткий тип для значений перечисления. Это будет работать:

public enum Crustaceans : short // <--
{
    Frog = 1,
    Toad = 4
}

short  @short = 1;
object @object = @short;

var @enum = (Crustaceans)@object; // @enum = Crustaceans.Frog   

если вы не хотите изменять значения переменных enum по умолчанию

public enum Crustaceans
{
    Frog = 1,
    Toad = 4
}

object @object = Crustaceans.Frog;

var @enum = (Crustaceans)@object; // @enum = Crustaceans.Frog

или

public enum Crustaceans
{
    Frog = 1,
    Toad = 4
}

int @integer= 1;

var @enum = (Crustaceans)@integer; // @enum = Crustaceans.Frog

Ответ 3

Бывают случаи, когда вы не можете использовать Generics (например, в конвертере WPF, когда вы получаете значение как object). В этом случае вы не можете использовать int, потому что тип перечисления может не быть int. Это общий способ сделать это без Generics. Пример указан внутри конвертера WPF, но код внутри является общим:

using System;
using System.Windows;
using System.Windows.Data;

.
.
.

public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
    var enumType = value.GetType();
    var underlyingType = Enum.GetUnderlyingType(enumType);
    var numericValue = System.Convert.ChangeType(value, underlyingType);
    return numericValue;
}