2009-12-06 6 views
43
  • Почему я не могу использовать ограничение where T : System.ValueType?
  • Почему Microsoft предотвращает ограничение этого типа ?

Пример:Почему я не могу использовать System.ValueType в качестве ограничения generics?

Почему я не могу сделать следующее?

// Defined in a .Net class 
public void bar<T>(T a) where T : ValueType {...} 

// Defined in my class 
public void foo<T>(T a) where T : ValueType 
{ bar<T>(a); } 

В чем разница в использовании структуры над ValueType?

// Defined in my class 
public void foo<T>(T a) where T : struct 
{ bar<T>(a); } 

ответ

60

Есть два различия между использованием

where T : struct 

и

where T : ValueType 
  • последний позволил бы T быть ValueType сам, что ссылочный тип.
  • последние также позволит T быть обнуляемым Тип Значения

Первое из этих различий почти никогда не то, что вы хотите. Второй может быть иногда быть полезным; Nullable<T> немного странно, поскольку он не удовлетворяет ни where T : struct, ни where T : class ограничениям.

Более полезным было бы ограничение

where T : struct, System.Enum 

которых запрещен C# без уважительной причины, что я могу сказать. См. my blog post и Unconstrained Melody project для получения дополнительной информации об этом.

+6

Должен сказать, я всегда задавался вопросом, что мы не можем ограничивать их, как 'where T: struct, System.Enum'. Было бы так полезно! –

+0

Вы _can_ на самом деле делаете 'где T: Enum' и' where T: ValueType' в F # (используя свой синтаксис 'когда 'T:> Enum'), и действительно, он работает, поскольку Джон ожидает, что он сработает. Для ограничения типа enum он работает с общими перечислениями, такими как 'enum ' и 'System.Enum' и правильно запрещает синонимичные типы значений, такие как 'byte' или' int'. Чтобы ответить на вопрос Джона о том, «почему» так сложно добавить в C#, см. Это обсуждение Roslyn: https://github.com/dotnet/roslyn/issues/262 – Abel

12

ValueType не является базовым классом типов значений, это просто контейнер для значения при его коробке. Поскольку это класс контейнера, а не какая-либо иерархия для фактических типов, которые вы хотите использовать, это не полезно в качестве общего ограничения.

+0

Не совсем и не полностью. В IL вы можете четко видеть объявление любого типа значений, имеющего 'extends System.ValueType', что делает его эффективным базовым классом. Я думаю, что его основная роль - это маркер, чтобы различать класс и тип значения, но я не уверен. – Abel

6

Использование struct в качестве общего ограничения функционально эквивалентно ограничению «ValueType». В .NET, a struct is a value type.

+0

Структура - это значение «ValueType», да, но не каждый тип значения является структурой, например, 'ValueType' сам по себе не является структурой и не является допустимыми типами значений. – Abel

Смежные вопросы