C# - CLR在继承期间如何组织内存/引用?

use*_*677 3 .net c# oop inheritance

假设我有以下代码片段:( 澄清目的/没有很好地形成)

class Employee
{
    #region fields

    protected string _empID;

    protected string _empName;

    protected readonly string _ssn;

    #endregion

    public Employee(){}   

    public Employee(string _empID,string _empName,string _ssn)
    {
        this._empID =_empID;
        this._empName=_empName;
        this._ssn = _ssn;
    }
}


class Manager : Employee
{
    private string _branchID;

    public Manager(int  _branchID):base(string _empID,string _empName,string _ssn)
    {
        this._branchID=_branchID;
    }
}

static void Main()
{
   Manager mgr = new Manager("1","sam","xxx","Branch1");
}
Run Code Online (Sandbox Code Playgroud)

使用base 关键字我正在调用父类构造函数.

在这种情况下,如何组织继承?我有一些不好的假设如下:

由于Manager是从Employee派生的,因此Manager类被填充(empID,empName,ssn)

-----------------
 Manager
-----------------
empID
empName
ssn
branchID
Run Code Online (Sandbox Code Playgroud)

第1步:构造函数调用:base("1","sam","xxx")

第2步:基类(Employee)构造函数填充派生类字段(empID,empName,ssn)

步骤3:branchID由派生类构造函数指定

.......

我的问题是

  • 如果一个类是从基类派生的,那么派生类也有基类的隐藏字段?
  • 派生类共享基类字段?我的意思是为Base类和派生类分配了单独的内存块?
  • Jon*_*eet 8

    对象以标题开头,标题包含指向其实际类型信息的指针.该类型信息包括用于确定哪种方法实际意味着什么的vtable.CLR在执行时使用该vtable来调用重写方法.

    对象头之后是与对象关联的所有实例数据 - 包括基类字段和派生类字段.它只在一个地方 - 它不像派生类的实例也引用了基类的"隐藏"实例.我强烈怀疑基类字段是第一位的,因为基类中的方法仍然可以通过对象"顶部"的偏移量(在汇编中)引用相同的字段...但我没有任何内容在我面前证实这一点.

    IIRC,Jeff Richter的"通过C#CLR"在一定程度上谈论了所有这些 - 它是这类事物的重要信息来源.


    Rob*_*les 6

    http://www.rvenables.com/linkjackandsufferaccidentaldroptable/clr_via_csharp_f4.9.png

    是的,派生类还将包含内存中的基类字段.在CLR第112页通过C#,Jeffrey Richter说:

    "然后,M3执行其代码来构造一个Manager对象.这会导致在托管堆中创建一个Manager类型的实例,一个Manager对象,如图4-9所示.如您所见,Manager对象-as do all objects-具有类型对象指针和同步块索引.该对象还包含将Manager类型定义的所有实例数据字段保存为Manager类型的任何基类定义的任何实例字段所需的字节数(在这种情况下,员工和对象)." (强调添加)

    另外值得一提的是,存储器的单独的块用于任何类型的基创建.但仅适用于类型数据(最多只能一次).当您创建Manager对象(派生自Employee)时,CLR将确保堆上有Manager类型对象Employee Type对象.

    1)里希特,杰弗里.CLR通过C#.雷德蒙德:微软出版社,2006年.(亚马逊链接)