以下代码是非法的:
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 变量的方式可以被初始化,它的实际用途是什么(除了我在问题的第一部分中解释的不一致之外)
答案 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; } }
}