Array.Initialize-为什么存在此方法

本文关键字:此方法 存在 为什么 Initialize- Array | 更新日期: 2023-09-27 18:24:25

我今天偶然发现了一个方法。我说的是:Array.Initialize().

根据文件:

此方法旨在帮助编译器支持值类型数组;大多数用户不需要这种方法。

此方法如何负责使编译器支持值类型?就我而言,这种方法只是:

通过调用值类型的默认构造函数来初始化值类型Array的每个元素。

此外,为什么它是公共?我不认为自己需要调用这个方法,编译器在创建数组时已经初始化了,所以手动调用这个方法是多余的,也是无用的。

即使我的意图是重置数组的值,我仍然不会调用它,而是创建一个新的数组。CCD_ 1。

所以,这个方法的存在似乎只是为了编译器。为什么会这样?谁能给我更多的细节吗?

Array.Initialize-为什么存在此方法

值得注意的是,.NET的规则与C#的规则不同。

我们可以在.NET中做一些在C#中做不到的事情,通常是因为代码是不可验证的(例如ref返回类型),或者是因为它们可能会带来一些混乱。

在C#中,struct s不能有一个定义的无参数构造函数,调用new SomeValueType()是通过创建内存的零填充部分来工作的(因此,所有字段对于数值类型都是0,对于引用类型是null,而对于其他值类型则是相同规则的结果)。

在.NET中,可以对值类型使用无参数构造函数。

这样做可能是个坏主意。首先,关于何时调用它以及何时值的内存为零,以及在不同情况下赋值时会发生什么的规则并不完全简单(例如,new SomeValueType()会调用它,但在Tarray = new int[]0的通用方法中,new T()不会!)。如果new SomeValueType()的结果总是零填充,那么生活会更简单。毫无疑问,这影响了C#的设计,即使.NET允许这样做。

因此,对于用C#编写的任何类型的新数组,Array.Initialize()都没有意义,因为调用构造函数和零填充是一回事。

但出于同样的原因,一个类型可以用另一种.NET语言编写(至少,你可以用CIL来做),这种语言确实有一个实际有效的无参数构造函数。因此,这样一种语言的编译器可能希望它的等价new SomeValueType[3]对数组中的所有类型调用该构造函数。因此,在框架中有一个允许进行这种填充的方法是明智的,这样这样一种语言的编译器就可以利用它

还有,为什么它是公开的?

因此,即使在安全限制阻止它调用另一个程序集的私有方法的情况下,它也可以由这样一个假设构造函数生成的代码调用。

对我自己来说,Initialize()方法似乎贯穿数组并在其中重新创建值类型。因此,使用新数组,您会得到一个新的空数组,使用array.Clear()也会得到,但使用array.Initialize(),您得到的数组充满了新创建的值类型(基于旧数组的类型和长度)。

这应该是所有的区别。

基于CLR源,该方法遍历数组的每个索引,并通过调用默认构造函数来初始化该索引上的值类型,类似于initobj IL指令(不过,我想知道当构造函数抛出异常时会发生什么)。该方法是公共的,因为直接从IL调用私有方法会使其有点无法验证。

现在的C#编译器在创建数组时不会初始化数组的每个元素,只需将每个索引"设置"为类型的默认值。C#6引入了实现值类型的默认构造函数(CLR已经支持这些构造函数),因此对于具有不同数组创建语义的语言来说,这是必需的。

您可以在测试代码中看到预期用途:

https://github.com/dotnet/coreclr/blob/3015ff7afb4936a1c5c5856daa4e3482e6b390a9/tests/src/CoreMangLib/cti/system/array/arrayinitialize.cs

基本上,它将非内在值类型的数组设置回其默认(T)状态。

它看起来并不是一个非常有用的工具,但我可以看到它对清零非内在值数据数组是多么有用。