Подтвердить что ты не робот

System.ValueType Понимание

Я попытался создать ValueType.

Я понимаю, что создание структуры мне поможет.

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

Но у меня появилось сообщение об ошибке компилятора .. не может быть получено из специального класса System.ValueType "

Когда я вижу метаданные ValueType, он выглядит как обычный абстрактный класс.

  • Что сделало его особенным?

  • Это компилятор С#, который воспринимает его как особый?

  • Если да, рекомендуется ли это, как правило, для разработки компилятора? Я имею в виду, это часть Common Language Specification?

4b9b3361

Ответ 1

ValueType - небольшая белая ложь.

Все типы значений встроены в числовые типы (int, long, byte), char, перечисления и структуры.

Это означает, что они имеют разные концепции идентичности и эквивалентности типов объектов. Если я делаю x = y, а x и y являются ссылочными типами, то x и y теперь указывают на один и тот же объект. Однако, если я делаю x = y, а x и y - типы значений, тогда x и y теперь представляют собой два совершенно разных объекта, которые оказываются идентичными. (Это также отражено в == и Equals, хотя это можно переопределить).

(Здесь люди отвлекаются от разговоров о стеке и куче, если они еще не сделали этого, действительно, что деталь реализации и в то же время важна не для разницы между значениями и ссылочными типами).

Теперь, в основном это все и хорошо, но одна вещь о ссылочных типах заключается в том, что все они извлекают выгоду из наследования из System.Object. Тип значения int на самом деле не так, и это хорошо, так как во многих отношениях это намного лучше, чем просто четыре байта памяти, обработанные прекрасными инструкциями CPU, которые так хороши в этом. Тем не менее, иногда полезно иметь возможность обрабатывать int, как если бы он также унаследовался от System.Object, и поэтому вы можете.

Конечно, это означает, что вы можете делать что-то с int, что имеет смысл делать только в System.Object, поэтому, когда вы это сделаете, int "помещается в коробку" и снова может быть "распакован".

Это здорово, но что, если мы хотим сделать что-то конкретное для типов значений? Более того, что, если разработчики CLR сделали (в частности, им нужен GetHashCode для типов значений, связанных с эквивалентной стоимостью, описанной выше, а не эквивалентностью, основанной на идентификаторах)?

Для этой цели мы имеем ValueType. Система рассматривает все типы значений как наследующие от этого класса, который, в свою очередь, наследует от Object. Enum в свою очередь наследует от типа значения, и все типы перечислений наследуют от него, что позволяет использовать некоторые общие функции во всех перечислениях.

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


Объяснение общей системы:

Структура - это тип значения, который неявно выводится из System.ValueType, который, в свою очередь, получен из System.Object. Структура очень полезна для представления значений, требования к памяти которых малы, и для передачи значений в виде параметров по значению методам, которые имеют строго типизированные параметры. В библиотеке классов .NET Framework все примитивные типы данных (Boolean, Byte, char, DateTime, Decimal, Double, Int16, Int32, Int64, SByte, Single, UInt16, UInt32 и UInt64) определяются как структуры.

Подобно классам, структуры определяют как данные (поля структуры), так и операции, которые могут выполняться над этими данными (методы структуры). Это означает, что вы можете вызывать методы для структур, включая виртуальные методы, определенные в классах System.Object и System.ValueType, и любые методы, определенные для самого типа значения. Другими словами, структуры могут иметь поля, свойства и события, а также статические и нестатические методы. Вы можете создавать экземпляры структур, передавать их в качестве параметров, хранить их как локальные переменные или хранить их в поле другого типа значения или ссылочного типа. Структуры также могут реализовывать интерфейсы.

Типы значений также отличаются от классов в нескольких отношениях. Во-первых, хотя они неявно наследуются от System.ValueType, они не могут напрямую наследоваться от любого типа. Аналогично, все типы значений запечатываются, а это означает, что из них не может быть выведен другой тип. Они также не требуют конструкторов.

Для каждого типа значений общая среда выполнения языков предоставляет соответствующий тип в виде бокса, который является классом, который имеет такое же состояние и поведение, что и тип значения. Экземпляр типа значения помещается в бокс, когда он передается методу, который принимает параметр типа System.Object. Он распаковывается (то есть преобразуется из экземпляра класса обратно в экземпляр типа значения), когда элемент управления возвращается из вызова метода, который принимает тип значения в качестве параметра для ссылки. Некоторые языки требуют, чтобы вы использовали специальный синтаксис, когда требуется тип boxed; другие автоматически используют коробчатый тип, когда это необходимо. Когда вы определяете тип значения, вы определяете как коробку, так и тип unboxed.

Странность ValueType позволяет сделать это выше.

Ответ 2

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

Ответ 3

Невозможность выводить из ValueType специфична для компилятора С#. Если мы посмотрим на управляемый код С++:

value class Foo {};
value class Foo : System::ValueType {};

Оба эти компилируются и идентичны. Конечно,

ref class Foo : System::ValueType {};

Выдает ошибку C3050: класс ref не может наследовать "System:: ValueType".
Не уверен, что другие компиляторы разрешают.

Если вы хотите получить значение ValueType в С#, используйте struct, а не class, и компилятор позаботится об этом.

Ответ 4

вы не можете напрямую подклассифицировать ValueType. Все типы значений производятся из ValueType неявно. В отличие от ссылочных типов, вы не можете получить новый тип из типа значения. Однако, как и ссылочные типы, структуры могут реализовывать интерфейсы.

см. MSDN, чтобы узнать больше

Ответ 5

С# не разрешает типы значений наследовать от других классов. Типы значений (struct) могут реализовывать интерфейсы.

Ответ 6

  • "Класс" расширяет "System.Object", а "struct" расширяет "System.ValueType". Если вы могли бы расширить класс "System.ValueType", тогда ключевое слово "struct" не будет иметь большого значения.

  • Да

  • Да. Должен быть только один способ выполнить любую данную вещь. Как только будут предоставлены два способа сделать что-то, вы просто сделаете все более сложным. Общее правило.

Ответ 7

Вот что меня озадачивает... Enum происходит из ValueType. Это заставляет меня думать, что это просто ограничение компилятора.

[Serializable, ComVisible(true)]
public abstract class Enum : ValueType, IComparable, IFormattable, IConvertible
{
  ...
}