#c# #.net #generics #enums
#c# #.net #обобщения #перечисления
Вопрос:
Я преобразую перечисление одного класса в перечисление другого класса с помощью приведенного ниже кода:
var someClassA.MyEnumA = (MyEnumA)Enum.Parse(typeof(MyEnumA), someClassB.MyEnumA.ToString());
Я обнаружил, что довольно часто повторяю этот блок кода, поэтому я написал вспомогательный метод, как показано ниже:
public static T EnumFromString<T>(string value)
{
return (T)Enum.Parse(typeof(T), value);
}
Затем в той же строке выше используется:
var someClassA.MyEnumA = EnumFromString<MyEnumA>(someClassB.MyEnumA.ToString());
Это прекрасно работает. Однако теперь у меня есть код, в котором я могу иметь nullable Enum. Итак, мой текущий код:
if (someClassB.MyEnumX.HasValue)
{
someClassA.MyEnumX = (MyEnumX)Enum.Parse(typeof(MyEnumX),someClassB.MyEnumX.ToString());
}
Я не уверен, как обновить мой текущий вспомогательный метод для обработки обоих сценариев — или было бы проще просто написать другой вспомогательный метод с именем NullableEnumFromString — я не уверен, как это будет работать или даже возможно с дженериками?
Комментарии:
1. Я немного смущен. Каков тип свойства MyEnumA в SomeClassA и MyEnumA в SomeClassB?
2. разве вы не можете проверить
value
и вернуть null ifstring.IsNullOrEmpty(value)
в своем вспомогательном методе?3. Для обработки nullable enums вы хотите использовать тип
<T?>
и ограничениеwhere T : struct
4. Кроме того (и в дополнение к другим комментариям) вам нужно будет концептуально решить, что вы хотите делать с null? как это соотносится? вы просто собираетесь использовать значение по умолчанию или собираетесь указать значение по умолчанию.
5. Почему бы не использовать
someClassA.MyEnumX = someClassB.MyEnumX;
вместо этого? Почему требуется сопоставление через строку?
Ответ №1:
Мне кажется, что основная проблема здесь заключается в том, что к моменту вызова метода преобразования вы уже преобразовали значение enum в a string
, и поэтому у вас нет способа узнать, каким был исходный тип, не говоря уже о том, чтобы обрабатывать nullable enum тип.
Мне это также кажется неудобным только с точки зрения того, что все вызывающие должны вызывать ToString()
себя.
Вы могли бы улучшить оба аспекта, написав два разных метода расширения: один для обычного типа перечисления и один для версии с нулевым значением:
public static TResult Convert<T, TResult>(this T value)
where T : struct, System.Enum
where TResult : struct, System.Enum
{
return (TResult)Enum.Parse(typeof(TResult), value.ToString());
}
public static TResult? Convert<T, TResult>(this T? value)
where T : struct, System.Enum
where TResult : struct, System.Enum
{
return value != null ?
(TResult?)Enum.Parse(typeof(TResult), value.ToString()) : null;
}
Примечания:
- В приведенном выше примере используется функция C # 7.3, которая допускает ограничение на
System.Enum
. Если вы используете более раннюю версию C #, просто опустите это. Он все равно будет работать, но просто не будет иметь такой же степени безопасности типов во время компиляции. - Хотя все четыре ограничения параметра типа указывают
struct
, строго говоря, это необходимо только для второй версии с nullable-enum . В первой версии это ничего не повредило; Я просто вставил это для согласованности. - Этот метод расширения nullable-enum возвращает
null
, если входное значение равноnull
. В вашем вопросе не указано, какое значение вы бы использовали в этом случае. Вы можете использовать любой запасной вариант, который вам нравится, если это не то, что вы хотели сделать.