基于几天前在SO中提出的以下问题:GetType()与多态性和阅读埃里克·利珀特答案,我开始思考,如果让GetType()不是虚拟的,那么就真的可以确保一个对象不能在其Type上撒谎。
具体而言,Eric的答复如下:
框架设计人员不会添加一个极其危险的特性,比如允许对象对其类型进行撒谎,仅仅是为了使其与同一类型上的其他三种方法保持一致。
现在的问题是:我能不能做一个关于它的类型的谎言,而不是马上就显而易见的东西?我在这里可能大错特错,如果是这样的话,我很想澄清,但请考虑以下代码:
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。
现在我不知道这是否有任何严重的影响,因为Eric将这种行为描述为“非常危险的特性”,但是这种模式会不会构成可信的威胁呢?
发布于 2013-05-28 09:19:02
问得好!在我看来,只有当GetType在对象上是虚拟的,而它不是虚拟的时候,你才能真正误导其他开发人员。
您所做的类似于跟踪GetType,如下所示:
public class BadFoo
{
public new Type GetType()
{
return typeof(int);
}
}使用这个类(并使用GetType()方法的MSDN示例代码),您确实可以拥有:
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实例用作某个方法的参数,该方法很可能是对象层次结构的object或公共基类型。就像这样:
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(foo)打印的是“不是int”。
因此,基本上(回到您的示例),您实际上只能使用有人针对您的IFoo接口编写的代码来利用您的“说谎类型”,这非常清楚地说明了它有一个“自定义”GetType()方法。
只有当GetType()在对象上是虚拟的时,您才能创建一个“说谎”类型,该类型可以与上面的CheckIfInt等方法一起使用,从而在其他人编写的库中造成破坏。
发布于 2013-05-28 09:05:55
确定类型有两种方法:
typeof
IFoo badFoo =新的BadFoo();IFoo niceFoo =新的NiceFoo();Console.WriteLine("BadFoo说他是'{0}'",badFoo.GetType().ToString());Console.WriteLine("NiceFoo说他是'{0}'",niceFoo.GetType().ToString();Console.WriteLine("BadFoo真的是'{0}'",类型(BadFoo));Console.WriteLine(“Console.WriteLine确实是'{0}'",类型();();object并调用GetType()方法
IFoo badFoo =新BadFoo();IFoo niceFoo =新NiceFoo();Console.WriteLine("BadFoo说他是'{0}'",badFoo.GetType().ToString());Console.WriteLine("NiceFoo说他是‘{0}’“;niceFoo.GetType().ToString();Console.WriteLine("BadFoo确实是‘{0}’”),((Object)badFoo());Console.WriteLine("NiceFoo确实是'{0}'",((对象)niceFoo).GetType();Console.ReadLine();发布于 2013-05-28 09:22:12
不你不能让GetType撒谎。你只是在介绍一种新的方法。只有知道此方法的代码才会调用它。
例如,您不能让第三方或框架代码调用新的GetType方法而不是真正的方法,因为该代码不知道您的方法存在,因此永远不会调用它。
但是,您可以将您自己的开发人员与这样的声明混淆起来。与声明一起编译并使用输入为IFoo的参数或变量的任何代码或由此派生的任何类型实际上都将使用您的新方法。但是,因为这只会影响您自己的代码,所以它并没有真正造成“威胁”。
如果您确实想为类提供自定义类型描述,则应该使用自定义类型描述符来完成,也许可以通过用TypeDescriptionProviderAttribute注释类来完成。这在某些情况下是有用的。
https://stackoverflow.com/questions/16787719
复制相似问题