Почему типы значения.NET изолируются?

Я думаю, что проблемы совместимости были большой проблемой. Прежде всего с IE и Java Microsoft VM, который не был как стандарты, совместимые, как это, возможно, было.

Даже с JVM Sun у Вас могли быть проблемы. Я весело провел время, где у меня было два сторонних Апплета, требующие различных версий Java, который вызывает все виды проблем. Sun попытался решить эту проблему путем замены Апплетов , сеть Java Запускается , который дает Вам ссылку в браузере, который запускает приложение в своем собственном окне вместо внутренней части браузер. (В теории с JWS у Вас могут быть различные приложения с помощью различного VMs, но это никогда, кажется, не работает на меня, а также это должно.)

Продвижения с JavaScript также позволили разработчику намного более богатые веб-страницы так много вещей в прошлом, которое Вы могли только сделать в Апплетах, может теперь быть сделан просто с Ajax.

38
задан Community 23 May 2017 в 12:17
поделиться

4 ответа

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

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

(Есть исключение: объект типа значения может быть помещен в коробку, что позволяет виртуальным методам, унаследованным от System.Object , к быть вызванным.)

Чтобы обратиться к одному из ваших пунктов:

  • Вы можете преобразовать производную структуру в базовую, поскольку они будут перекрывать одну и ту же память.

Нет, это было бы невозможно - приведение типа значения скопировало бы его значение. Здесь мы не имеем дело со ссылками, поэтому в памяти нет перекрытия. Следовательно, приведение типа значения к его базовому типу бессмысленно (опять же, если мы не говорим о преобразовании в объект , который фактически выполняет бокс под капотом, а также работает с ] copy значения).

Все еще не ясно? Давайте посмотрим на пример.

Допустим, у нас есть гипотетическая struct Shape и, наследуя от нее , struct Circle . Форма определяет виртуальный метод Draw (который принимает объект Graphics ). Теперь предположим, что мы хотим нарисовать фигуру на холсте. Это, конечно, работает отлично:

var circle = new Circle(new Point(10, 10), 20);
circle.Draw(e.Graphics); // e.Graphics = graphics object of our form.

- Но здесь мы вообще не используем наследование. Чтобы использовать наследование, представьте вместо этого следующий вспомогательный метод DrawObject :

void DrawObject(Shape shape, Graphics g) {
    // Do some preparation on g.
    shape.Draw(g);
}

И мы вызываем его в другом месте с помощью Circle :

var circle = new Circle(new Point(10, 10), 20);
DrawObject(circle, e.Graphics);

- И, ka-blam - этот код не рисует круг. Почему? Потому что, когда мы передаем круг методу DrawObject , мы делаем две вещи:

  • Мы копируем его.
  • Мы разрезаем его, т. Е. объект shape объект больше не является Кругом - ни оригиналом, ни копией. Вместо этого его часть Circle была «вырезана» во время копирования, и осталась только часть Shape . shape.Draw теперь вызывает метод Draw для Shape , не из Circle .

В C ++ вы действительно можете вызвать такое поведение. По этой причине ООП в C ++ работает только с указателями и ссылками, а не напрямую с типами значений. И по той же причине .NET допускает наследование только ссылочных типов, потому что вы все равно не можете использовать его для типов значений.

Обратите внимание, что приведенный выше код действительно работает в .NET, если Shape - это интерфейс. Другими словами, ссылочный тип . Теперь ситуация иная: ваш объект circle будет по-прежнему скопирован, но он также будет помещен в ссылку.

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

52
ответ дан 27 November 2019 в 03:42
поделиться

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

1
ответ дан 27 November 2019 в 03:42
поделиться

Потому что каждый экземпляр типа значения имеет разный размер и хранится в стеке. Итак, если вы напишете «Base = Derived», где «Base» и «Derived» являются типами значений, вы повредите стек.

-1
ответ дан 27 November 2019 в 03:42
поделиться

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

Я не знаю, что означает «нарезка значений», но полагаю, что они запечатаны, чтобы обеспечить эффективную реализацию CLR.

9
ответ дан 27 November 2019 в 03:42
поделиться
Другие вопросы по тегам:

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