Почему универсальный тип ограничен 'Enum', который не может быть квалифицирован как 'struct' в C # 7.3? - PullRequest
0 голосов
/ 11 мая 2018

Если у меня есть универсальный интерфейс с ограничением struct, например:

public interface IStruct<T> where T : struct { }

Я могу предоставить перечисление как мой тип T, например, так как enum удовлетворяет struct ограничение:

public class EnumIsAStruct : IStruct<DateTimeKind> { }

C # 7.3 добавлено Enum ограничение .Следующий код, который ранее был недопустим, теперь компилируется:

public class MCVE<T> : IStruct<T> where T : struct, Enum { }

Однако, к моему удивлению, следующее не удается скомпилировать:

public class MCVE<T> : IStruct<T> where T : Enum { }

... с ошибкой

CS0453 Тип 'T' должен быть необнуляемым типом значения, чтобы использовать его в качестве параметра 'T' в универсальном типе или методе 'IStruct'

Почемуэто?Я ожидал бы, что универсальный тип, ограниченный Enum, будет использоваться в качестве аргумента типа, где тип ограничен struct, но это, похоже, не так - мне нужно изменить мое ограничение Enum на struct, Enum.Мои ожидания неверны?

1 Ответ

0 голосов
/ 11 мая 2018

Эта проблема странное (возможно, но ожидаемое) поведение.

Сам класс System.Enum может поставляться как тип T. Будучи классом, System.Enum, конечно, не struct!

public class MCVE<T> where T : Enum { }
public class MCVE2 : MCVE<Enum> { }

Как объяснил автор HaloFour :

Это странное поведение самой CLR. System.Enum это класс, но каждый тип, производный от System.Enum, является struct. Так что ограничение на System.Enum само по себе не подразумевается struct, так как вы могли бы пройти System.Enum в качестве аргумента универсального типа ...

Это странно, но проще было просто снять наложенное ограничение на компиляторе, чем спорить по поводу другого синтаксиса для "enum" ограничения, которые могут иметь различное поведение.

Решение - сделать из вашей стандартной практики ограничение struct, Enum, когда вы хотите ограничить конкретные типы до любым конкретным перечислением . Если дополнительно вы хотите принять класс System.Enum в качестве универсального типа, только тогда вы ограничитесь Enum.

...