现在的位置: 首页 > 综合 > 正文

[C#]struct如何支持虚方法覆盖和接口继承

2012年11月20日 ⁄ 综合 ⁄ 共 1325字 ⁄ 字号 评论关闭

  我还没有研读《CLR Via C#》之类的专著,只是心里有了疑问,然后就去个人探究,下文多为猜想。更希望了解内幕的朋友告知C#后台真相。

  我自个儿琢磨出来的结论:形如 

1 // 原始声明
2 struct People : IFormattable
3 {
4 public string ToString(string format, IFormatProvider formatProvider)
5 {
6 return ToString();
7 }
8 public override string ToString() { return Name; }
9
10 public string Name { get; set; }
11 }

 的结构声明,会被转化为两个后台声明:

1 // 实际代码中的struct People被映射成这个类型,虚方法声明和接口继承都无效了
2 struct PeoplePOD // : IFormattable
3 {
4 public string ToString(string format, IFormatProvider formatProvider)
5 {
6 return ToString();
7 }
8 public /* override */ string ToString() { return Name; }
9
10 public string Name { get; set; }
11 }
12 // 这是装箱后的堆对象类型,任何试图将原始struct转化为object/ValueType/接口的转型,都会被自动装箱为这个类型的对象
13 class PeopleBox : IFormattable
14 {
15 public string ToString(string format, IFormatProvider formatProvider)
16 {
17 return ToString();
18 }
19 public override string ToString() { return Name; }
20
21 public string Name { get; set; }
22 }

  代码中出现的所有struct People,其实都是struct PeoplePOD,即放弃了虚函数和接口继承后的纯数据+非虚方法。没有了虚方法,对象实例中就不需要为了支持多态而去包含指向类型信息的指针,故对这个struct取sizeof得到的大小等于各个字段(不包括class字段)sizeof大小之和。

  而任何将原始struct对象进行向基类的转换,都会造成装箱,装箱类型就是PeopleBox:

1 People orgin = new People();
2 object _object = orgin; // object _object = new PeopleBox(orgin);
3 ValueType _valueType = orgin; // ValueType _valueType = new PeopleBox(orgin);
4 IFormattable _iformattable = orgin; // IFormattable _iformattable = new PeopleBox(orgin);

  所以,在struct中声明的虚函数和接口继承,只在装箱后对象上完全发挥了效果,对于struct对象本身,这些虚方法退化成了静态调用(编译期绑定)。

抱歉!评论已关闭.