【问题标题】:I'm confused about Inheritance我对继承感到困惑
【发布时间】:2018-11-28 03:13:39
【问题描述】:

条件: 如果一个类(ep:A)继承了另一个类(ep:B)。

class B
{
    public int id;
    public string Name;
}

class A:B
{
    public string className;
}    

当我创建A的实例时,然后通过A的实例调用id

 static void Main(string[] args)
 {
      A a = new A();
      Console.WriteLine(a.id);
 }

问题: 当我调用 Main 时,CLR 会检查所有 Main 的引用类型并将这些类型加载到 AppDomain 中。**

现在,我只引用 A 类型 - CLR 会加载 B 吗?** 我认为 B 类型将被加载到 AppDomain - 但是为什么呢?

那么,关于动态内存问题?CLR会给A类型多少内存?

内存会包含 B 的字段吗? 如果如我们所料,哪个 ctor 会初始化这些来自 B 的文件? B 的 ctor? 但是要注意ctor不能被继承。 那么,我们怎么称呼B的ctor呢?按base(关键字)? base如何获取B的ctor?

我想从 IL Code 中寻找答案:

B::id 让我很困惑....我没有 B 的实例,我可以调用 B::id 吗? 谁知道这些问题的原因,请给我解释一下!非常非常感谢!!!

【问题讨论】:

  • 您关心的是如何使用继承,或者微软是如何实现它的?如果 B 没有加载,编译器怎么知道 A 有一个 id 字段?你怎么能多态地将它用作 B?
  • @John 微软是如何实现的?
  • 我没有答案。为什么这对您很重要?
  • 不想成为 API 用户是什么意思? .NET 由数千个 API 构建而成。如果您打算使用 .NET,那么您将使用 api。这个问题的答案不会让你更有效率。如果您想做低级编程,那么 C# 可能不适合您。 C 或 Rust 可能更符合您的喜好。
  • @John 谢谢你的帮助!

标签: c#


【解决方案1】:

当我调用Main 时,CLR 将检查Main 中使用的所有类型并将这些类型加载到 AppDomain 中。

不,这不一定是真的。如果需要,类型加载器可以提前加载这些类型,或者在某些情况下,它可以延迟加载这些类型。

您假设的机制是 jit 编译器在 jit Main 时检查 Main 使用的类型集,并加载任何已使用但尚未加载的类型,并在此过程中初始化静态这些类型的状态,对吗?这是抖动有时会发生的优化。它不是 C# 语言的保证; C# 只保证如果你有一个静态构造函数,它会在创建第一个实例或执行第一个方法之前运行。

我只引用类型A - CLR 会加载类型B吗?

是的。 A 类型的所有依赖项都必须加载,包括基类型。

我认为 B 类型会被加载到 AppDomain 中,但是为什么呢?

必须加载所有A 类型的依赖项,包括基类型。

CLR 为A 类型的实例分配了多少内存?

只要它需要。

内存将包含B 的字段?

是的。

哪个 ctor 将初始化来自 B 的这些字段? B 的 ctor?

内存分配器会将所有字段初始化为其默认值;如果 B 的 ctor 然后为该字段分配不同的值,则会在 B 的 ctor 运行时发生。

但是要注意ctor不能被继承。

正确。 B 中的 ctor 不是 A 类型的成员。

我们如何称呼B ctor?通过base 关键字?

正确。如果您的 ctor 中没有包含 basethis 引用,C# 将自动假定您的意思是 base()。如果没有匹配的可访问 ctor,则程序出错,您必须明确指定要调用的基构造函数。

base 如何获得B ctor?

编译器查找相应基类 ctor 的元数据标记,并将其放入派生类 ctor 的实现中。您显然可以使用 ILDASM;使用它查看A ctor,您将看到对B ctor 的调用。

我没有B 的实例

是的,你知道。所有A 都是B 的实例。如果你有一个类Animal,和一个派生自Animal 的类Giraffe,并且你有一个Giraffe 的实例,那么你也有一个Animal 的实例,对吧?

我可以使用B 中的id 吗?

显然是的;你做到了!

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2019-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-11
  • 1970-01-01
相关资源
最近更新 更多