Как структура может наследоваться от класса в ограничениях параметров типа?

Я увидел следующую строку кода:

class Sample<T,U> where T:class where U: struct, T

В приведенном выше случае параметр U имеет тип значения и является производным от типа ссылки T.

Как эта строка может быть допустимой?
Кроме того, если тип значения наследуется от ссылочного типа, где выделяется память: в куче или в стеке?


person Community    schedule 24.02.2009    source источник


Ответы (5)


Вопреки другому ответу, существуют типы помимо T=System.Object, где это компилируется:

class Samplewhere T:class where U:struct, T

Ограничение «T : class» на самом деле не означает, что T должен быть классом. Это означает, что T должен быть ссылочным типом. Сюда входят интерфейсы, а структуры могут реализовывать интерфейсы. Так, например, T=IConvertible, U=System.Int32 работает отлично.

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

Что касается более общего момента: как говорит Обиван Кеноби, все зависит от вашей точки зрения. Спецификация CLI имеет довольно сложное объяснение этого, где «происходит от» и «наследует от» не означает одно и то же, IIRC. Но нет, вы не можете указать базовый тип типа значения — это всегда либо System.ValueType, либо System.Enum (который происходит от System.ValueType), и он выбирается на основе того, объявляете ли вы struct или enum. Несколько сбивает с толку тот факт, что оба они сами по себе являются ссылочными типами...

person Jon Skeet    schedule 24.02.2009
comment
Отличное замечание, сэр. Очевидно, я не все обдумал, когда отвечал. - person Randolpho; 24.02.2009
comment
Я могу представить себе ситуации, когда было бы полезно ограничить параметр типа типом значения, который реализует некоторый изменяющийся интерфейс. Как правило, структурам вредно реализовывать изменяющиеся интерфейсы, потому что система не может отличить изменяющиеся элементы от неизменяемых и не предоставляет никаких средств, с помощью которых объявление структуры может запрещать неявные преобразования, такие как упаковка (что означало бы, что нельзя t к интерфейсу, но сможет использовать его как ограничение). С другой стороны, несмотря на ограничения на их использование,... - person supercat; 23.11.2011
comment
... мутирующие интерфейсы могут обеспечить семантику, которую в противном случае было бы трудно достичь (вероятно, можно было бы добиться того же эффекта, что и семантика типа значения, учитывая метод клонирования, если у вас есть метод клонирования и он используется каждый раз, когда вы копируете ссылку на объект , или же имеет метод, который, учитывая два экземпляра объекта, изменит один для хранения тех же данных, что и другой, но когда требуется семантика типов значений, использование типов значений, вероятно, будет более эффективным). - person supercat; 23.11.2011
comment
Один вопрос, сэр, могу ли я получить класс из структуры в С#? Я думаю, что это возможно в С++. Я пробовал на С#, но у меня были некоторые проблемы, может быть, я не знаю, как это сделать? - person Dhananjay; 24.04.2012
comment
@Dhananjay: Нет, ты не можешь. Вы не можете получить что-либо из структуры в C#. - person Jon Skeet; 24.04.2012

Все структуры неявно наследуются от типа ValueType. Нельзя указать явный базовый тип.
См. это руководство MSDN по структурам, опубликованное codemelt.

  • Когда вы создаете экземпляр структуры, например. как локальная переменная, они размещаются в стеке (лучше производительность)
  • Классы могут содержать структуры в качестве членов — в этом случае они размещаются в куче.
person Gishu    schedule 24.02.2009
comment
Пожалуйста, имейте в виду, что размещение структуры в стеке не обязательно означает лучшую производительность. Только в определенных обстоятельствах вы получите лучшую производительность, используя структуру, и они существуют исключительно для этих обстоятельств. - person Randolpho; 24.02.2009
comment
Выделение большого объекта в стеке потребует много копий, так как структура передается от метода к методу. Если ваша структура особенно тяжелая, вы можете получить хуже производительность. - person Randolpho; 24.02.2009
comment
@Sasha: Это, безусловно, отвечает на первый вопрос! - person Jon Skeet; 24.02.2009

MSDN говорит,

Для структур нет наследования, как для классов. Структура не может наследоваться от другой структуры или класса и не может быть базой класса. Однако структуры наследуются от объекта базового класса. Структура может реализовывать интерфейсы, и делает это точно так же, как и классы.

person Ray Lu    schedule 24.02.2009
comment
просто подумал, что источник должен помочь OP - msdn .microsoft.com/en-us/library/aa288471(VS.71).aspx - person Gishu; 24.02.2009
comment
Ну, это не отвечает на мой вопрос, больше информации в редактировании № 1. - person ; 24.02.2009

Саша Написал:

Если наследование не разрешено, то почему следующее законно:

класс Samplewhere T: класс, где U: структура, T

В приведенном выше случае параметр U является типом значения и является производным от T -- ссылочного типа.

Хотя это допустимо с точки зрения универсального контракта, вы никогда не получите никакого полезного кода, использующего этот класс для компиляции, потому что у вас никогда не будет другого типа, кроме T=System.Object, удовлетворяющего ограничению U. Вы можете подумать, что это очень незначительная ошибка в реализации дженериков в C#.

person Randolpho    schedule 24.02.2009
comment
Потому что Sample‹object, double› является допустимым. Sample‹object, anyvaluetype› допустим, но не более того. - person ShuggyCoUk; 24.02.2009

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

person JaredPar    schedule 24.02.2009
comment
‹педант› или System.Enum ‹/педант› - person Jon Skeet; 24.02.2009
comment
@jon, о да, забыл об этом. Спасибо! - person JaredPar; 24.02.2009