很少使用值类型初始化

时间:2011-06-22 09:07:35

标签: c# value-type

以下代码是非法的:

public struct MyStruct
{
    public MyStruct(int a, int b)
    {
        this.a = a;
        this.b = b;
    }

    public int a;
    public int b;
}

//now I want to cache for whatever reason the default value of MyStruct
MyStruct defaultValue;
...
if (foo != defaultValue) //use of unassigned variable...

应该做的事情显然是:

MyStruct defaultValue = default(MyStruct) //or new MyStruct();
...
if (foo != defaultValue) //compiler is happy

但是下面的 也是允许的(我不知道这件事偶然发现了):

MyStruct defaultValue;
defaultValue.a = 0;
defaultValue.b = 0;
...
if (foo != defaultValue) //legal

我想编译器会验证struct的所有字段都已初始化,因此允许编译此代码。我仍然觉得它与其他语言的工作原理相混淆。毕竟,你基本上是以C#的方式使用未分配的变量。

如果考虑以下代码,事情会变得更加混乱:

public struct MyStruct
{
    public MyStruct(int a, int b)
    {
        this.a = a;
        this.b = b;
        this.c = (a + b).ToString();
    }

    public int a;
    public int b;
    internal string c;
}

以下代码是非法的,因为在这种情况下,我们尚未分配所有可见字段:

MyStruct defaultValue;
defaultValue.a = 0;
defaultValue.b = 0;
...
if (foo != defaultValue) //use of unassigned variable...

可见是这里的关键词,因为如果要在引用的程序集中定义MyStruct,则c不是可见并且编译器不会抱怨,以前的代码完全有效。再次混淆。

请问somebdoy请解释为什么允许以这种方式初始化C#中的struct?为什么不完全禁止它,以便在处理语言中任何类型的价值时有更统一的经验?

编辑1 :我在上一个例子中犯了一个错误。仅当不可见字段为引用类型时,编译器才会满意。更令人困惑的是。这最后一个案例是编译器中的一个已知错误,还是有理由让它按照它的方式工作?

将最后一个示例更改为有效案例。

编辑2 :我仍然对值类型初始化的工作方式感到困惑。例如,为什么不允许以下内容:

struct MyStruct
{ 
    public int A { get; set; } //Auto-implemented property
    public int B { get; set; } //Auto-implemented property
}

MyStruct defaultValue;
defaultValue.A = 0;  //use of unassigned variable...
defaultValue.B = 0;

我看到它的方式,毫无疑问所有字段MyStruct都已初始化。我可以看到为什么如果属性不是自动实现就不允许这样做的原因,因为有可能设置者不保证所有字段都已设置。但是在自动实现的属性中,编译器知道,100%确定如果属性是(在编译器为您生成的所有代码之后)将设置字段。

最后,一个明显没有实际用途的小理论案例:

struct MyUselessStruct
{
}

MyUselessStruct defaultValue;
Console.WriteLine(defaultValue.ToString()); //hehe did I get away with using an unassigned variable?

那为什么不允许这样做:

Object object;
if (object == null) .... //use of unassigned variable

我发现两个案例的概念相似,我希望它们在C#中的工作方式相同。我仍然不明白为什么这种看似无用的区别 value-type 变量的方式可以被初始化,它的实际用途是什么(除了我在问题的第一部分中解释的不一致之外)

1 个答案:

答案 0 :(得分:5)

规范明确允许这个; ECMA334v4中的12.3

  
      
  • 如果结构类型变量的每个实例变量都被认为是明确赋值的,则它被认为是明确赋值的。
  •   

但是,可变结构 evil 。所以我强烈建议你不要这样做。

将字段设为私有,通过自定义构造函数设置它们,并通过get - 仅属性访问它们:

public struct MyStruct
{
    public MyStruct(int a, int b)
    {
        this.a = a;
        this.b = b;
    }
    public int A { get { return a; } }
    public int B { get { return b; } }
    private readonly int a, b;
    internal int C { get { return a + b; } }
}