Как ограничить параметр типового типа на System.Enum
Возможные дубликаты:
Кто-нибудь знает хороший способ обхода нехватки enum generic constraint?
Создать общий метод, ограничивающий T до Enum
Возможно ли ограничить параметр родового типа [я не знаю, соответствует ли это правильному имени] Enum
?
Например, как мне сделать что-то подобное?
//VB.NET
Function GetValues(Of T As System.Enum)(ByVal value As T) As IEnumerable(Of T)
Return [Enum].GetValues(value.GetType)
End Function
//C#
public IEnumerable<T> GetValues<T>(T value) where T : System.Enum
{
return Enum.GetValues(value.GetType());
}
Обновить
В конце концов я использовал Jon Skeet Unconstrained Melody для этой цели. Спасибо вам всем за ваш вклад.
Ответы
Ответ 1
К сожалению, вы не можете - Microsoft закрыла это, поскольку не будет исправлять элемент.
Вы можете рассматривать перечисления как структуры и использовать это как ограничение вместо этого (я думаю, именно так Джон Скит сделал это в Unconstrained Melody?) но это довольно неприглядно.
Ответ 2
Вы не можете. Альтернативное решение использует struct
и проверку времени выполнения.
public IEnumerable<T> GetValues<T>(T value) where T : struct
{
if (!typeof(T).IsEnum) throw new NotSupportedException();
return (IEnumerable<T>)Enum.GetValues(value.GetType());
}
Ответ 3
Мэтт и Дэнни отвечают, у обоих есть половина ответа. Это должно фактически обеспечить вам то, что вам нужно:
public IEnumerable<T> GetValues<T>() where T : struct
{
if (!typeof(T).IsEnum) throw new InvalidOperationException("Generic type argument is not a System.Enum");
return Enum.GetValues(typeof(T)).OfType<T>();
}
Изменения от ответа Дэнни:
- Хотя параметр с общим типом допускает вывод типа, поскольку значение фактически не используется, более правильно явно указать общий тип (например, с помощью методов Linq, которые не принимают параметры).
- Enum.GetValues () возвращает массив объектов, который не будет использоваться неявно для IEnumerable из T. Дополнительный метод Linq для вывода результатов (технически OfType - это операция фильтра, но в этом случае он вернет все) необходимо для соответствия типу возврата.
- Необязательно: хотя NotSupportedException также является хорошим выбором для любого исключения, но есть другие варианты; ArgumentException, InvalidOperationException, InvalidCastException и т.д. Я выбрал InvalidOperationException, потому что это то, чем оно является; неверная попытка получить значения перечисления из типа, отличного от перечисления. Это семантично, и я не буду спорить с кем-либо еще логикой.
Ответ 4
Нет необходимости создавать свой метод таким образом.
Вы можете просто использовать System.Enum
как параметр типа в возвращаемом типе:
using System.Linq;
.
.
.
public IEnumerable<Enum> GetValues(Enum value)
{
return Enum.GetValues(value.GetType()).OfType<Enum>();
}