由于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的发布模式下,它会抛出InvalidProgramException。 (在调试模式下,它可以正常工作)

在VS2010 Beta 2中,它没有编译(我没试过Beta 1);我学到了很难的方法

在纯C#中有没有其他方法可以使 this == null

有帮助吗?

解决方案

此观察结果已在另一个发布在StackOverflow上问题今天早些时候。

Marc 对该问题的答案很好表明根据规范(第7.5.7节),你不应该能够在该上下文中访问 this ,并且在C#3.0编译器中执行此操作的能力是一个错误。 C#4.0编译器根据规范正常运行(即使在Beta 1中,这是一个编译时错误):

  

<强>&#167; 7.5.7此访问

     

this-access 由保留字 this 组成。

     

此访问:

this
     

只允许在实例构造函数,实例方法或实例访问器的中使用 this-access

其他提示

Debug模式二进制文件的原始反编译(没有优化的Reflector)是:

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
   .locals init (
        [0] string CS$1
    L_0000: ldloc.0 
    L_0001: call instance string CompilerBug.Program/Derived::CheckNull()
    L_0006: ret 
) 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
; CS$1<*> = CS$1<*>.CheckNull(); Label_0009: return CS$1<*>; } private string CheckNull() { string CS$1<*>; CS$1<*> = "Am I null? " + ((bool) (this == null)); Label_0017: return CS$1<*>; } }

CompilerGenerated方法没有意义;如果您查看IL(下面),它会在null 字符串(!)上调用该方法。

<*>

在Release模式下,局部变量被优化掉,因此它会尝试将不存在的变量推送到堆栈。

<*>

(反射器在转换为C#时崩溃)


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

我有那个! (并得到证据)

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

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

仅仅因为你可以做坏事并不意味着当你得到它时, bug

我可能错了,但我很确定你的对象是 null 还是永远不会出现 this 的情况。

例如,您如何调用 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 [&quot; UserID&quot;],147);

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top