代码之家  ›  专栏  ›  技术社区  ›  Selman Genç

为什么C编译器强制构造函数中所有值类型字段的显式初始化?

  •  2
  • Selman Genç  · 技术社区  · 6 年前

    对于一个类,这是可以的:

    class Point
    {
        private int _x, _y;
    
        public Point(int x)
        {
            _x = x;
        }
    }
    

    但是如果我使用值类型,编译器会抱怨 _y 未初始化:

    struct Point
    {
        private int _x, _y;
    
        public Point(int x)
        {
            _x = x;
        }
    }
    

    我在想到底是怎么回事 理论基础 幕后黑手?为什么编译器不能初始化 0 当没有提供显式构造函数时会发生什么?

    3 回复  |  直到 6 年前
        1
  •  6
  •   Marc Gravell    6 年前

    为什么?因为语言规范(ECMA 334 16.4.9)这样说:

    在明确指定所构造结构的所有字段之前,不能调用实例函数成员(包括属性X和Y的set访问器)。但是,请注意,如果Point是类而不是结构,则允许使用实例构造函数实现。

    至于为什么语言规范要求它。。。可能是为了通过避免不必要的擦除和覆盖,使结构赋值尽可能便宜。

        2
  •  0
  •   Gauravsa    6 年前

    这可以在C规范的第5.3.1节中找到,该节规定最初分配了以下类型的变量。目的清单如下:

    • 类实例的实例变量。
    • 值参数。
    • 参考参数。

    以下值将为0:

    Point p = new Point(10);
    Console.WriteLine(p.y);
    

    这本身不会编译:

    int temp;
    Console.WriteLine(temp);
    

    Jon Skeet有一个很好的答案:

    Non initialized variable in C#

        3
  •  0
  •   Poul Bak    6 年前

    您可以这样做,现在所有值类型都已初始化:

    struct Point
    {
        private int _x, _y;
    
        public Point(int x)
            :this()
        {
            _x = x;
        }
    }
    

    注意,我只是调用了默认构造函数。

    我认为这种行为的原因是,如果您调用默认构造函数或使用参数指定构造函数中的所有字段,它表明您知道自己在做什么,而不是意外地将某些字段初始化为默认值。