【问题标题】:Explicit assignment of null显式分配 null
【发布时间】:2010-10-08 11:54:11
【问题描述】:
string s1;
string s2 = null;

if (s1 == null) // compile error
if (s2 == null) // ok

我真的不明白为什么需要显式分配。空变量和未赋值变量有什么区别?我总是假设未分配的变量无论如何都被运行时/编译器简单地分配为 null 。如果它们不为空,那么它们是什么?

【问题讨论】:

    标签: c#


    【解决方案1】:

    未分配的成员会自动初始化为其默认值(在string 的情况下为空引用)。

    未分配的局部变量未分配任何值,尝试访问可能未分配的变量将导致编译错误。

    【讨论】:

    • 值得注意的是,编译器确定局部变量没有被赋值相对容易,而成员变量或全局变量则非常困难。因此,行为上的差异。
    • 没有分配给 null。可以将某些内容分配为 null :)
    • @martineau:C# 中没有全局变量
    • @Winston:不仅非常困难,而且通常是不可能的。 :)(参见停止问题)
    • 顺便说一句,发生这种情况的原因是因为编译器很有帮助。此错误消息允许编译器帮助您找到一大类您可能会错过的错误。吸收——永远不要在第一次通过时将变量初始化为空。在没有它的情况下编写代码,看看你是否真的需要它,如果你不能轻松地重写你的代码以不需要分配,那么继续添加它,但永远不要养成自动执行它的习惯。
    【解决方案2】:

    需要显式赋值的原因很简单。当人们尝试使用未分配/未初始化的变量时,这通常是错误的来源。

    通过强制开发人员这样做,它消除了开发人员忘记初始化变量时发生的错误。通过初始化它,您可以控制它。

    这真是一件好事!我不知道在某些脚本语言中我多久出现一次未初始化或未定义的变量,这需要很长时间才能找到^^

    【讨论】:

    • 在 Python 中,您必须分配一个初始值。你不能只说a,你必须说a = None 什么的。在 JS 中,您可以执行 var x;,但这意味着 var x = undefined;,它仍在为其分配一个值。我看不出这种 Java 区别有什么帮助。如果要防止未初始化的变量,请不要在语言中使用null(如 Haskell)。
    • @Claudiu 这是一件坏事,不是好事。让您养成初始化停止路径查找错误检查的习惯——例如使用 Java/C# int x;if(condA)x=5;else if(condB)x=7;打印 "x="+x;会给你一个错误,因为它意识到你在使用它之前没有初始化 x (即使在两种情况下你确实初始化了它。如果你总是初始化变量,那么系统就不能做这种检查你。
    【解决方案3】:
    1. 如果你有一个未分配的本地值,你很可能会做一些愚蠢的事情。更糟糕的是,你正在做聪明人一时冲动可以做的蠢事(每个人每天都在做蠢事)。

    2. 与导致警告的某些事情不同,在特殊情况下使用未分配的值没有可能的优势。

    3. 允许未分配的本地或假设特定值之间的唯一成本差异是几次击键(通常= null;最多可能是= default(SomeType);

    禁止这样的结构是利多害少。没有技术上的理由表明该语言不能被设计为允许未分配的本地人使用,但禁止的好处大于坏处。

    【讨论】:

      【解决方案4】:

      查看规范:5.3 Definite assignment

      在以下情况下需要明确分配:
      变量必须在每个获取其值的位置明确分配。

      s1 和 s2 最初是未分配的 (5.3.1 Initially assigned variables),但只有 s2 被认为已在给定位置明确分配, [因为] 通向该位置的所有可能执行路径都包含以下至少一项:

      • 一个简单的赋值(第 7.13.1 节),其中变量是左操作数。

      如您所见,null 在这种情况下是无关紧要的。重要的是赋值本身,而不是值。

      【讨论】:

        【解决方案5】:

        C# 编译器不允许使用未初始化的局部变量。最初未赋值的变量没有初始值。

        【讨论】:

        • 那么“no value”和null有什么区别?
        • @fearofawhackplanet: No value 是当变量是 declared 而不是 defined 时。不存在的东西是没有价值的。当你定义变量时,它的默认值或赋值可以是 null。
        • @Mike:它确实存在。在某处为该变量留出了空间。 C# 有一个选择:默认分配该空间 null 并继续使用它,或者强制您自己将 null 放在那里。我认为后一种方式没有什么好处。
        • C# 不允许使用未分配的 local 变量。字段、数组元素、形式参数、指针解引用等等,都被认为是“一出生就赋值”。
        • @Eric,谢谢,我在回答中添加了形容词 local
        【解决方案6】:

        从未被赋值的变量拥有一个undefined值。在最坏的情况下,这实际上发生在大多数语言中,这意味着它可以具有 any 值,因为它解决了一些内存,这很可能以前已用于其他目的,甚至可能由另一个程序。一些语言确保所有变量都初始化为一些合理的默认值。然而这可能只是一种浪费,因为最终它是一个写操作,这可能不是必需的,默认情况下这样做是浪费时间。

        【讨论】:

        • 我怀疑 C# 无论如何都会把一些价值放在那里。我知道 C 没有,但不确定 C#
        【解决方案7】:

        要记住的一件事是作用域将在其中发挥作用。如果您将 S1 定义为类变量,然后在函数中对其进行测试,编译器将不会停止并且代码将运行良好。原因是类在实例化的时候就初始化了变量。

        在方法内部移动,你很有可能在初始化变量之前测试变量时忘记了一些东西。

        我看到的另一个警告是字符串的默认值是什么? (更重要的是,这在一个不会改变的规范中?请记住,空字符串与分配为空的字符串不同。有一种解决方法,因为您可以改为使用 string.IsNullOrEmpty(S1) 进行测试而是。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-01-26
          • 2017-03-25
          • 1970-01-01
          • 2011-06-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多