简而言之,我认为拳击是一种烦恼。让我们看看一些替代方案......
public class Box<T>
where T : struct
{
public T Value { get; set; }
public static implicit operator T(Box<T> box)
{
return box.Value;
}
}
System.Int32 派生自抽象类 System.ValueType,后者派生自 System.Object 类。您不能从 C# 中的 System.ValueType 派生,但我猜想 struct 关键字正是这样做的,并且 CLI 将这些类型定义识别为具有按值传递的语义。无论如何,当将结构分配给对象类型时,就会发生装箱。我不想陷入拳击本身,而是想直接进入它。
我查看了一些由 C# 编译器生成的 IL。
object obj = 1;
.locals init ([0] object obj)
L_0000: nop
L_0001: ldc.i4.1
L_0002: box int32 // Convert a value type (of the type specified in valTypeToken) to a true object reference.
L_0007: stloc.0
在 MSDN 上找到这个...
值类型在公共语言基础结构 (CLI) 中有两种不同的表示形式:
当值类型嵌入另一个对象或堆栈时使用的“原始”形式。
一种“盒装”形式,其中值类型中的数据被包装(盒装)到一个对象中,因此它可以作为独立实体存在。
这使我得出结论,编写这样的代码应该同样昂贵......
var box = obj as Box<int>;
if (box != null)
{
Console.WriteLine(box.Value);
}
如果我打算将相同的值作为 System.Object 传递,我真的想每次都将 ValueType 拆箱和装箱吗?我的直觉告诉我不,但我真的找不到任何人愿意评论所有这些喋喋不休的好动机?
编辑
有人发现自己在这样做吗?我意识到它可能看起来很奇怪,但有一次我发现自己处于一个位置,我想基于几种不同的表示来抽象计算。我是这样做的,并使用 lambda 表达式。它与装箱并没有真正的关系,但它允许我将任何 ValueType(这个结构方便地以 8 字节对齐)视为一种单一类型“ReinterpretCast”。
[StructLayout(LayoutKind.Explicit)]
public struct ReinterpretCast
{
[FieldOffset(0)] sbyte @sbyte;
[FieldOffset(0)] byte @byte;
[FieldOffset(0)] short @ushort;
[FieldOffset(0)] ushort @short;
[FieldOffset(0)] int @int;
[FieldOffset(0)] uint @uint;
[FieldOffset(0)] long @long;
[FieldOffset(0)] ulong @ulong;
[FieldOffset(0)] float @float;
[FieldOffset(0)] double @double;
}