(this == null)在C#中!

由于在C#4中修复了一个错误,下面的程序打印为true 。 (在LINQPad中试用)

 void Main() { new Derived(); } class Base { public Base(Func<string> valueMaker) { Console.WriteLine(valueMaker()); } } class Derived : Base { string CheckNull() { return "Am I null? " + (this == null); } public Derived() : base(() => CheckNull()) { } } 

在VS2008的Release模式下,它会抛出一个InvalidProgramExceptionexception。 (在debugging模式下,它工作正常)

在VS2010 Beta 2中,它不能编译(我没有尝试Beta 1); 我了解到这一点很难

有没有其他的方式来使纯C#中的this == null

这个观察已经在今天早些时候的另一个问题的 StackOverflow上发布了。

Marc 对这个问题的很好的回答表明,按照规范(7.5.7节),你不应该能够在上下文中访问this ,而在C#3.0编译器中这样做的能力是一个bug。 C#4.0编译器根据规范正确运行(即使在Beta 1中,这也是一个编译时错误):

§7.5.7这个访问

这个访问由保留字this

此访问:

 this 

只能在实例构造函数,实例方法或实例访问器的中允许此访问

debugging模式二进制的原始反编译(Reflector with no optimizations)为:

 private class Derived : Program.Base { // Methods public Derived() { base..ctor(new Func<string>(Program.Derived.<.ctor>b__0)); return; } [CompilerGenerated] private static string <.ctor>b__0() { string CS$1$0000; CS$1$0000 = CS$1$0000.CheckNull(); Label_0009: return CS$1$0000; } private string CheckNull() { string CS$1$0000; CS$1$0000 = "Am I null? " + ((bool) (this == null)); Label_0017: return CS$1$0000; } } 

CompilerGenerated方法没有意义; 如果你看IL(下面),它将调用空string (!)上的方法。

  .locals init ( [0] string CS$1$0000) L_0000: ldloc.0 L_0001: call instance string CompilerBug.Program/Derived::CheckNull() L_0006: stloc.0 L_0007: br.s L_0009 L_0009: ldloc.0 L_000a: ret 

在释放模式下,局部variables被优化掉了,所以它试图把一个不存在的variables推到堆栈上。

  L_0000: ldloc.0 L_0001: call instance string CompilerBug.Program/Derived::CheckNull() L_0006: ret 

(reflection器转换成C#时崩溃)


编辑 :有人(Eric Lippert?)知道为什么编译器发出ldloc

我已经有了! (也有certificate)

替代文字

这不是一个“错误”。 这是你滥用types系统。 你永远不应该将一个对当前实例( this )的引用传递给构造函数中的任何人。

我也可以通过在基类构造函数中调用一个虚拟方法来创build一个类似的“bug”。

只是因为你可以做一些坏事,并不意味着它是一个错误

我可能是错的,但我敢肯定,如果你的对象是null ,那永远不会是一个适用的场景。

例如,你将如何调用CheckNull

 Derived derived = null; Console.WriteLine(derived.CheckNull()); // this should throw a NullReferenceException 

不知道这是你在找什么

  public static T CheckForNull<T>(object primary, T Default) { try { if (primary != null && !(primary is DBNull)) return (T)Convert.ChangeType(primary, typeof(T)); else if (Default.GetType() == typeof(T)) return Default; } catch (Exception e) { throw new Exception("C:CFN.1 - " + e.Message + "Unexpected object type of " + primary.GetType().ToString() + " instead of " + typeof(T).ToString()); } return default(T); } 

例如:UserID = CheckForNull(Request.QueryString [“UserID”],147);