Страницы

Поиск по вопросам

пятница, 5 октября 2018 г.

Почему запрещено наследование от значимых типов?

Почему запрещено наследование от значимых типов, например struct? То что struct sealed - это понятно:) Но почему её сделали sealed?


Ответ

Проблема вот в чём. Допустим, разрешено было бы наследоваться от структур.
Рассмотрим такой код:
class C1 { int x; }
class C2 : C1 { int y; public override string ToString() { return y.ToString(); } }
Вы можете написать так: C1 c = new C2(); и вызвать c.ToString();. Поскольку c является лишь ссылкой на данные, проблем с вызовом не возникает. Это стандартная фича, базовое полиморфное поведение ссылочных типов.
Представьте себе теперь аналогичную ситуацию:
struct S1 { int x; }
struct S2 : S1 { int y; public override string ToString() { return y.ToString(); } }
S1 s = new S2();
Что будет в s? Из соображений эффективности структуры хранятся в памяти как есть, то есть, просто набор полей, а не ссылка на них. Это значит, что под s отводится столько байт, сколько занимает S1, и для поля y там просто нет места! Что в этом случае должен вернуть вызов s.ToString()?
Аналогичная проблема возникает при передаче параметров производного типа в функцию, требующую аргумент базового типа.
Эта проблема называется slicing, и она актуальна для дизайна многих языков программирования. Например, она присутствует в C++. Решение в C# — отказаться от наследования структур: допустить неработающий полиморфизм при наследовании — плохая идея. При таком решении slicing в C# исключён.
Другие языки решают проблему по-другому. Например, в C++ настоящим типом объекта s будет просто S1, а не S2, и y просто потеряется. Создатели языка C# считают такое поведение неинтуитивным, ведущим к проблемам и ошибкам, поэтому они пошли по другому пути. Если вам нужно наследование, в C# нужно воспользоваться классами, или перейти к композиции.

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

Комментариев нет:

Отправить комментарий