栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

为什么要检查此!= null?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

为什么要检查此!= null?

我假设您正在查看.NET 3.5的实现?我相信.NET 4的实现略有不同。

但是,我有一个偷偷摸摸的怀疑,这是因为甚至有可能 在null引用上
非虚拟地调用虚拟实例方法。即在IL中可能。我看看是否可以产生一些IL来调用

null.Equals(null)

编辑:好的,这是一些有趣的代码:

.method private hidebysig static void  Main() cil managed{  .entrypoint  // Code size       17 (0x11)  .maxstack  2  .locals init (string V_0)  IL_0000:  nop  IL_0001:  ldnull  IL_0002:  stloc.0  IL_0003:  ldloc.0  IL_0004:  ldnull  IL_0005:  call instance bool [mscorlib]System.String::Equals(string)  IL_000a:  call void [mscorlib]System.Console::WriteLine(bool)  IL_000f:  nop  IL_0010:  ret} // end of method Test::Main

我是通过编译以下C#代码得到的:

using System;class Test{    static void Main()    {        string x = null;        Console.WriteLine(x.Equals(null));    }}

…然后进行拆卸

ildasm
和编辑。注意这一行:

IL_0005:  call instance bool [mscorlib]System.String::Equals(string)

最初是

callvirt
而不是
call

那么,当我们重新组装时会发生什么呢?好了,有了.NET 4.0,我们得到了:

Unhandled Exception: System.NullReferenceException: Objectreference not set to an instance of an object.    at Test.Main()

嗯 .NET 2.0呢?

Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object.   at System.String.EqualsHelper(String strA, String strB)   at Test.Main()

现在,这变得更有趣了……我们显然已经设法进入了

EqualsHelper
,这是我们通常不会期望的。

足够的字符串…让我们尝试自己实现引用相等,看看是否可以

null.Equals(null)
返回true:

using System;class Test{    static void Main()    {        Test x = null;        Console.WriteLine(x.Equals(null));    }    public override int GetHashCode()    {        return base.GetHashCode();    }    public override bool Equals(object other)    {        return other == this;    }}

与以前相同的过程-拆卸,更改

callvirt
call
,重新组装并观看打印
true

请注意,尽管另一个答案引用了这个C ++问题,但我们在这里更加曲解……因为我们非 虚拟地 调用 虚拟 方法。通常,即使C ++ /
CLI编译器也将

callvirt
用于虚拟方法。换句话说,我认为在这种特殊情况下,唯一的为
this
null的方法是手动编写IL。


编辑:我刚刚注意到了一些事情……我实际上并没有在我们的两个小示例程序中 调用正确的方法。这是第一种情况下的通话:

IL_0005:  call instance bool [mscorlib]System.String::Equals(string)

这是第二个电话:

IL_0005:  call instance bool [mscorlib]System.Object::Equals(object)

在第一种情况下,我 的意思 来调用

System.String::Equals(object)
,并在第二,我 的意思
打电话
Test::Equals(object)
。从中我们可以看到三件事:

  • 您需要小心过载。
  • C#编译器向虚拟方法的 声明者 发出调用,而不是对虚拟方法的最具体的 覆盖 。IIRC,VB的工作方式相反
  • object.Equals(object)
    很乐意比较一个空的“ this”引用

如果将控制台输出添加到C#覆盖中,您将看到区别-除非您更改IL以显式调用它,否则它将不会被调用,如下所示:

IL_0005:  call   instance bool Test::Equals(object)

所以,我们到了。空引用上实例方法的乐趣和滥用。

如果你走到今天这一步,你可能也想看看我的博客文章约值类型如何 可以
声明参数构造函数 …在IL。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/465230.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号