C# · 12月 31, 2021

在.Net / C#中,是空密类型的?

null有一个类型?如何在内部表示一个空值?以下代码发生了什么? void Foo(string bar) {…}void Foo(object bar) {…}Foo((string)null);

编辑:迄今为止的答案是非特定的和太高的级别.引用类型对象由一个指向堆栈的指针组成,它指向堆上的一个位置,它包含同步块索引,类型句柄和对象的字段.当我将一个对象的实例设置为null时,堆栈上的指针指向哪里?而在代码片段中,C#编译器简单地使用的转换来决定要调用哪个重载,并且没有真正的任何转换为​​null?

我正在寻找一个了解CLR内部人员的深入回答.

解决方法 代码示例中的转换字符串不会给null一个类型,因为null不能有类型本身.如果你想证明这一点,那么执行下面的代码,你可以看到null总是等于它自己,不管它分配给哪个类型的变量是: string s = null;IPAddress i = null;Console.WriteLine(object.Equals(s,i)); // prints “True”Console.WriteLine(object.ReferenceEquals(s,i)); // prints “True”

演员所做的是告诉编译器选择哪个重载.由于null没有类型,因此不知道是否选择接受对象或字符串的重载,因为值可以被解释为.所以你正在帮助它说“这是一个空值,应该被视为一个字符串”.

如果你想看看下面发生了什么,那么看看你的代码中的IL.方法调用的相关位在文本IL中类似于以下内容(取决于您的命名空间和类名等):

ldnull call void ConsoleApplication1.Program::Foo(string)

所以发生这种情况的是,在堆栈中加载一个空值,然后由占用字符串的重载消耗,因为在编译时执行重载分辨率,所以调用方法被烧录到IL中.

如果你想看看ldnull的作用,以及为什么不像使用像ldc.i4.0这样的东西把零加载到堆栈上,那么看到this answer(如果你不想跟随链接,原因是它是否则不存在于CLR中的大小不相关的零).