根据几天前在SO:GetType()和多态性中提出的以下问题并阅读Eric Lippert的回答,我开始思考如果GetType()
不是虚拟,确实确保一个对象无法对其产生谎言Type
.
具体而言,Eric的答案陈述如下:
框架设计者不会添加一个令人难以置信的危险特性,例如允许对象只是为了使其与同类型的其他三种方法保持一致.
现在的问题是:我是否可以创建一个对其类型有谎言的对象而不会立即明显?我在这里可能是非常错误的,如果是这样的话,我想要澄清,但请考虑以下代码:
public interface IFoo
{
Type GetType();
}
Run Code Online (Sandbox Code Playgroud)
以及所述接口的以下两个实现:
public class BadFoo : IFoo
{
Type IFoo.GetType()
{
return typeof(int);
}
}
public class NiceFoo : IFoo
{
}
Run Code Online (Sandbox Code Playgroud)
然后,如果您运行以下简单程序:
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();
}
Run Code Online (Sandbox Code Playgroud)
果然badFoo
输出错了Type
.
现在我不知道这是否有任何严重影响,基于埃里克将这种行为描述为" 难以置信的危险特征 ",但这种模式是否会构成可信的威胁?
Pao*_*lla 45
好问题!我看到它的方式,如果GetType在对象上是虚拟的,那么你只能误导同事开发者,而事实并非如此.
你做的是类似于遮蔽GetType,如下所示:
public class BadFoo
{
public new Type GetType()
{
return typeof(int);
}
}
Run Code Online (Sandbox Code Playgroud)
使用此类(并使用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
Run Code Online (Sandbox Code Playgroud)
所以,你已成功撒谎,对吧?嗯,是和否......考虑将此作为漏洞使用将意味着使用您的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");
}
}
Run Code Online (Sandbox Code Playgroud)
但CheckIfInt(foo)
打印"不是int".
所以,基本上(回到你的例子),你真的只能利用你的"撒谎类型"和某人用你的IFoo
界面编写的代码,这是非常明确的,因为它有一个"自定义"的GetType()
方法.
只有当GetType()在对象上是虚拟的时,您才能够创建一个"撒谎"类型,可以与CheckIfInt
上面的方法一起使用,以在其他人编写的库中创建破坏.
Joh*_*zek 32
有两种方法可以确定类型:
typeof
在无法重载的类型上使用
Run Code Online (Sandbox Code Playgroud)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.WriteLine("BadFoo really is a '{0}'", typeof(BadFoo)); Console.WriteLine("NiceFoo really is a '{0}'", typeof(NiceFoo)); Console.ReadLine();
将实例强制转换为an object
并调用GetType()
Method
Run Code Online (Sandbox Code Playgroud)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.WriteLine("BadFoo really is a '{0}'", ((object)badFoo).GetType()); Console.WriteLine("NiceFoo really is a '{0}'", ((object)niceFoo).GetType()); Console.ReadLine();
Mår*_*röm 10
不,你不能让GetType撒谎.您只介绍了一种新方法.只有知道此方法的代码才会调用它.
例如,您不能让第三方或框架代码调用您的新GetType方法而不是真实方法,因为该代码不知道您的方法存在,因此永远不会调用它.
但是,您可以将自己的开发人员与此类声明混淆.任何使用您的声明编译并使用类型为IFoo的参数或变量或从中派生的任何类型的代码确实会使用您的新方法.但由于这只会影响您自己的代码,因此并未真正强加"威胁".
如果您确实希望为类提供自定义类型描述,则应使用自定义类型描述符来完成,可能通过使用TypeDescriptionProviderAttribute注释您的类.这在某些情况下很有用.
嗯,其实有是已经这样一种类型,可以躺在GetType
:任何可空类型.
这段代码:
int? x = 0; int y = 0;
Console.WriteLine(x.GetType() == y.GetType());
Run Code Online (Sandbox Code Playgroud)
输出True
.
其实,这不是int?
谁在说谎,只是隐式转换为object
转int?
成盒装int
.但无论如何,你不能告诉int?
从int
用GetType()
.
我不认为它会,因为每个调用GetType的库代码都会将变量声明为'Object'或通用类型'T'
以下代码:
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());
}
Run Code Online (Sandbox Code Playgroud)
打印:
对象BadFoo说他是'TypeConcept.BadFoo'
对象NiceFoo说他是'TypeConcept.NiceFoo'
通用类型BadFoo说他是'TypeConcept.BadFoo'
通用类型NiceFoo说他是'TypeConcept.NiceFoo'
这种代码导致错误情况的唯一时间是在您自己的代码中,您将参数类型声明为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());
}
Run Code Online (Sandbox Code Playgroud)
IFoo BadFoo说他是'System.Int32'
IFoo NiceFoo说他是'TypeConcept.NiceFoo'
归档时间: |
|
查看次数: |
3353 次 |
最近记录: |