System.Object如何在内部存储“对象”?

时间:2011-02-23 20:01:00

标签: .net object store

我正在阅读有关拳击的内容,书中说“拳击可以正式定义为通过将变量存储在System.Object中将值类型显式转换为相应的引用类型的过程“。 (重点补充)

我的问题不是关于拳击,但这让我思考 - System.Object实例如何以及在何处存储分配给它的值/变量/对象。所以我不仅想知道

object objShort = 5;

但也

object someOtherObj = someReallyComplicatedObject;

我一直在寻找,包括here (MSDN System.Object),我没有看到任何描述System.Object实例如何实际存储其数据的地方。

对象只是简单地存储指向分配给它的对象的指针,或者在装箱的情况下,指向堆栈上值类型的指针?

(乔恩,请原谅我,如果这也出现在你的书中。我已经订购了它,它已经开始了!)

3 个答案:

答案 0 :(得分:8)

拳击的描述不准确。创建的对象不仅仅是裸System.Object的实例;每个值类型实际上都有自己的“隐藏”对应引用类型,它只是从ValueType派生的类实现与值类型相同的接口,并且具有值类型类型的字段。这当然是我对它的看法,至少,它大致是CLI规范描述它的方式。 System.Object本身 没有任何存储空间。

我还想纠正“存储变量”部分 - 装箱将存储在一个对象中。该值可能是变量的值,也可能是方法调用的结果,或者其他任何内容。

当然,对于参考类型,根本不需要拳击。你真的需要区分引用对象 - 一旦你在脑海中清楚地了解了这两个,大多数其他事情都很容易理解。然后记住变量的值永远不是一个对象 - 它只是一个值类型值或一个引用(或一个指针:)

(哦,这在C#深度中有点有些,但不是很详细。但你可能对Eric Lippert的帖子"The Truth About Value Types"感兴趣。)

答案 1 :(得分:6)

想象一下,有一个通用的引用类型,如下所示:

sealed class Box<T> : System.ValueType where T : struct
{
    private T value;
    public Box(T t) 
    {
        this.value = t;
    }
}

还有一堆其他狡猾的东西:

  • Box<T>T的显式转换运算符。
  • TBox<T>的隐式转化运算符,它只是调用构造函数。
  • 代理this.value的ToString,GetHashcode和GetType的实现。

概念,从int到object的装箱转换只是调用从intBox<int>的隐式转换运算符。

当然,实际上没有Box<T>这样的类型,如果有的话,它必须充满古怪的东西;你不能正常覆盖GetType,你不能正常地在一个类中扩展ValueType,它的可行类型的行为很奇怪,依此类推。所有这些细节都是CLR的实现细节,但它有助于想象CLR只是创建一个非常特殊类型的实例来完成装箱和拆箱的工作。

答案 2 :(得分:2)

CLR中引用类型的对象(包括C#)存储有一些元数据,这些元数据描述了它是什么类型的对象,它的锁状态和垃圾收集信息等,以及实际数据该对象存储。

当(值类型的)值被加框时,将为值类型创建为引用类型创建的相同类型的结构。它是在用于引用类型对象的同一托管堆中创建的,并且它受到相同的垃圾回收。 (因此它不是对堆栈上的值的引用。)