【问题标题】:How does the CLR know the type of a boxed object?CLR 如何知道装箱对象的类型?
【发布时间】:2010-04-16 09:05:32
【问题描述】:

当一个值类型被装箱时,它被放置在一个untyped引用对象中。 那么是什么导致了这里的无效转换异常呢?

long l = 1;
object obj = (object)l;
double d = (double)obj;

【问题讨论】:

    标签: c# clr type-conversion boxing


    【解决方案1】:

    不,它没有放在无类型的对象中。对于每种值类型,CLR 中都有一个装箱的引用类型。所以你会有 something 比如:

    public class BoxedInt32 // Not the actual name
    {
        private readonly int value;
        public BoxedInt32(int value)
        {
            this.value = value;
        }
    }
    

    尽管它在 C++/CLI 中,但在 C# 中不能直接访问该盒装类型。显然,它知道原始类型。因此,在 C# 中,变量的编译时类型必须为 object,但这并不意味着这是对象的实际类型。

    请参阅ECMA CLI specCLR via C# 了解更多详情。

    【讨论】:

    • 有趣,谢谢乔恩。 Wagner 的 Effective C# 指出:“装箱将值类型放在无类型的引用对象中”。我很确定它也说明了盒装对象不包含任何类型元数据,尽管我现在找不到那个特定的引用。正是在阅读那本书时,我想到了这个问题。
    • @fearofawhackplanet:我不想在 Bill 的嘴里说出他的确切含义 - 但 box 对象绝对确实知道它的原始类型,包括枚举。 (框一个枚举值,然后直接使用 ToString 而不拆箱来证明这一点:)
    • 我相信这是一个很好的示范。 long l = 40L; object o = (object)l; Console.WriteLine(o.GetType()); 在这种情况下,System.Int64 被打印到屏幕上。即使o 是一个对象,其底层类型仍然是一个long。
    【解决方案2】:

    Jon Skeet 的回答涵盖了原因;至于如何绕过它,这是你必须做的:

    long l = 1;
    object obj = (object)l;
    double d = (double)(long)obj;
    

    双重演员的原因是这样的;当 .NET 对变量进行拆箱时,它只知道如何将其拆箱为从其拆箱的类型(在您的示例中为 long。)一旦您将其拆箱并且您拥有适当的 long 原语,您就可以进行强制转换将其转换为 double 或来自 long 的任何其他类型。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-20
      • 2010-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-02
      • 1970-01-01
      相关资源
      最近更新 更多