【问题标题】:Difference between null and not initialized?null 和未初始化的区别?
【发布时间】:2011-02-23 20:23:58
【问题描述】:

当我用 C# 编写以下代码时:

SqlCeCommand command;
try
{
    // The command used to affect the data
    command = new SqlCeCommand
                  { 
                     // init code removed for brevity
                  };

    // Do stuff 
    // Do more stuff
}
finally
{
    if (command != null)
        command.Dispose();
}

Resharper 抱怨我对命令的检查!= null。它表示该命令可能未分配(因为它可能会在构造过程中失败并仍然命中 try 块)。

所以我把命令的声明改成SqlCeCommand command = null;,大家都很开心。

但我想知道有什么区别?

为什么它不默认为空? 含义: C# 不仅将局部变量默认为 null,对 C# 有何好处?

【问题讨论】:

  • 因为 C++ 似乎是唯一“真正”的答案。

标签: c# null initialization


【解决方案1】:

局部变量没有默认值。语言的一部分。

【讨论】:

  • 但是为什么呢?为什么不让它们默认为空?通过要求分配可以获得什么?
  • 就像mrz说的——是为了保护程序员。同样的规则也存在于其他语言(如 Java)中。编译器在发现可能的执行路径导致在为其分配确定值之前使用局部变量后抱怨此规则已使我被此规则保存。事实证明,这几乎总是由于我的错误。如果局部变量有默认值,这种检查是不可能的。 (顺便说一句,您为什么要对正确答案投反对票?如果您不喜欢该消息,为什么要伤害信使?)
  • 我没有对这个问题投过一个反对票(而且反对票通常很少)。我不会仅仅因为它是我不想听到的东西而对 stackoverflow 答案投反对票。
  • @Vaccano - 我很抱歉。有人似乎对您提出反对意见的每个答案都投了反对票。我认为这是你的反对票,这是一个毫无根据的结论。
【解决方案2】:

好吧,如果您希望它为空,那么您需要告诉它。这是为了捕捉错误。编译器和 ReSharper 等实用程序会搜索所有执行路径,并确保变量在使用之前已初始化。这是为了捕捉常见的编码错误。所以不可能有额外的“甚至不是空”值,它只是编译器(或其他)所做的分析来帮助你。

类成员被初始化为默认值(例如,引用类型为 null),因此您可以得到您期望的行为。

【讨论】:

  • 我想说这也是一种优化。在你将它设置为另一个值之前将它分配给某个东西只是浪费指令。
  • 好吧,如果编译器不是很糟糕,它应该检测到这一点,甚至永远不会进行初始分配。
【解决方案3】:

这与 C# 帮助确保代码正确性的目标有关。在类声明中(与局部变量相反),成员具有隐式值,因此您不必在声明或类构造函数中显式设置它们。然而,在函数/方法的上下文中,C# 会跟踪变量是否已显式设置,这样它就可以像你所看到的那样向你发出警告......这是一个设计决策在语言方面。

【讨论】:

【解决方案4】:

您可以使用为您调用Disposeusing 构造编写等效但更紧凑的代码:

using (var command = new SqlCeCommand
       { 
           // init code removed for brevity
       })
{

    // Do stuff 
    // Do more stuff
}

您无需担心处置或检查无效性。

【讨论】:

    【解决方案5】:

    类字段成员被默认(值类型取决于其类型,引用类型为 null)但局部变量不会。

    // Example 1:
    SomeClass someObject;
    if(x == y)
    {
        someObject = new SomeClass();
    }
    someObject.someMethod();   //Error since it may not execute the if statements
    
    // Example 2
    SomeClass someObject;
    someObject = new SomeClass();
    someObject.someMethod();   //No Error
    

    编辑:这是为了避免导致程序意外关闭(由于空指针)的 C++ 运行时错误。

    P.S:当我谈论 C# 规范时,你可能不会对我投反对票(我没有制定 C# 规范,不过我为这种避免感到高兴)。

    【讨论】:

    • 但是为什么呢?为什么不要求两者都初始化或都不初始化?
    • 我没有投反对票! (而且我刚刚投了赞成票)事实上,你的 C++ 参考是我所听到的最好的真正理由(尽管我真的不明白为什么 C++ 在 C# 中所做的事情很重要,除非它是一个刚刚被继承下来的约定)跨度>
    • @Vaccano 我在某处读过 C# => C++++,我知道它有很大不同并且功能更强大,但它会是一个很好的路线图,可以抛弃旧的编程语言漂亮的东西。
    【解决方案6】:

    您可以测试 null,因为 null 是一个值。 未初始化意味着没有价值,因此您无法对其进行测试。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-16
      • 1970-01-01
      • 2011-10-28
      相关资源
      最近更新 更多