Как типы значений выводятся из объекта (ReferenceType) и все еще являются типами значений?



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



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

618   5  

5 ответов:

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

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

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

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

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

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

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

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

конечно. Тип структуры может переопределять 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 находится внутри О.

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

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

  • никакой голубой ящик не находится внутри E.

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

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

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

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

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

как типы значений выводятся из объекта (ReferenceType) и все еще являются типами значений?

как

как это возможно, что каждый красный ящик (типы значений) находится внутри (происходит от) box 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
 {
 }

это даже не будет компилироваться. Компилятор напомнит вам " тип " системы.ValueType 'in interface list - это не интерфейс".

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

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

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

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

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

Comments

    Ничего не найдено.