#c_sharp #net
Господа, подскажите, пожалуйста, по коду. Вот ради эксперимента набросал код, но не пойму, почему метод GetNameObj возвращает объект типа a1, если ему как через конструктор, так и через параметр типа передают a2. Вот код: using System; interface a{ T GetNameObj(); } class b : a { T t; public b(T o) { t = o; } public T GetNameObj() { Console.WriteLine(typeof(T).Name); return t; } } class a1 { } class a2 : a1 { } class c { static void Main() { a A = new b (new a2()); a2 A2 =(a2) A.GetNameObj(); //вот этот метод почему-то возвращает тип a1 } } Мне кажется, что единственным объяснением такого поведения является то, что методу без разницы, что я там передаю за тип данных в конструктор или параметр типа, ему главное, что в интерфейсной ссылке указан параметр типа a1. Но в таком случае приоритет выше у параметра типа интерфейса, чем у типа объекта? Или я что-то не правильно понял? Подскажите, пожалуйста.
Ответы
Ответ 1
Вы встретились с различием между заявленным (compile-time) и реальным (run-time) типом. Объект, создаваемый конструктором new b(new a2()), имеет реальный тип b . Поскольку b является разновидностью (то есть, подтипом) a для любого T, то b есть разновидность a . Далее, a2 есть подтип a1, поэтому, вследствие ковариантности a<>, a есть подтип a . Поэтому возможно присвоить переменной A типа a ссылку на объект типа b . Далее, рассмотрим объект, возвращаемый A.GetNameObj(). Поскольку A имеет заявленный тип a , возвращённый объект имеет заявленный тип a1. Реальный же тип этого объекта — a2, т. к. реальный тип A — b . При компиляции для присвоения переменной A2 существенен лишь заявленный тип (компилятор в общем случае не знает, как будет реальный тип), поэтому код без приведения типов не скомпилируется. Тем не менее, приведение типов может привести объект к его реальному типу (но выяснится это лишь во время выполнения), поэтому код с приведением типов работает без выброса исключения. По вашему вопросу: ...методу без разницы что я там передаю за тип данных в конструктор или параметр типа, ему главное что в интерфейсной ссылке указан параметр типа a1. Но в таком случае приоритет выше у параметра типа интерфейса чем у типа объекта ? Для компилируемости кода важен лишь заявленный тип. В вашем случае важен заявленный тип переменной A, а не реальный тип объекта, который будет в эту переменную записан. Если бы вы заявили более сильный тип для переменной A, то приведение типов не понадобилось бы: a A = new b (new a2()); a2 A2 = A.GetNameObj();
Комментариев нет:
Отправить комментарий