System.Array 是否对值类型执行装箱?
我最近对一系列小型结构的 List<>
与 []
进行了一些粗略的性能测量。 System.Array 似乎轻而易举地获胜了,所以我就这么做了。
我才刚刚意识到 System.Array 包含对象类型,所以用结构填充它肯定会导致装箱发生吗?
但是,System.Array 的 MSDN 条目指出:
在 .NET Framework 2.0 版中,Array 类实现
System.Collections.Generic.IList
,System.Collections.Generic.ICollection
,以及System.Collections.Generic.IEnumerable
通用接口。这 实现在运行时提供给数组,因此 对于文档构建工具不可见。结果,通用的 接口不会出现在数组的声明语法中 类,并且没有关于接口成员的参考主题 只能通过将数组转换为通用接口类型来访问 (显式接口实现)。
这是否意味着拳击最终不会发生? (并会解释我的表现结果)
I recently did some rough performance measuring on List<>
vs []
for an array of small structures. System.Array seemed to win hands down so I went with that.
It's only just dawned on me that System.Array contains object types, so surely filling it with structures would cause boxing to occur?
However, the MSDN entry for System.Array states:
In the .NET Framework version 2.0, the Array class implements the
System.Collections.Generic.IList<T>
,System.Collections.Generic.ICollection<T>
, andSystem.Collections.Generic.IEnumerable<T>
generic interfaces. The
implementations are provided to arrays at run time, and therefore are
not visible to the documentation build tools. As a result, the generic
interfaces do not appear in the declaration syntax for the Array
class, and there are no reference topics for interface members that
are accessible only by casting an array to the generic interface type
(explicit interface implementations).
Does this mean that boxing does not occur after all? (And would explain my performance results)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果使用索引器表示法,则不使用数组不会装箱。
例如,
编译为以下 IL(请注意,行号不相关,因为它们来自其他代码片段)
对于无法使用索引器的语言(我真的不知道它们是否存在),在以下位置创建了 2 个其他方法数组的编译时间。
它创建这些公共方法::
这些方法也不装箱,并且通常不能通过 C# 访问。 (不要问我为什么它们是公共方法)。您可以使用 IL 或通过创建它们的委托来执行它们。它们速度较慢,因为您被迫执行 callvirt 来调用这些方法。
stelem.* 和 ldelem.* 系列用于处理强类型数组类型的存储。使用泛型时,通常会在使用
T[]
时附加以下前缀constrained
或readonly
。stelem.*
类型通常不检查类型。例如,使用stelem.i4
比使用stelem.any Int32
更快,除非您使用readonly
前缀,否则它会强制进行类型检查。现在,类型检查对值类型数组完全没用,因为它们不是协变的!
因为运行时生成从零开始的一维数组(称为 SZ_array 或向量类型)类型,所以它们本身是已知的。
它们有一系列 il 操作码:
newarr
、stelem.*
、ldelem.*
、ldlen
。List
类型使用T[]
作为 BCL 的 Microsoft 实现中的后备存储List
不装箱。无论使用列表还是数组,您都将数据存储在数组中。No using an array does not box if you use the indexer notation.
e.g.
Compiles to the following IL (note the line numbers are irrelevant as they come from some other snippet of code)
For languages that cannot use the indexer (and I don't really know if they exist or not) 2 other methods are created at compile time for Arrays.
It creates these public methods::
Those methods don't box either and are not normally accessible through C#. (Don't ask me why they are public methods). You can execute them using IL or by creating delegates to them. They are slower as you are forced to do a callvirt to invoke these methods.
The stelem.* and ldelem.* family is used to handle storing to a strongly typed array type. When using generics usually the following prefixes are attached
constrained
orreadonly
when using aT[]
.stelem.*
type usually do not check type. E.g. usingstelem.i4
is faster than usingstelem.any Int32
unless you prefix it withreadonly
because otherwise it forces a type check.Now the typecheck is COMPLETELY useless on valuetype arrays are they are not covariant!
Because the runtime generates the one dimensional array starting at zero (either called SZ_array or vector type) type they are natively known.
There are a family of il op codes for them:
newarr
,stelem.*
,ldelem.*
,ldlen
etc.The
List<T>
type uses aT[]
for its backing store in the microsoft implementation of the BCL.List<T>
does not box. Regardless of using list or array you are storing things in an array.