【问题标题】:CLR specification on boxing关于拳击的 CLR 规范
【发布时间】:2011-10-05 11:31:26
【问题描述】:

我目前正在阅读CLR specification。我在理解“I 8.2.4 值的装箱和拆箱”部分时遇到了一些麻烦。

1。什么时候可以使用盒装类型?

一方面它指出:

对于每个值类型,CTS 定义了一个相应的引用类型,称为装箱类型。 [...] 一个值的表示 装箱类型(装箱值)是可以存储值类型的值的位置。盒装类型是 对象类型和装箱值是对象。

装箱类型不能直接通过名称引用,因此不能给字段或局部变量一个装箱 type. 最接近盒装枚举值类型的命名基类是 System.Enum;对于所有其他值类型 它是 System.ValueType。类型为 System.ValueType 的字段只能包含 null 值或 a 的实例 盒装值类型。本地类型的 System.Enum 只能包含 null 值或装箱的实例 枚举类型。

这是否意味着我可以拥有使用强类型盒装值类型的属性/方法,或者这只是规范中的一个遗漏?如果是这样,为什么我可以有属性但没有字段?

另一方面,C++/CLI 似乎支持装箱值类型,即使在使用 MyStruct^but seems to behave strangely with boxed primitive types(System.Int32^) 的局部变量中也是如此。但我不确定其中哪一部分是 C++/CLI 编译器魔法(它可能使用标记的 Object 变量代替),哪一部分由 CLR 处理。

规范进一步指出:

CLS 规则 3:盒装值类型不符合 CLS。 [注意:代替盒装类型,请酌情使用 System.Object、System.ValueType 或 System.Enum。

这似乎暗示强类型的装箱值类型可以是类型的公共接口的一部分。但不应用于 CLS 合规性(这是可以理解的,因为大多数语言不支持它们)。

那么在哪里可以使用强类型的装箱值类型呢?为什么那些地方可以用,其他地方不行?

2。装箱引用类型

规范还提到了装箱引用类型:

一个类型是可装箱的,如果它是以下之一:

[...]

  • 引用类型(包括类、数组、委托和泛型类的实例),不包括 托管指针/byrefs (§8.2.1.1)

  • 泛型参数(用于泛型类型定义或泛型方法定义)[注意:装箱和 通用参数的拆箱增加了 CLI 实现的性能开销。受约束的。 前缀可以提高虚拟分派到由值类型定义的方法期间的性能,通过避免 装箱值类型。尾注]

装箱引用类型是无操作的吗?允许装箱引用类型对于您不知道某物是值还是引用类型的泛型参数很有用。因此,我假设允许对引用类型进行装箱,以便与表示引用类型的泛型参数保持一致。

3。接口“在类型上定义”是什么意思?

最后我在理解以下段落时遇到了问题:

接口和继承仅在引用类型上定义。因此,虽然值类型定义(§8.9.7)可以 指定应由值类型和类(System.ValueType 或 System.Enum) 继承,这些仅适用于装箱值。

接口“在类型上定义”是什么意思?我的理解是,转换为接口/基类将值框起来,但是您仍然可以使用受约束的虚拟调用在未装箱的情况下调用在此类接口/类中定义的方法。 (带约束前缀的virtcall)

【问题讨论】:

  • 关于你的最后一个问题,我认为混淆源于这样一个事实,即 CIL 中没有“铸造”。 C#(或其他托管语言)中的转换可以转换为各种 CIL 操作,其中之一是装箱。不过,我不确定接口方法。

标签: .net c++-cli clr value-type boxing


【解决方案1】:

是的,C++/CLI 语言允许声明强类型的装箱值类型:

public ref class Class1
{
public:
    int^ boxedInt;
    Class1() { boxedInt = 42; }
};

它遵守 CLI 规范,但是,boxedInt 字段在元数据中键入 ValueType。它会记住并检查带有 modOpt 属性的盒装类型:

field boxedInt: public class System.ValueType modopt(System.Int32) modopt(System.Runtime.CompilerServices.IsBoxed)

在 C# 中也可以实现完全相同的操作,但编译器会检查是否仅将 int 值分配给该字段。只需将该字段声明为 ValueType。否则没有实际价值。

【讨论】:

  • 如果有一个名为objObject^,持有对装箱Int32 的引用,则可以使用*((Int32^)Object) = 5; 导致装箱对象的值为5。尽管.net假装拥有一个“统一类型系统”,装箱任何值类型都会将其转换为可变引用类型,并使用 Equals 方法假定它永远不会发生变异。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多