12

我在一个类中定义了以下方法:

public bool LogOff(string sessionId)
{
   int res;
   // Some non related code here..
   if (res == 1)
   {
      return true;
   }
   return false;
}

对我来说奇怪的是,我在 IF 子句上从 Visual Studio(我确实安装了 ReSharper)收到“本地变量在访问之前可能未初始化”错误。为什么当“res”是一个值类型并且应该默认为0时会出现这种情况?我应该指出,如果我专门将 res 的值设置为 0,那么一切正常。

我在这里想念什么?我认为这些是编程的基础知识,但显然我不熟悉这些基础知识......

4

5 回答 5

13

“为什么 C# 以这种方式工作”的答案总是“因为这是规范中的内容”。C# 语言规范的第 5.3.2 节列出了最初未分配的变量:

  • 最初未分配的结构变量的实例变量。
  • 输出参数,包括 struct 实例构造函数的 this 变量。
  • 局部变量,在 catch 子句或 foreach 语句中声明的变量除外。

至于为什么这是一个错误,第 5.3 节指出

必须在获得其值的每个位置明确分配一个变量。

如果将值初始化为int res = new int();,您将获得默认值零。其他答案中提到了更常见的方法,即明确将其设置为零。依赖默认值只会降低代码的可读性,并没有真正的优势。

于 2013-06-18T18:09:41.623 回答
9

为什么当“res”是一个值类型并且应该默认为0时会出现这种情况?

即使成员字段中的值默认为 0,本地人也需要显式设置该值。编译器会警告您正在使用它而不初始化它,因为这可能是一个错误。

虽然从逻辑的角度来看,这种“技术上”可以使用零初始化默认值,但从现实世界的角度来看,您在检查它之前从未设置过该值的事实是 1)无用(if永远不会是真的) 或 2) 错误(您打算设置值,但发生了一些变化)。

在任何一种情况下,都会有一个警告来帮助您防止任何一种情况意外发生。

我应该指出,如果我专门将 res 的值设置为 0,那么一切正常。

当您执行此操作时,您专门提供了一个值,因此编译器不再警告您。

于 2013-06-18T17:50:58.180 回答
2

C# 要求在使用之前初始化所有变量。对于像这样的局部变量,您需要显式初始化它们。结构或类中的字段不需要显式初始化,因为它们接收默认值作为对象构造的一部分。

所以在这里,你只需要做

int res = 0;

一切都会好起来的。

于 2013-06-18T17:56:08.253 回答
1

问题是 C# 不保证未初始化的值是 0。根据语言规范,不得使用未初始化的变量,因为 C# 旨在防止您做明显的坏事。

一些其他语言(特别是 C 和 C++)允许这样的主要原因是编译器编写者需要额外的工作来检测和标记这种情况。

编辑:是 C# 语言规范的相关部分:

于 2013-06-18T17:51:02.313 回答
0

默认初始化适用于类/结构成员,此处不适用,因为 res 是局部变量;作为变量,而不是数据成员,“使用前需要初始化”适用。

于 2013-06-18T18:03:26.873 回答