Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/google-app-engine/4.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
当默认值为0时,为什么我必须在C#中为int赋值?_C#_Initialization_Default_Int_Default Value - Fatal编程技术网

当默认值为0时,为什么我必须在C#中为int赋值?

当默认值为0时,为什么我必须在C#中为int赋值?,c#,initialization,default,int,default-value,C#,Initialization,Default,Int,Default Value,这项工作: class MyClass { int a; public MyClass() { int b = a; } } 但这会导致编译器错误(“使用未分配的局部变量“a”): 据我所知,这是因为在第一个示例中,从技术上讲,编译器不知道“a”没有赋值。在后一个示例中,“a”是在本地定义的,因此易于跟踪 但为什么后一个例子不起作用 整数不是默认为0吗?这是编译器为“最佳实践”而强制执行的吗。还是有其他原因 整数不是默认为0吗 当它们是类的数据

这项工作:

class MyClass
{
    int a;

    public MyClass()
    {
        int b = a;
    }
}
但这会导致编译器错误(“使用未分配的局部变量“a”):

据我所知,这是因为在第一个示例中,从技术上讲,编译器不知道“a”没有赋值。在后一个示例中,“a”是在本地定义的,因此易于跟踪

但为什么后一个例子不起作用

整数不是默认为0吗?这是编译器为“最佳实践”而强制执行的吗。还是有其他原因

整数不是默认为0吗


当它们是类的数据成员时会这样做,但当它们是局部变量时不会这样做:局部变量在使用之前需要显式初始化,因此编译器会出错。

在第一个示例中,它是一个字段。字段自动默认为0/false/null。在第二个示例中,它是一个变量。变量不是默认的,在使用之前必须有“明确的赋值”


本质上,在创建对象(或初始化结构)时,它会将内存归零(或者在非默认结构的情况下,强制您手动初始化所有内容)。然而,变量是如此的常见(在每个方法中),它不需要一直将堆栈归零的开销。相反,它会强制您指示初始值。

当您实例化一个类的新实例时,对象需要的所有内存都是“归零”的int被设置为0,字符串被设置为null等。这是为了避免C(++)中可能出现的许多奇怪的内存错误和攻击。不幸的是,这也有一个小的处理成本,所以当您创建一个局部变量时,语言假定您将很快自己设置该值,而不必麻烦将其归零以减少所需指令的总数。为了抵消使用未设置内存的风险,这将引入编译器检查,以确保在允许您使用变量之前已设置值。

这可能是因为在类级别声明的变量不能在同一范围内赋值(声明时除外)

e、 g

鉴于

class Test
{
   void test()
   {
     int a;
     int b = a;

     a = 20; // this is allowed
   }
}

据我所知,当我们在类中声明一个变量并创建一个对象时,默认构造函数会初始化该变量,因此不需要初始化类变量。但是对于类中的方法,没有构造函数或任何东西来初始化这些变量,因此我们不能在方法中分配未初始化的变量。

:“局部变量不会自动初始化,因此没有默认值。为了确定赋值检查的目的,局部变量被认为是初始未赋值的。”另一个选项是不初始化变量(并将其保留为堆栈上当前存在的垃圾).但是,由于C#有时超出了使代码更加安全的措施,编译器坚持无论如何都要将变量初始化为某个默认值(即使它不是必需的),这也使编译器能够优化局部变量的重用。例如:“for(…){int j;…}for(…){int k;…}“--当k出现时,编译器可以重新使用分配给j的空间,因为它们从不重叠。如果在使用k之前必须对其进行初始化,那么我们就不必担心将以前的j值留在那里。从C#的角度来看,这就是它的全部内容,但是CLR要求有所不同。如果你想要可验证的代码(正如C#默认生成的那样),你的局部变量也必须初始化为零-在你的C#HelloWorld应用程序上启动
ildasm
,然后自己检查!当然,当JIT看到变量立即被分配了不同的值时,它可以(并且确实)避免初始化,但这是另一回事(而且抽象程度更低)。@Marc:是的。我想说的是——在类级别上,您不能将一个值分配给字段,而不是它的声明。
class Test
{
   int a;

   a = 0; // this is not allowed at class level & hence a initialized to default
}
class Test
{
   void test()
   {
     int a;
     int b = a;

     a = 20; // this is allowed
   }
}