Array.Initialize-为什么存在此方法
本文关键字:此方法 存在 为什么 Initialize- Array | 更新日期: 2023-09-27 18:24:25
我今天偶然发现了一个方法。我说的是:Array.Initialize().
根据文件:
此方法旨在帮助编译器支持值类型数组;大多数用户不需要这种方法。
此方法如何负责使编译器支持值类型?就我而言,这种方法只是:
通过调用值类型的默认构造函数来初始化值类型Array的每个元素。
此外,为什么它是公共?我不认为自己需要调用这个方法,编译器在创建数组时已经初始化了,所以手动调用这个方法是多余的,也是无用的。
即使我的意图是重置数组的值,我仍然不会调用它,而是创建一个新的数组。CCD_ 1。
所以,这个方法的存在似乎只是为了编译器。为什么会这样?谁能给我更多的细节吗?
值得注意的是,.NET的规则与C#的规则不同。
我们可以在.NET中做一些在C#中做不到的事情,通常是因为代码是不可验证的(例如ref
返回类型),或者是因为它们可能会带来一些混乱。
在C#中,struct
s不能有一个定义的无参数构造函数,调用new SomeValueType()
是通过创建内存的零填充部分来工作的(因此,所有字段对于数值类型都是0
,对于引用类型是null
,而对于其他值类型则是相同规则的结果)。
在.NET中,可以对值类型使用无参数构造函数。
这样做可能是个坏主意。首先,关于何时调用它以及何时值的内存为零,以及在不同情况下赋值时会发生什么的规则并不完全简单(例如,new SomeValueType()
会调用它,但在T
是array = 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)状态。
它看起来并不是一个非常有用的工具,但我可以看到它对清零非内在值数据数组是多么有用。