Основываясь на следующий вопрос, заданный несколько дней назад в так: метод gettype() и полиморфизм и значение Эрик Липперт'с ответа, я начал думать, если делать метод gettype () не виртуальные, действительно гарантировал, что объект не может врать о его "тип".
В частности, Эрик'ы ответ гласит следующее:
В рамках дизайнеры добавлять не будем невероятно опасную особенность, например, что объект врать про свои типа просто чтобы привести его в соответствие с тремя другими методами на тот же тип.
Теперь вопрос: Можно ли сделать объект, который делает ** ложь о его типа не сразу заметно? Может быть, я глубоко ошибся здесь, и я'd любовь разъяснений, если это так, но рассмотрим следующий код:
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
выводит ошибочное тип
.
Теперь я не'т знаю, имеет ли это серьезные последствия, основанные на Эрика, описывающих это поведение как-то "невероятно опасные функция", но может это узор создают реальную угрозу?
Хороший вопрос! Как я это вижу, вы можете только действительно ввести в заблуждение коллег-разработчиков, если метод gettype был фактически на объект, который это'т.
То, что вы сделали сродни тенизации метод gettype, как это:
public class BadFoo
{
public new Type GetType()
{
return typeof(int);
}
}
этот класс (и используя пример кода из MSDN для метод gettype ()) вы действительно могли бы:
int n1 = 12;
BadFoo foo = new BadFoo();
Console.WriteLine("n1 and n2 are the same type: {0}",
Object.ReferenceEquals(n1.GetType(), foo.GetType()));
// output:
// n1 and n2 are the same type: True
так, блин, вы'вэ успешно соврал, верно?
Ну, и да, и нет... считают, что, используя это как подвиг означал бы, используя свой экземпляр BadFoo в качестве аргумента в метод где-то, что ожидает, скорее всего, объект
или общий базовый тип для иерархии объектов. Что-то вроде этого:
public void CheckIfInt(object ob)
{
if(ob.GetType() == typeof(int))
{
Console.WriteLine("got an int! Initiate destruction of Universe!");
}
else
{
Console.WriteLine("not an int");
}
}
но CheckIfInt(ФОО)` печатает "и не int и".
Так что, в принципе (в вашем примере), вы могли действительно использовать вашу "лежа тип" с кодом, который кто-то написал от вашего IFoo интерфейс, который очень четко о том, что он имеет и"таможня" в метод gettype()
метод.
Только если метод gettype() был фактически на объект, вы могли бы создать и"лежа" и типа, которые могут быть использованы с такими методами, как CheckIfInt
выше, чтобы создать хаос в библиотеки, написанные кем-то другим.
Есть два способа быть уверенным в тип:
typeof
на типа, который может'т быть перегруженыIFoo badFoo = новый BadFoo(); IFoo niceFoo = новый NiceFoo();
В консоли.Метода WriteLine("и BadFoo говорит, что он'ы '{0}'&я badFoo.Метод gettype().Метод toString()); В консоли.Метода WriteLine("и NiceFoo говорит, что он'ы '{0}'&я niceFoo.Метод gettype().Метод toString());
В консоли.Метода WriteLine("в BadFoo действительно '{0}'&я, вызова typeof(BadFoo)); В консоли.Метода WriteLine("в NiceFoo действительно '{0}'&я, вызова typeof(NiceFoo)); В консоли.С readline();
метод gettype()
IFoo badFoo = новый BadFoo(); IFoo niceFoo = новый NiceFoo();
В консоли.Метода WriteLine("и BadFoo говорит, что он'ы '{0}'&я badFoo.Метод gettype().Метод toString()); В консоли.Метода WriteLine("и NiceFoo говорит, что он'ы '{0}'&я niceFoo.Метод gettype().Метод toString());
В консоли.Метода WriteLine("в BadFoo действительно '{0}'&Я, ((объект)badFoo).Метод gettype()); В консоли.Метода WriteLine("в NiceFoo действительно '{0}'&Я, ((объект)niceFoo).Метод gettype()); В консоли.С readline();
Нет, вы можете'т принять метод gettype ложь. Вы не только внедрение нового метода. Только код, которые знают этот метод будем называть его.
Нельзя, например, стороннего или рамочный кодекс вызвать ваш новый метод gettype, а не реальный, так что код не знает, что существует метод и поэтому никогда не называю.
Однако вы можете запутать своих собственных разработчиков с таким заявлением. Любой код, который компилируется с вашей декларации и, что использование параметров или переменных с типом IFoo или любой тип, производный от этого действительно будет использовать свой новый метод. Но поскольку это влияет только на ваш собственный код не ввести и "Опасная" по.
Если вы хотите, чтобы обеспечить изготовленный на заказ описание типа для класса, это должно быть сделано с помощью пользовательский тип дескриптора, возможно, путем аннотирования класса с TypeDescriptionProviderAttribute. Это может быть полезно в некоторых ситуациях.
Ну, вообще-то есть такое уже тип, который может лежать в метод gettype
: любой тип, допускающий значение null.
int? x = 0; int y = 0;
Console.WriteLine(x.GetType() == y.GetType());
выходы правда
.
На самом деле, это's Не типа int?
кто врет, просто неявное приведение к объекту
превращает инт?
в коробке типа int
. Но, тем не менее, вы cannot сказать типа int?
от инт
с метод gettype()
.
Я не'т думаю, что это будет, так как каждая библиотека кода, который вызывает метод gettype будет объявить переменную как 'объект' или в качестве универсального типа 'Т'
Следующий код:
public static void Main(string[] args)
{
IFoo badFoo = new BadFoo();
IFoo niceFoo = new NiceFoo();
PrintObjectType("BadFoo", badFoo);
PrintObjectType("NiceFoo", niceFoo);
PrintGenericType("BadFoo", badFoo);
PrintGenericType("NiceFoo", niceFoo);
}
public static void PrintObjectType(string actualName, object instance)
{
Console.WriteLine("Object {0} says he's a '{1}'", actualName, instance.GetType());
}
public static void PrintGenericType<T>(string actualName, T instance)
{
Console.WriteLine("Generic Type {0} says he's a '{1}'", actualName, instance.GetType());
}
печать:
BadFoo объект говорит, что он'ы с 'TypeConcept.BadFoo'
объект NiceFoo говорит, что он'ы с 'TypeConcept.NiceFoo'
универсальный BadFoo тип говорит, что он'ы с 'TypeConcept.BadFoo'
универсальный NiceFoo тип говорит, что он'ы с 'TypeConcept.NiceFoo'
Единственный раз, когда подобный код приведет к плохому сценарию's-это в свой собственный код, где вы объявить тип параметра как IFoo
public static void Main(string[] args)
{
IFoo badFoo = new BadFoo();
IFoo niceFoo = new NiceFoo();
PrintIFoo("BadFoo", badFoo);
PrintIFoo("NiceFoo", niceFoo);
}
public static void PrintIFoo(string actualName, IFoo instance)
{
Console.WriteLine("IFoo {0} says he's a '{1}'", actualName, instance.GetType());
}
IFoo BadFoo говорит, что он'ы с 'системы.Типа int32'
IFoo NiceFoo говорит, что он'ы с 'TypeConcept.NiceFoo'
Худшее, что может произойти, насколько я могу сказать, вводит в заблуждение невинных программистов, которые происходят в использовании отравленных класса, например:
Type type = myInstance.GetType();
string fullName = type.FullName;
string output;
if (fullName.Contains(".Web"))
{
output = "this is webby";
}
else if (fullName.Contains(".Customer"))
{
output = "this is customer related class";
}
else
{
output = "unknown class";
}
Если после
- это экземпляр класса, такие, как вы описали в вопросе, это будет просто рассматриваться как неизвестный тип.
Так что мой ответ нет, может'т вижу никакой реальной угрозы здесь.
У вас есть несколько вариантов, если вы хотите перестраховаться против такой хак:
Приведение к объекту первого
Вы можете вызвать метод в метод gettype () первый кастинг экземпляр
объект`:
Console.WriteLine("BadFoo says he's a '{0}'", ((object)badFoo).GetType());
результаты в:
BadFoo says he's a 'ConsoleApplication.BadFoo'
Использовать метод шаблона
Используя этот метод шаблон также даст вам реальную типа:
static Type GetType<T>(T obj)
{
return obj.GetType();
}
GetType(badFoo);
Есть разница между объекта.Метод gettype и IFoo.Метод gettype
. Метод gettype вызывается во время компиляции не известны объекты, а не на интерфейсы. В вашем примере с badFoo выход
.Метод gettype-это ожидаемое поведение, потому что вы перегружаете метод. Только дело в том, что другие программисты могут запутаться в этом поведении.
Но если вы используете для вызова typeof ()
, он выдает, что типа то же самое, и вы можете'т перезаписать для вызова typeof()
.
Также программист может увидеть во время компиляции, какой метод метод gettype
он ссылается.
Поэтому на ваш вопрос: этот шаблон не может представлять реальной угрозы, но это тоже не лучший стиль кодирования.