ValueType - небольшая белая ложь.
Все типы значений являются встроенными численными типами (int, long, byte), char, enums и structs.
Это означает, что они имеют разные концепции идентичности и эквивалентности типов объектов. Если я делаю 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 заключается в том, чтобы позволить, чтобы это произошло.
Для действительно хорошего понимания того, как наилучшим образом создавать типы значений, проверка Эффективный C# (2-е изд.), Билл Вагнер; особенно в пункте 20. В нем также содержится много полезной информации. –
Dupe: [why-cant-i-outive-from-system-enum-abstract-class] (http://stackoverflow.com/questions/2324667/why-cant-i-derive-from-system-enum-abstract -класс) – nawfal
Очень красивый и понятный вопрос. Экономит время чтения. Я призываю всех четко задать вопрос. Благодарю. –