使用固定大小的数组创建不安全的结构时,数组是否初始化为默认值



考虑以下代码:

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的变量中。在第一次迭代中,结构的内部固定大小的缓冲区如预期的那样清晰;然而,在随后的迭代中,每次额外的newing都毫无作用,所以数据积累了起来,我的几个测试都失败了。

我找到了两种方法来通过测试:

  1. 将一个Clear方法添加到我的结构中,并在每个new之后调用它,或者将它添加到结构的无参数构造函数中
  2. 从我的结构中删除无参数构造函数,它的存在显然阻止了缓冲区被清除

当规范中有未定义的内容时,我会密切关注,不要冒险。如果你想让数据清楚,你应该确保自己清除它。否则,您永远无法确定您的代码在任何情况下都能工作,或者更新后其行为不会发生显著变化。

最新更新