Если структура не может наследовать другой класс или структуру, почему Int32 имеет метод ToString()?
int a = 2;
Console.WriteLine(a.ToString()); // displays 2
// definition of ToString() here - public override string ToString();
Теперь, вот некоторые из моих понятий:
- Все классы в .net получают метод
ToString()
, который наследуется от класса Object
.
- Структура не может быть получена из класса или другой структуры.
int
- это структура типа Int32
, которая получает пару методов ToString()
[With Parameters] из интерфейсов, которые она реализует.
- В struct
Int32
имеется функция
ToString()
[без параметров]
Согласно http://msdn.microsoft.com/en-us/library/system.int32.tostring.aspx,
struct Int32 переопределяет метод ValueType.ToString()
Если структура не может наследовать какой-либо класс или структуру, можете ли вы объяснить, как этот метод ToString()
доступен для Int32
?
Ответы
Ответ 1
Если структура не может наследовать некоторый класс или структуру,
Это неверно. Все структуры (и встроенные типы значений, такие как System.Int32
, System.Single
и т.д.) Всегда неявно наследуют от System.ValueType
(который, в свою очередь, наследует от System.Object
).
Однако вы не можете создать структуру, которая наследуется от всего остального.
Это четко указано в спецификации языка С#, 4.1.1:
4.1.1 Тип System.ValueType
Все типы значений неявно наследуются от класса System.ValueType, который, в свою очередь, наследуется от объекта класса. Невозможно, чтобы любой тип выводился из типа значения, поэтому типы значений неявно закрыты (§10.1.1.2).
Затем, позже (4.1.3) struct явно определяется как тип значения:
4.1.3 Типы конструкций
Тип структуры - тип значения, который может объявлять константы, поля, методы, свойства, индексы, операторы, конструкторы экземпляров, статические конструкторы и вложенные типы.
Ответ 2
Int32
реализует IFormattable
, который определяет метод ToString
Ответ 3
Каждое определение типа, производного от ValueType, фактически определяет два разных типа вещей во время выполнения: тип объекта кучи (который происходит от ValueType
и, в свою очередь, от Object
и который содержит информацию о встроенном типе) и тип места хранения (который не содержит информации о встроенном типе, а вместо этого требует, чтобы используемый им код должен иметь некоторые другие способы узнать, что это такое). Экземпляр типа объекта кучи содержит поле типа хранилища, а код, который пытается получить доступ к this
, получит доступ к этому полю. Если тип значения применяется неявно или явно к месту хранения ссылочного типа, система создаст новый объект кучи с соответствующим типом и скопирует все общедоступные и частные поля типа значения в соответствующие поля в кучном объекте. Если объект кучи отбрасывается в хранилище данных типа значения, все общедоступные и частные поля из объекта кучи будут скопированы в хранилище значений типа.
Если делается попытка использовать любой метод Object
или интерфейса для объекта кучи типа значения, метод будет вызываться так же, как и любой другой метод кучного объекта. Если попытка сделана в месте хранения типа значения, для любого метода, отличного от GetType
, компилятор будет генерировать специальный "ограниченный" код операции, который сообщает время выполнения типа хранилища и указывает время выполнения вызова адрес метода, соответствующего этому типу. Поскольку у компилятора будет доступный тип местоположения хранилища, и время выполнения может использовать его для поиска соответствующего метода, соответствующий метод можно вызвать непосредственно в месте хранения, не создавая сначала новый объект кучи. GetType
является единственным заметным исключением; поскольку он работает, исследуя информацию о типе, встроенную в объект, он может работать только на вещи, которые имеют встроенную информацию о типе. Следовательно, его аргумент будет преобразован в форму кучи объекта перед вызовом; GetType
затем сможет исследовать информацию о встроенном типе этого объекта кучи.