考虑以下代码:
public unsafe struct MyStruct
{
public fixed int Nums[128];
}
private static void DoSomething()
{
MyStruct s = new MyStruct();
unsafe
{
int val = s.Nums[23];
Console.WriteLine(val.ToString()); //Is this guaranteed to be "0"?
}
}
在这种情况下,是否保证在创建新的MyStruct
时,每个索引处的Nums
的值都为0?
在我自己的测试中,它看起来确实被初始化为默认值,但我问是因为它是unsafe
。
好吧,这需要一些时间才能找到,
然而,从语言规范3.0版
从18.7固定大小缓冲区开始并继续
有几个参考文献,最著名的
固定大小的缓冲区不接受明确的赋值检查(§5.3(,并且为了结构类型变量的确定赋值检查。当固定大小缓冲区成员的最外层包含结构变量静态变量、类实例的实例变量或数组元素,固定大小缓冲区的元素会自动初始化为默认值(§5.2(。在所有其他情况下固定大小缓冲区的初始内容未定义
现在,我自己还没有测试过,这些规范的语言有时很难完全理解。然而,这似乎与的发现一致
除了TheGeneral在这里发布的内容外,我在更新的规范中找不到任何更新或额外的指导。
从18.7固定大小的缓冲区开始,并继续进一步的
有几个参考文献,最著名的
固定大小的缓冲区不接受明确的分配检查(§5.3(,并且为了结构类型变量的确定赋值检查。当固定大小缓冲区成员的最外层包含结构变量静态变量、类实例的实例变量或数组元素,固定大小缓冲区的元素会自动初始化为默认值(§5.2(。在所有其他情况下固定大小缓冲区的初始内容未定义。
也就是说,我可以确认至少有一种情况——在.NET 6中——固定大小缓冲区中的数据可能无法初始化。我刚刚遇到了这个问题,在我的例子中,我的结构存储在一个for循环中声明和new
-ed的变量中。在第一次迭代中,结构的内部固定大小的缓冲区如预期的那样清晰;然而,在随后的迭代中,每次额外的new
ing都毫无作用,所以数据积累了起来,我的几个测试都失败了。
我找到了两种方法来通过测试:
- 将一个
Clear
方法添加到我的结构中,并在每个new
之后调用它,或者将它添加到结构的无参数构造函数中 - 从我的结构中删除无参数构造函数,它的存在显然阻止了缓冲区被清除
当规范中有未定义的内容时,我会密切关注,不要冒险。如果你想让数据清楚,你应该确保自己清除它。否则,您永远无法确定您的代码在任何情况下都能工作,或者更新后其行为不会发生显著变化。