Подтвердить что ты не робот

Как ограничить параметр типового типа на 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 для этой цели. Спасибо вам всем за ваш вклад.

4b9b3361

Ответ 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>();
}