Как ValueTypes производным от объекта (ReferenceType) и еще ValueTypes?

C# не позволяет структурам выводиться из классов, но все типы значений выводятся из Object. Где проводится это различие?

как CLR справляется с этим?

5 ответов


C# не позволяет структурам выводиться из классов

ваше утверждение неверно, отсюда и ваше недоумение. В C# тут разрешить структурам наследоваться от классов. Все структуры происходят из одного класса System.ValueType, производный от System.Объект. И все перечисления происходят из системы.Перечисление.

UPDATE: в некоторых (теперь удаленных) комментариях была некоторая путаница, которая требует разъяснения. Я попрошу еще вопросы:

а структуры являются производными от базового типа?

ясно да. Мы можем увидеть это, прочитав первую страницу спецификация:

все типы C#, включая примитивные типы, такие как int и double, наследуются от одного корневого типа объекта.

теперь я отмечаю, что спецификация преувеличивает случай здесь. Типы указателей не являются производными от object, а отношение вывода для типов интерфейса и type типы параметров более сложны, чем показывает этот эскиз. Однако очевидно, что все типы структур являются производными от базового типа.

существуют ли другие способы, которыми мы знаем, что типы структур происходят от базового типа?

конечно. Тип структуры может переопределять ToString. Что это переопределяет, если не виртуальный метод его базового типа? Поэтому он должен иметь базовый тип. Базовый тип является классом.

могу ли я создать пользовательский структура из класса по моему выбору?

однозначно нет. это не означает, что структуры не являются производными от класса. Структуры являются производными от класса, и таким образом наследуют наследуемые члены этого класса. На самом деле, структуры требуются для получения из определенного класса: перечисления должны быть получены из Enum, структуры должны выводиться из ValueType. Потому что это требуются, язык C#запрещает вы от указания отношения деривации в коде.

зачем запрещать?

когда отношение требуются, конструктор языков имеет опции: (1) требовать от пользователя ввести требуемое заклинание, (2) сделать его необязательным или (3) запретить его. У каждого есть плюсы и минусы, и дизайнеры языка C# выбрали по-разному в зависимости от конкретных деталей каждого.

например, поля const должны быть статическими, но это запрещено говорить, потому что это, во-первых, бессмысленное словоблудие, а во-вторых, подразумевает, что существуют нестатические поля const. Но перегруженные операторы должны быть отмечены как статические, даже если у разработчика нет выбора; разработчикам слишком легко поверить, что перегрузка оператора является методом экземпляра в противном случае. Это отменяет беспокойство о том, что пользователь может поверить, что "статический" подразумевает, что, скажем, "виртуальный" также возможен.

в этом случае, требуя от пользователя сказать, что их структура происходит от ValueType, кажется просто избыточным глаголом, и это означает, что структура мог бы производного от другого типа. Чтобы устранить обе эти проблемы, C# делает это незаконно указать в коде, что структура происходит от базового типа, хотя это явно так.

аналогично все типы делегатов являются производными от MulticastDelegate, но C# требует от вас не говорят, что.

Итак, мы установили, что все структуры в C# являются производными от класса.

Каковы отношения между наследование и вывод из класса?

многие люди путают отношения наследования в C#. Отношение наследования довольно простое: если структура, класс или делегат типа D происходит от типа класса B, то наследуемые члены B являются также члены D. Это так просто.

что это означает в отношении наследования, когда мы говорим, что структура происходит от ValueType? Просто все наследуемые члены ValueType также являются членами структуры. Вот как структуры получают свою реализацию ToString, например; наследуется от базового класса структуры.

все наследуемые члены? Конечно, нет. Частные члены наследственным?

да. Все частные члены базового класса также являются членами производного типа. Это незаконно называть этих членов по имени, конечно, если сайт вызова не находится в домен доступность члена. Только потому, что у вас есть член, не означает, что вы можете его использовать!

теперь мы продолжим с оригинальным ответом:


как CLR справляется с этим?

очень хорошо. :-)

что делает тип значения типом значения разве что его экземпляры копировать значение. Что делает ссылочный тип ссылочным типом, так это то, что его экземпляры являются копирование ссылки. Вы, кажется, верите, что наследование отношения между типами значений и ссылочными типами-то особенное и необычное, но я не понимаю, что это вера. наследование не имеет ничего общего с тем, как вещи копируются.

посмотрите на это так. Предположим, я скажу следующие факты:

  • есть два вида коробок, красный коробки и синие коробки.

  • Каждый красный ящик пуст.

  • есть три специальные синие коробки под названием O, V и E.

  • O нет внутри любой коробки.

  • V внутри O.

  • E находится внутри V.

  • никакой другой голубой ящик внутри В.

  • нет синий ящик внутри E.

  • Каждый красный ящик находится в V или E.

  • каждая синяя коробка, кроме O, сама находится внутри синей коробки.

синие поля являются ссылочными типами, красные-типами значений, O-системой.Объект, в системы.ValueType, E-система.Перечисление, и" внутреннее "отношение" происходит от".

это совершенно последовательный и простой набор правил, которые вы могли бы легко реализовать сами, если бы у вас было много картона и много терпения. Красный или синий ящик не имеет никакого отношения к тому, что внутри; в реальном мире вполне возможно поместить красный ящик в синий ящик. В среде CLR совершенно законно создавать тип значения, который наследуется от ссылочного типа, если это либо система.ValueType или система.Перечисление.

Итак, давайте перефразируем ваш вопрос:

как ValueTypes производным от объекта (ReferenceType) и еще ValueTypes?

as

как это возможно, что каждый красный ящик (типы значений) находится внутри (происходит от) окна O (System.Объект), который является синим полем (ссылочный тип) и по-прежнему является красным полем (тип значения)?

когда вы так говорите, Я надеюсь, что это очевидно. Ничто не мешает тебе положить красную коробку внутрь коробки V, которая внутри коробки O, которая синий. С чего бы это?


ДОПОЛНИТЕЛЬНОЕ ОБНОВЛЕНИЕ:

первоначальный вопрос Джоан был о том, как это возможно что тип значения является производным от ссылочного типа. Мой первоначальный ответ на самом деле не объяснял никаких механизмов, которые CLR использует для учета того факта, что у нас есть отношение деривации между двумя вещами, которые имеют совершенно разные представления, а именно, имеют ли упомянутые данные заголовок объекта, синхронизацию блок, владеет ли он собственным хранилищем для целей сбора мусора и так далее. Эти механизмы сложны, слишком сложны, чтобы объяснить их в одном ответе. Правила системы типов CLR довольно сложны, чем несколько упрощенный вкус, который мы видим в C#, где нет сильного различия между коробочной и распакованной версиями типа, например. Введение дженериков также вызвало большую дополнительную сложность, которая будет добавлена к СБРОС. Обратитесь к спецификации CLI для деталей, обращая особое внимание на правила для бокса и ограниченных виртуальных вызовов.


Это несколько искусственная конструкция, поддерживаемая CLR, чтобы все типы рассматривались как система.Объект.

типы значений являются производными от System.Объект через система.ValueType, где происходит специальная обработка (т. е. CLR обрабатывает бокс/распаковку и т. д. Для любого типа, производного от ValueType).


небольшая коррекция, C# не позволяет структурам произвольно выводиться из чего-либо, а не только из классов. Все, что может сделать структура, это реализовать интерфейс, который очень отличается от деривации.

Я думаю, что лучший способ ответить на это, что ValueType особенная. По существу, это базовый класс для всех типов значений в системе типов среды CLR. Трудно знать, как ответить "как CLR обрабатывает это", потому что это просто правило CLR.


ваше утверждение неверно, отсюда и ваше недоумение. C# позволяет структурам наследоваться от классов. Все структуры происходят из одного класса System.ValueType

Итак, давайте попробуем этот:

 struct MyStruct :  System.ValueType
 {
 }

это даже не будет компилироваться. Компилятор напомнит вам систему "Type".Велоэтапе в список интерфейс не интерфейс".

при декомпиляции Int32, который является структурой, вы найдете:

публичная структура Int32: IComparable, Разделе, В Разделе Iconvertible {}, не упоминая, что он получен из системы.ValueType. Но в обозревателе объектов вы обнаружите, что Int32 наследуется от System.ValueType.

Итак, все это заставляет меня поверить:

Я думаю, что лучший способ ответить на это - это то, что ValueType особенный. По существу, это базовый класс для всех типов значений в системе типов среды CLR. Трудно знать, как ответить "как CLR обрабатывает это", потому что это просто правило СБРОС.


упакованный тип значения фактически является ссылочным типом (он ходит как один и крякает как один, поэтому эффективно он один). Я бы предположил, что ValueType на самом деле не является базовым типом типов значений, а скорее является базовым ссылочным типом, к которому типы значений могут быть преобразованы при приведении к типу Object. Сами неупакованные типы значений находятся вне иерархии объектов.