3

要将您转换为的值类型装箱System.Object- 这本身对我来说似乎是“错误的”(因为转换应该将值转换为另一种类型(因此将 Int32 转换为 Object 应该是数据丢失操作,因为 Object 没有实例自己的状态)或将接口指针转换为父对象(这不会影响所指向对象的状态,并且是编译时关注的问题)。在 CLR 中装箱值类型时,您正在复制值当您只想执行第一个任务(将值复制到堆,或者至少获得对它的引用)时,同时丢失了接口信息。

IntegerJava 用和的强类型解决了这个问题Long。为什么.NET 没有这个?

我有自己的实用程序源代码集合,我喜欢将它们包含在其他项目中,它们包括自己的强类型盒装类(例如 BoxedInt32)的实现,它们覆盖了隐式和显式转换运算符,因此它们的工作方式与转换为 Object 可以,除非不必实际转换为对象(从而保留类型数据)。所以我可以这样做:

private BoxedInt32 _reference;
public Int32 GetValue{ return _reference; }

那么为什么.NET 在四个主要版本之后仍然没有强类型的盒装类型呢?

4

3 回答 3

4

There would be no point. You would never directly use BoxedInt32, since if you knew the type in advance it would only be sensible to use int instead of the box. So the only interesting case is: when we don't know the type in advance, i.e. when dealing with object. Well, value-type boxing already handles that perfectly, reporting the type as Int32.

The reason the specific boxed versions exist in Java is, in part, because Java generics work very differently via type erasure; however .NET has true generics including for value-types, so this is unnecessary.

You could make your own box:

public class Box<T> where T : struct {
    private readonly T value:
    public Box(T value) { this.value = value; }
    public T Value { get { return value; } }
}

(perhaps adding more features such as conversions / equality): but - again: no point whatsoever. Regular inbuilt boxing already handles this much better.

于 2012-09-03T02:34:01.577 回答
1

您的问题的根源似乎是对铸造的工作原理及其用途的误解:

(因为转换应该将值转换为另一种类型......或将接口指针转换为父级)

当您将一件事转换为另一件事时,所发生的一切就是告诉编译器“请以稍微不同的方式处理这个随机的位集合”。这些位根本不应该被转换或修改。为了安全起见,C# 和 Java 会进行类型检查,但这并不是强制转换操作本身的核心。

将表示 int32 的位集合视为其他东西(例如 Object 引用)是荒谬的,因此 Boxing 系统会在您背后为您生成包装器。它仍然遵循强制转换规则 - 编译器现在可以将此装箱包装器视为对象引用,并且原始位不会被修改

...除非不必实际转换为对象(从而保留类型数据)...

同样,这是基于一个不正确的假设。根据上面的解释,强制转换确实“保留了类型数据”,因为它不修改值,它只是改变了编译器解释该数据的方式。装箱生成的包装器仍然可以访问底层数据, - 您可以在装箱的 int 上调用 .GetType() ,它会很高兴地报告它是一个 Int32。您的BoxedInt32课程只是在浪费时间和空间来存储已经可用的数据。

**注意:有时看起来像 C# 中的强制转换的代码实际上会通过调用隐式转换运算符来转换数据。这不是铸造,只是假装,所以规则不适用。

于 2012-09-03T04:38:01.767 回答
0

也许对于这种情况会很方便:

var myDictionary = new Dictionary<int, bool>();

// So we could use a BoxedBool here and modify the
// value set below.
//var myDictionary = new Dictionary<int, BoxedBool>();

myDictionary.Add(1, true);
myDictionary.Add(2, false);

foreach (var key in myDictionary.Keys)
{
    myDictionary[key] = false;
    // Cannot do this as it modified the collection.
    // If it was a reference type, this would not be a problem?
}
于 2014-01-28T05:49:00.267 回答