вторник, 5 мая 2015 г.

Модификатор new

Излюбленным вопросом на собеседованиях у многих является вопрос про модификатор new, тем не менее почти никто не представляет, зачем же он действительно нужен. Куски кода, где используется данный модификатор, как правило содержат виртуальный метод и перекрытие этого метода в классе наследнике. Ну и вопрос, какой метод вызван в зависимости от типа ссылки на объект.
В действительности же, мы можем просто переопределить (override) данные метод в своем классе. Так же не существует ни одного принципа или паттерна который бы "узаконивал" существование модификатора new.
Так зачем же он был введен в язык C#? В Java например, все методы, которые не статические и публичные - виртуальные. В .NET пошли на некоторые оптимизации, действительно, не виртуальный метод вызвать проще, адрес виртуального нужно определять в рантайме. 
В итоге имеем методы, которые можно переопределить в наследниках и которые нельзя, так как они не виртуальные. Модификатор new позволяет нам перекрыть в наследнике такие члены как поля, события, свойства, индексаторы и методы. Вообще это плохой дизайн, когда мы в наследниках перекрываем члены своих же классов, лучше изначально объявить их виртуальными. Но у базового класса может быть другой автор, в другой стране и даже на другом континенте, которые не будет ни менять свой код, ни предоставлять исходники. Так вот используя dll с некоторым базовым классом и имея в своем наследнике некоторый член класса, наш код продолжит работать если мы получим новую версию библиотеки в которой появиться член с такой же сигнатурой. Компилятор автоматически будет подставлять new и при этом будет давать нам предупреждение.
Хотя существует еще один известные мне случай, когда использование этого модификатора оправдано. .NET предоставляет для программиста механизм атрибутов, который может использоваться для множества полезных целей. И тут может сложиться ситуация, когда для наследника и предка один и тот же член должен иметь разные атрибуты. Этого конечно можно добиться перестраиванием иерархии классов, введением технологических предков и т. д. Но с помощью new такую задачу решить проще.