基于几天前在 SO 中提出的以下问题:GetType() and polymorphism 并阅读 Eric Lippert's 答案,我开始思考是否使 GetType() 不是虚拟的真的能确保一个对象不能对其 0x231348 撒谎。

具体来说,埃里克的回答说明如下:



现在的问题是:我可以制作一个在类型上撒谎的对象而不是立即显而易见的吗?我在这里可能大错特错,如果是这种情况,我很想澄清一下,但请考虑以下代码:

public interface IFoo
{
    Type GetType();
}

以及上述接口(interface)的以下两个实现:
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();
}

果然 Type 输出错误的 badFoo

现在我不知道根据 Eric 将这种行为描述为“极其危险的特征”,这是否有任何严重影响,但这种模式是否会构成可信的威胁?

最佳答案

好问题!在我看来,如果 GetType 在对象上是虚拟的,你只能误导其他开发人员,而事实并非如此。

您所做的类似于隐藏 GetType,如下所示:

public class BadFoo
{
    public new Type GetType()
    {
        return typeof(int);
    }
}

使用此类(并使用 the sample code from the MSDN for the GetType() method )您确实可以拥有:
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)基类型。像这样的东西:
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) 打印“不是整数”。

因此,基本上(回到您的示例),您实际上只能使用某人针对您的 IFoo 接口(interface)编写的代码来利用您的“谎言类型”,这非常明确地说明它具有“自定义” GetType() 方法这一事实。

只有当 GetType() 在对象上是虚拟的,您才能制作一个“谎言”类型,该类型可以与上面的 CheckIfInt 之类的方法一起使用,以在其他人编写的库中造成严重破坏。

关于c# - GetType() 会撒谎吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16787719/

10-12 20:47