Виходячи з наступного запитання, яке було задано кілька днів тому в SO: GetType () та поліморфізму та читання відповіді Еріка Ліпперта , я почав думати, чи GetType()не бути віртуальним насправді гарантує, що об’єкт не може брехати про нього Type.
Зокрема, у відповіді Еріка зазначено наступне:
Дизайнери фреймворку не збираються додавати неймовірно небезпечну функцію, таку як дозволяти об’єкту брехати про свій тип, лише щоб зробити його узгодженим з трьома іншими методами того ж типу.
Тепер питання: чи можу я зробити об’єкт, який бреше про свій тип, не відразу це очевидно? Я можу тут глибоко помилятися, і я хотів би пояснити, якщо це так, але враховуйте наступний код:
public interface IFoo
{
Type GetType();
}
І наступні дві реалізації згаданого інтерфейсу:
public class BadFoo : IFoo
{
Type IFoo.GetType()
{
return typeof(int);
}
}
public class NiceFoo : IFoo
{
}
Тоді, якщо ви запустите таку просту програму:
static void Main(string[] args)
{
IFoo badFoo = new BadFoo();
IFoo niceFoo = new NiceFoo();
Console.WriteLine("BadFoo says he's a '{0}'", badFoo.GetType().ToString());
Console.WriteLine("NiceFoo says he's a '{0}'", niceFoo.GetType().ToString());
Console.ReadLine();
}
Звичайно, badFooвиводиться помилкове повідомлення Type.
Зараз я не знаю, чи це має якісь серйозні наслідки, засновані на тому, що Ерік описує цю поведінку як " неймовірно небезпечну особливість ", але чи може цей шаблон представляти надійну загрозу?
IFoo.GetTypeі object.GetTypeце не те саме, тому тут нічого поганого не відбувається, крім поганого стилю. Редагувати: загалом GetTypeбуде викликано якийсь об’єкт, невідомий під час компіляції, в більшості випадків, objectа не якийсь хитрий інтерфейс. :)
GetType, з тим самим підписом. Це не стосується GetTypeважливого методу. Ви також можете зробити відкритий метод примірника, який приховує відповідний GetTypeметод, використовуючи newключове слово modifier. Зверніть увагу, що якщо у вас є загальний метод типу static Type Test<T>(T t) { return t.GetType(); }(без обмежень T), такі речі Test<IFoo>(new BadFoo())все одно викликатимуть оригінальний GetTypeметод.