不从 System.Object 继承之后
Written by Allen Lee
上一篇文章说到 IL 允许创建一个不继承自 System.Object 的类,这打破了我们已有的一些认识。到了这个份上,我们自然会追问,为什么要允许这种类型存在呢?
考察如下 C++/CLI 代码:
using
namespace
System;2

3
public
ref
class
Person4

{5
public:6
Person(String^name)7


{8
m_Name=name;9
}10

11
Person(Person%p)12


{13
m_Name=p.Name;14
}15

16
propertyString^Name17


{18
String^get()19


{20
returnm_Name;21
}22
}23

24
private:25
String^m_Name;26
}
;27

28
void
DisplayPersonInfo(Personp)29

{30
Console::WriteLine("Name:{0}",p.Name);31
}
32

33
int
main(array
<
System::String
^>
^
args)34

{35
Person^p=gcnewPerson("Allen");36
DisplayPersonInfo(*p);37

38
return0;39
}
DisplayPersonInfo 方法只能用在 C++/CLI 中,你无法在 C# 中对引用类型进行解引用,就像第三十六行那样。为了处理 C++/CLI 的特性,IL 引入了不少别的语言无法使用的东西。
或许,如同部分评论所言,此举乃是为某些语言的特性埋下伏笔。然而,此举却为 C# 带来了麻烦。我用上一篇文章里所说的方法创建了一个不继承自 System.Object 的 NoInherit 类,置于 NoInherit.dll 中,然后用 Visual Studio 2005 新建一个项目,引用 NoInherit.dll,并在 Main 里写下这些代码:
Typet
=
typeof
(NoInherit);2
Console.WriteLine(t.BaseType
==
null
);3

4
NoInheritni
=
new
NoInherit(
"
NoInherit
"
);5
object
o
=
ni
as
object
;6
if
(o
!=
null
)7

{8
Console.WriteLine(o.GetType());9
Console.WriteLine(o.ToString());10
}
你猜上面代码的运行结果是什么?正常来说,运行结果应该只有一个 true,即第二行的输出,但事实上,第八行居然正确输出“NoInherit”,而第九行则抛出 AccessViolationException。按道理,第九行的异常是意料中事,但第二行和第五行的结果就很矛盾了。第二行输出 true 表明了 NoInherit 类的确没有继承自 System.Object,但第五行却转换成功,否则 o 应该是 null 的。
当一个系统复杂到一定程度,一个看似没问题的改动可能会导致一些看似不相关的问题。当你拿到一个库时,你是假定里面的所有类都继承自 System.Object,还是去验证一下呢?
探讨了IL允许创建不继承自System.Object的类的原因及其带来的挑战,特别是在C#中的应用和潜在问题。
1925

被折叠的 条评论
为什么被折叠?



