首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >GetType()能说谎吗?

GetType()能说谎吗?
EN

Stack Overflow用户
提问于 2013-05-28 08:48:23
回答 8查看 3.6K关注 0票数 94

基于几天前在SO中提出的以下问题:GetType()与多态性和阅读埃里克·利珀特答案,我开始思考,如果让GetType()不是虚拟的,那么就真的可以确保一个对象不能在其Type上撒谎。

具体而言,Eric的答复如下:

框架设计人员不会添加一个极其危险的特性,比如允许对象对其类型进行撒谎,仅仅是为了使其与同一类型上的其他三种方法保持一致。

现在的问题是:我能不能做一个关于它的类型的谎言,而不是马上就显而易见的东西?我在这里可能大错特错,如果是这样的话,我很想澄清,但请考虑以下代码:

代码语言:javascript
复制
public interface IFoo
{
    Type GetType();
}

以及所述接口的以下两个实现:

代码语言:javascript
复制
public class BadFoo : IFoo
{
    Type IFoo.GetType()
    {
        return typeof(int);
    }
}

public class NiceFoo : IFoo
{
}

然后,如果运行以下简单程序:

代码语言:javascript
复制
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将这种行为描述为“非常危险的特性”,但是这种模式会不会构成可信的威胁呢?

EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2013-05-28 09:19:02

问得好!在我看来,只有当GetType在对象上是虚拟的,而它不是虚拟的时候,你才能真正误导其他开发人员。

您所做的类似于跟踪GetType,如下所示:

代码语言:javascript
复制
public class BadFoo
{
    public new Type GetType()
    {
        return typeof(int);
    }
}

使用这个类(并使用GetType()方法的MSDN示例代码),您确实可以拥有:

代码语言:javascript
复制
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或公共基类型。就像这样:

代码语言:javascript
复制
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等方法一起使用,从而在其他人编写的库中造成破坏。

票数 45
EN

Stack Overflow用户

发布于 2013-05-28 09:05:55

确定类型有两种方法:

  1. 在不能重载的类型上使用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}'",类型();();
  2. 将实例强制转换为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();
票数 32
EN

Stack Overflow用户

发布于 2013-05-28 09:22:12

不你不能让GetType撒谎。你只是在介绍一种新的方法。只有知道此方法的代码才会调用它。

例如,您不能让第三方或框架代码调用新的GetType方法而不是真正的方法,因为该代码不知道您的方法存在,因此永远不会调用它。

但是,您可以将您自己的开发人员与这样的声明混淆起来。与声明一起编译并使用输入为IFoo的参数或变量的任何代码或由此派生的任何类型实际上都将使用您的新方法。但是,因为这只会影响您自己的代码,所以它并没有真正造成“威胁”。

如果您确实想为类提供自定义类型描述,则应该使用自定义类型描述符来完成,也许可以通过用TypeDescriptionProviderAttribute注释类来完成。这在某些情况下是有用的。

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16787719

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档