Как ValueTypes происходят из Объекта (ReferenceType) и все еще ValueTypes?

Хороший способ видеть его состоит в том, что лямбды выполняются в их собственном объеме (как будто это был вызов метода), в то время как Procs может быть просмотрен как выполняемый встроенный с вызывающим методом, по крайней мере, это - хороший способ решить который использовать в каждом случае.

78
задан Jon Seigel 27 February 2010 в 03:48
поделиться

3 ответа

C# doesn't allow structs to derive from classes

Your statement is incorrect, hence your confusion. C# does allow structs to derive from classes. All structs derive from the same class, System.ValueType, which derives from System.Object. And all enums derive from System.Enum.

UPDATE: There has been some confusion in some (now deleted) comments, which warrants clarification. I'll ask some additional questions:

Do structs derive from a base type?

Plainly yes. We can see this by reading the first page of the specification:

All C# types, including primitive types such as int and double, inherit from a single root object type.

Now, I note that the specification overstates the case here. Pointer types do not derive from object, and the derivation relationship for interface types and type parameter types is more complex than this sketch indicates. However, plainly it is the case that all struct types derive from a base type.

Are there other ways that we know that struct types derive from a base type?

Sure. A struct type can override ToString. What is it overriding, if not a virtual method of its base type? Therefore it must have a base type. That base type is a class.

May I derive a user-defined struct from a class of my choice?

Plainly no. This does not imply that structs do not derive from a class. Structs derive from a class, and thereby inherit the heritable members of that class. In fact, structs are required to derive from a specific class: Enums are required to derive from Enum, structs are required to derive from ValueType. Because these are required, the C# language forbids you from stating the derivation relationship in code.

Why forbid it?

When a relationship is required, the language designer has options: (1) require the user to type the required incantation, (2) make it optional, or (3) forbid it. Each has pros and cons, and the C# language designers have chosen differently depending on the specific details of each.

For example, const fields are required to be static, but it is forbidden to say that they are because doing so is first, pointless verbiage, and second, implies that there are non-static const fields. But overloaded operators are required to be marked as static, even though the developer has no choice; it is too easy for developers to believe that an operator overload is an instance method otherwise. This overrides the concern that a user may come to believe that the "static" implies that, say "virtual" is also a possibility.

In this case, requiring a user to say that their struct derives from ValueType seems like mere excess verbiage, and it implies that the struct could derive from another type. To eliminate both these problems, C# makes it illegal to state in the code that a struct derives from a base type, though plainly it does.

Similarly all delegate types derive from MulticastDelegate, but C# requires you to not say that.

So, now we have established that all structs in C# derive from a class.

What is the relationship between inheritance and derivation from a class?

Many people are confused by the inheritance relationship in C#. The inheritance relationship is quite straightforward: if a struct, class or delegate type D derives from a class type B then the heritable members of B are also members of D. It's as simple as that.

What does it mean with regards to inheritance when we say that a struct derives from ValueType? Simply that all the heritable members of ValueType are also members of the struct. This is how structs obtain their implementation of ToString, for example; it is inherited from the base class of the struct.

All heritable members? Surely not. Are private members heritable?

Yes. All private members of a base class are also members of the derived type. It is illegal to call those members by name of course if the call site is not in the accessibility domain of the member. Just because you have a member does not mean you can use it!

We now continue with the original answer:


How does the CLR handle this?

Extremely well. :-)

What makes a value type a value type is that its instances are copied by value. What makes a reference type a reference type is that its instances are copied by reference. You seem to have some belief that the inheritance relationship between value types and reference types is somehow special and unusual, but I don't understand what that belief is. Inheritance has nothing to do with how things are copied.

Look at it this way. Suppose I told you the following facts:

  • There are two kinds of boxes, red ящики и синие ящики.

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

  • Есть три специальных синих ящика, называемых O, V и E.

  • O не находится внутри ни одного ящика.

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

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

  • Никакой другой синий прямоугольник не находится внутри V.

  • Нет синего прямоугольника внутри E.

  • Каждый красный прямоугольник находится либо в V, либо в E.

  • Каждый синий прямоугольник, кроме O, является сам внутри синего прямоугольника.

Синие прямоугольники - это ссылочные типы, красные прямоугольники - это типы значений, O - это System.Object, V - это System.ValueType, E - System.Enum, а «внутреннее» отношение - это производные от".

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

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

Как ValueTypes наследуются от Object (ReferenceType) и по-прежнему остаются ValueTypes?

как

Как это возможно, что каждое красное поле (типы значений) находится внутри (происходит от ) box O (System.Object), который является синим прямоугольником (ссылочный тип) и по-прежнему является красным прямоугольником (тип значения)?

Когда вы это формулируете таким образом, я надеюсь, что это очевидно. Ничто не мешает вам поместить красную коробку в коробку V, которая находится внутри синей коробки O. Почему это могло быть?


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

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

103
ответ дан 24 November 2019 в 10:34
поделиться

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

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

20
ответ дан 24 November 2019 в 10:34
поделиться

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

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

21
ответ дан 24 November 2019 в 10:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: