Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么不';是否自动初始化未分配的局部变量?_C#_.net_Variables_Compiler Construction_Initialization - Fatal编程技术网

C# 为什么不';是否自动初始化未分配的局部变量?

C# 为什么不';是否自动初始化未分配的局部变量?,c#,.net,variables,compiler-construction,initialization,C#,.net,Variables,Compiler Construction,Initialization,似乎没有办法在代码中包含未分配的局部变量或检查它们,因为编译器会抛出未分配局部变量的使用错误 为什么编译器在编译时不对这些变量使用default(T) 即使对值类型很难执行,在这种情况下,引用类型也可以很容易地初始化为null,对吗 下面是一些测试代码: public void Test ( ) { int x; string s; if ( x == 5 ) Console.WriteLine ( 5 ); if ( s != null )

似乎没有办法在代码中包含未分配的局部变量或检查它们,因为编译器会抛出
未分配局部变量的使用
错误

为什么编译器在编译时不对这些变量使用
default(T)

即使对值类型很难执行,在这种情况下,引用类型也可以很容易地初始化为
null
,对吗

下面是一些测试代码:

public void Test ( )
{
    int x;
    string s;

    if ( x == 5 )
        Console.WriteLine ( 5 );

    if ( s != null )
        Console.WriteLine ( "s" );
}
返回:

Use of unassigned local variable 'x'
Use of unassigned local variable 's'
更新:

对于那些有充分理由声称这是不允许的人,为什么在班级级别上允许这样做

public class C
{
    public int X;
    public string S;

    public void Print ( )
    {
        Console.WriteLine ( X );
        Console.WriteLine ( S );
    }
}
这段代码编译得非常好


为什么在类级别上而不是在方法级别上使用是可以的?

因为您希望在其中包含什么?你希望x默认为零,我希望它是5

如果他们将0分配给int(s),而全世界都开始这样假设,那么在某个时候它们将变为-1,这将破坏全球范围内的许多应用程序

在VB6中,我认为默认情况下,变量被分配给某个对象,但它并没有看上去那么好

当你使用C++或C++时,你用你想要的而不是编译器来分配值。

< P> C是一个“成功的”语言。p>
这是一个设计决策,因为该语言完全能够允许您使用未明确指定的局部变量。然而,这类变量的使用通常是错误的,代码路径由于某种原因没有设置值。为避免此类错误,编译器要求在使用之前分配所有局部变量。

通过采纳您的建议,将引用类型初始化为null,而不是当前行为(错误代码导致编译时错误),当您取消引用未初始化的变量时,将出现运行时错误。这真的是你想要的吗?

我知道你已经更新了你的问题,所以我会更新我的答案。您的问题有两部分,一部分与
局部变量相关,另一部分与类实例上的
实例变量相关。然而,首先,这实际上不是一个编译器设计决策,而是一个语言设计决策

第12.3.1/12.3.2节

局部变量 我们知道为什么可以定义变量而不给它赋值。一个原因,一个类似的例子:

int x;
// do stuff
x = 5;  // Wow, I can initialize it later!
Console.WriteLine(x);
该标准定义了为什么这是有效代码。现在,我不是C#设计团队的成员,但是他们为什么不为您自动初始化代码是很有道理的(除了性能方面的问题,当您实际上不希望自动初始化代码时)

假设上面的代码是您的意图,但是您忘记初始化
x=5。如果编译器已经为您自动初始化了变量,那么代码将进行编译,但它不会像您期望的那样执行任何操作

虽然这是一个微不足道的例子,但这是语言设计者做出的一个非常好的设计决定,因为它可以避免许多试图找出某些东西为什么不能按预期工作的头疼问题

作为旁注,我想不出你为什么要定义代码而不给它赋值,或者使用默认值(在任何情况下),对我来说,这可能是一个bug,我相信这是编译器设计者可能已经确定的

类实例变量 类级成员由最初指定的标准定义。事实上,公平地说,那些在
catch
foreach
using
语句中声明的局部变量之外的局部变量最初是未赋值的。实际上,这是一个标准问题,而不是编译器问题

如果我试着猜测为什么类实例的实例变量会出现这种情况,我会说这与如何在堆上分配内存有关,因为类就是在堆上分配的。当一个类被分配到堆上时,它的所有成员都必须被初始化并与之一起分配到堆上。它不仅可以在类成员中执行,也可以在局部变量中执行,它必须以这种方式执行。它们不能不被分配

1为什么编译器不允许使用未初始化的变量

因为这会促进良好的编程

2为什么编译器允许使用未初始化的类成员


因为不可能精确地跟踪它

考虑以下代码:

void blah(IDictionary<int,int> dict)
{
  for (int i=0; i<10; i++)
  {
    if ((i & 11) != 0)
    {
        int j;
        dict.TryGetValue(i, out j);
        System.Diagnostics.Debug.Print("{0}",j);
        j++;
    }
  }
}
void blah(字典目录)
{

对于(int i=0;编译器想要编译器想要的东西。我认为这是一个设计决策,而不仅仅是一个像C/C++那样的程序。你更喜欢编译时错误还是(运行时)当您忘记初始化引用类型的变量时出现空指针异常?也许编译器鼓励您使用良好的编码实践。CLR实际上会将该变量初始化为默认值(T)在VB.NET或C++ +CLI中依赖默认值是可能的,但是在C++语言中,语言设计者选择使它成为一个“很可能是一个错误”的错误。我明白你的意思,但你为什么不抱怨这种行为存在于类级别?而且如果他们使用0作为默认值,以后就不能将其更改为-1。同样的原因是,他们不会因为中断问题而更改以前做的很多事情。非堆栈变量保证初始化为ver二进制零表示给定类型(通常为0,null,…)。如果您没有初始化一个变量,并且知道编译器将为您初始化它为null,那么您就不会有运行时null ref异常,而不是将它初始化为null,然后忘记检查它。@JoanVenge