9

检查此代码..

    string str;

    if (str.Contains("something.."))
    {
    }

编译器为此代码抛出此错误

使用未分配的局部变量“str”

为什么引用类型未初始化为 null ?

只是出于好奇想知道。

我也想知道下面的代码会发生什么。这个任务是如何工作的?

    string str = null;
4

4 回答 4

22

只有字段(在类级别声明的变量)会自动初始化:

  • 值类型被初始化为其默认值。
  • 引用类型被初始化为null引用。

您要声明的是方法内的“局部变量”。无论是值类型还是引用类型,局部变量都不会自动初始化。

我也想知道下面的代码会发生什么。这个任务是如何工作的?

这个赋值用一个ldnull指令后跟一个stloc指令(如果它没有被优化,当然)初始化具有空值的局部变量,更重要的是,满足编译器的数据流分析规则进行明确的赋值。C# 规范定义了一个称为明确赋值的概念,可确保在首次使用之前分配变量。

于 2010-01-06T13:32:51.853 回答
7

C# 语言要求在读取所有变量之前明确分配它们。局部变量最初被认为是未赋值的,而字段、数组元素等被认为是最初赋值给它们的默认值。(对于引用类型,它为 null。)

没有技术原因我们不能将局部变量视为最初分配给它们的默认值并丢弃所有明确的分配检查。它存在是因为使用未分配的本地作为其默认值是 (1) 一种糟糕的编码习惯,以及 (2) 极有可能是令人讨厌的错误的来源。通过要求您在使用局部变量之前显式分配它们,我们可以防止用户使用不良做法,并消除您无需调试的一整类错误。

此外,请考虑以下事项:

while(whatever)
{
    int i;
    print(i);
    i = i + 1;
}

您是否希望 i 在循环的执行过程中保持其值,或者每次都将其初始化为零?通过强制您显式初始化它,问题变得毫无意义,这是一个没有区别的区别。

(此外,在上述情况下,还有一个小的潜在性能优化,因为编译器知道将清除内容,因此编译器可以重新使用该变量而无需生成代码来清除其内容。)

我不知道如何回答您的第二个问题,因为我不知道您所说的“工作”是什么意思。你能告诉我如何分配“int x = 123;” 作品?一旦我知道您所说的“有效”是什么意思,我就可以描述如何将 null 分配给引用类型的变量。

于 2010-01-06T14:53:06.837 回答
2

确实被初始化为null。编译器只是帮了你一个忙,不必调试你会得到的不可避免的 NullReferenceException。

于 2010-01-06T13:58:31.287 回答
-1

还要记住,对空字符串调用 Contains 会引发 NullReferenceException。

于 2010-01-06T13:34:19.773 回答