Интерфейсы являются производными от System.Object? C # spec говорит да, Эрик говорит нет, реальность говорит нет

Вопрос прост и задан в заголовке.

В спецификации C # 4.0 сказано: (§4.2.2)

  

Тип объекта класса является окончательным   Базовый класс всех других типов. каждый   введите C # прямо или косвенно   происходит от типа класса объекта.

Эрик Липперт говорит :

  

Типы интерфейса, не являющиеся классами,   не получены из объекта.

Реальность говорит:

Type t = typeof(ICloneable).BaseType;
Console.WriteLine(t == null);
  

True

Так что спецификация не так или как? Кому верить?

32 голоса | спросил Andrey 13 J000000Tuesday10 2010, 14:41:31

3 ответа


0

Это не такой простой вопрос, как вы могли бы подумать:)

Интерфейсы не являются производными от object, но вы можете вызывать членов object на них. Таким образом, вы можете вызвать ToString() для выражения, имеющего тип времени компиляции IDisposable, например.

По совпадению, я обсуждаю этот момент между Нилом Гафтером и Эриком в НЦД.

Я считаю, что, к сожалению, раздел 4.2.2 спецификации слишком упрощен. Надеюсь, Мэдс и Эрик исправят это в будущем выпуске - я пришлю им письмо, чтобы убедиться, что они увидят этот вопрос.

Я также изо всех сил пытаюсь найти что-то в спецификации, чтобы поддержать оставшуюся часть этого ответа. Раздел 3.4.5 спецификации C # 4 подходит настолько близко, насколько я могу найти:

  

Члены интерфейса - это члены, объявленные в интерфейсе и во всех базовых интерфейсах интерфейса. Члены класса object, строго говоря, не являются членами какого-либо интерфейса (13.2). Однако члены в классе object доступны через поиск членов в любом типе интерфейса (7.4).

Преобразование из типа интерфейса в object рассматривается в разделе 6.1.6:

  

Неявные ссылочные преобразования:

     
  • От любого ссылочного типа до object и dynamic
  •   
ответил Jon Skeet 13 J000000Tuesday10 2010, 14:50:55
0

Джон - это (как обычно) место. Это не так просто, как вы думаете!

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

Простой факт заключается в том, что в объектно-ориентированном программировании термин «наследование» очень часто используется. (Кажется, я помню, что в C ++ есть шесть различных типов наследования, хотя мне было бы сложно назвать их всех в короткие сроки.)

Если бы у меня были мои детекторы, то спецификация C # явно указала бы разницу между наследованием и реализацией интерфейса . Наследование - это * метод совместного использования кода для типов классов (и делегатов) и структур (и перечислений) "; его механизм заключается в том, что все наследуемые члены базового типа становятся членами производного типа . в отличие от реализации интерфейса , которая является требованием, чтобы тип реализации имел определенный набор открытых членов . Эти две вещи кажутся мне концептуально очень разными, одна из них касается совместное использование существующих участников , а другой - о требовании определенных членов .

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

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

ответил Eric Lippert 14 J000000Wednesday10 2010, 02:07:53
0

Типы интерфейса не наследуются от Object, но места хранения типов интерфейса содержат ссылки на объекты типа класса, которые (если не null) гарантированно наследуется от System.Object.

Я думаю, что понять, что происходит, будет легче, если начать с изучения различий между типами значений и типами классов. Предположим, у меня есть структура:

public struct SimplePoint {public int x,y;}

и у меня есть два метода

public doSomethingWithPoint(SimplePoint pt) ...
public doSomethingWithObject(Object it) ...

и назовите каждый метод:

SimplePoint myPoint = ...;
doSomethingWithPoint(myPoint);
dosomethingWithObject(myPoint);

Первый вызов не пропускает ничего, что происходит от Object. Вместо этого он передает содержимое всех открытых и закрытых полей SimplePoint. Второму вызову нужна вещь, которая наследуется от Object, поэтому он генерирует новый экземпляр объекта кучи типа SimplePoint, который содержит все открытые и закрытые поля типа значения SimplePoint, загружает все эти поля с соответствующими значениями из myPoint и передает ссылку на этот объект.

Обратите внимание, что тип SimplePoint на самом деле описывает два разных вида вещей: набор полей (то есть тип значения) и куча тип объекта. Какое значение применимо, зависит от контекста, в котором используется тип.

Типы интерфейса имеют похожую складку: при использовании в качестве типов места хранения они указывают, что место хранения будет содержать ссылку на объект. При использовании в качестве общего ограничения они ничего не говорят о том, как будет храниться тип. Таким образом, место хранения типа интерфейса будет содержать ссылку на объект кучи, который действительно наследует от System.Object, но является переменной тип, ограниченный интерфейсом, может содержать либо ссылку, либо набор полей.

ответил supercat 4 FebruaryEurope/MoscowbMon, 04 Feb 2013 01:54:06 +0400000000amMon, 04 Feb 2013 01:54:06 +040013 2013, 01:54:06

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

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132