【问题标题】:Why do I have to assign a value to an int in C# when defaults to 0?为什么我必须在默认为 0 时为 C# 中的 int 赋值?
【发布时间】:2010-11-28 05:58:57
【问题描述】:

这行得通:

class MyClass
{
    int a;

    public MyClass()
    {
        int b = a;
    }
}

但这会导致编译器错误(“使用未分配的局部变量'a'”):

class MyClass
{
    public MyClass()
    {
        int a;
        int b = a;
    }
}

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

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

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

【问题讨论】:

    标签: c# initialization default int default-value


    【解决方案1】:

    整数不是默认为 0 吗?

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

    【讨论】:

    【解决方案2】:

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

    本质上,在创建对象(或初始化结构)时,它会将内存归零(或者在非默认结构 ctor 的情况下,强制您手动初始化所​​有内容)。但是,变量非常常见(在每种方法中),它不希望始终将堆栈归零的开销。相反,它会强制您指明初始值。

    【讨论】:

    • 另一种选择是不初始化变量(并将其保留为当前存在于堆栈中的垃圾)。但是由于 C# 有时会超出使您的代码更加安全的措施,因此编译器坚持认为该变量无论如何都会被初始化为某个默认值(即使它不是必需的)
    • 这也使编译器能够优化局部变量的重用。例如: "for(...){ int j;... } for(...){ int k;... }" -- 当 k 出现时,编译器可以重新使用分配给 j 的空间,因为它们从不重叠。如果在使用 k 之前必须对其进行初始化,那么我们就不必担心将 j 的旧值留在其中。
    • 从 C# 的角度来看,这就是它的全部内容,但 CLR 要求不同。如果您想要可验证的代码(如 C# 默认生成的那样),您的局部变量也必须进行零初始化 - 在您的 C# HelloWorld 应用程序上启动 ildasm 并自行检查!当然,当 JIT 看到该变量立即被赋予不同的值时,它可以(并且确实)忽略初始化,但这是另一回事(并且在阶梯上的抽象级别降低了)。
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

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

      例如

      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
         }
      }
      

      【讨论】:

      • @Marc:是的。我想说的是 - 在类级别,您不能在与声明字段不同的行上为字段分配值。
      【解决方案5】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-09-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多