【问题标题】:Fixing the 'Use of unassigned local variable' with a null assignment. Why?使用空分配修复“使用未分配的局部变量”。为什么?
【发布时间】:2011-09-06 23:21:24
【问题描述】:

这样一段代码,编译器会报c.MyProperty

MyClass c;

try { throw new Exception(); }
catch (Exception) { }

c.MyProperty = 2; // "Use of unassigned local variable 'c'".

但是,如果您在初始化时将 null 分配给 c,它不会报错:

MyClass c = null;

try { throw new Exception(); }
catch (Exception) { }

c.MyProperty = 2; // no complains this time.

那么,为什么会这样呢?如果c 没有分配null 并且编译器假设允许它,那么c.MyProperty 不会抛出相同的异常,对象引用未设置为对象的实例

【问题讨论】:

  • 嗯,这很有趣,我的猜测是虽然这段代码(第二版)仍然会在运行时抛出异常。这可能只是一个 Visual Studio 问题,没有获得空分配- 只是猜测?
  • 问得非常漂亮优雅的问题

标签: c# exception variable-assignment


【解决方案1】:

当您将null 分配给变量时,您是在告诉编译器退出,因为您比他更了解,所以他不应该抱怨这一点。

这可能是因为分配null 被认为暗示了开发人员的明确操作。

【讨论】:

  • 虽然这让我发笑,但我仍然没有接近答案。
  • @Andreas:这是实际的答案,这就是允许的原因。 C# 会让你有意在脚下开枪。它只是不会让您无意这样做。
  • 虽然我回答的方式是为了给我的观点增添一些幽默感,但我真的认为这可能是编译器停止抱怨的原因,所以它是一个有效的答案,即使它在最后不是正确的一个。
  • 我一直认为编译器是她的。
【解决方案2】:

这样想,编译器并不是告诉你它会抛出一个空引用,因此它不能编译,而是编译所需的条件之一不满足,即必须明确分配。

根据规范,null 是一个 c# 文字:“null-literal 可以隐式转换为引用类型或可空类型”

以及在分配方面:(取自规范)

引用自规范的开始

5.3.3 确定明确分配的精确规则 为了确定每个使用的变量都被明确赋值,编译器必须使用与本节中描述的过程等效的过程。

编译器处理具有一个或多个初始未分配变量的每个函数成员的主体。对于每个最初未赋值的变量 v,编译器会在函数成员中的以下每个点确定 v 的明确赋值状态:

· 在每个语句的开头

· 在每个语句的结束点(第 8.1 节)

· 在将控制权转移到另一个语句或语句的终点的每条弧上

· 在每个表达式的开头

· 在每个表达式的末尾

引用结束

因此,尽管 null 实际上并不指向内存中的对象,但它确实满足了被明确分配的要求,这就是编译器允许它的原因。

【讨论】:

    【解决方案3】:

    这是因为 C# 语言规范 v. 4.0 第 1.6.6.2 节“方法体和局部变量”规定如下:

    方法体可以声明特定于方法调用的变量。这样的变量称为局部变量。

    [跳过]

    C# 需要一个局部变量明确赋值才能获得它的值。

    正如 Binary Warrier 巧妙地指出的那样,这是为了避免让你在脚上开枪。

    【讨论】:

      【解决方案4】:

      此异常的原因是您没有为变量分配默认值,例如

      if (Request.Files != null  && Request.Files.Count > 0)
                  {
                       Image = Request.Files.AllKeys[0];
                  }
      var stream  = new FileStream(Image,FileMode.Open);
      

      现在 Image 变量会给出编译错误

      使用未赋值的局部变量'Image'

      这是因为有可能条件变为真并且控制永远不会知道 Image 变量是什么。所以要么放置一个 else 块,要么如下分配一个默认值。

      string Image = "";
      if (Request.Files != null  && Request.Files.Count > 0)
                  {
                       Image = Request.Files.AllKeys[0];
                  }
      var stream  = new FileStream(Image,FileMode.Open);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-18
        • 2015-11-09
        • 2012-05-18
        • 1970-01-01
        • 2023-03-29
        相关资源
        最近更新 更多