问题的目的是了解遗产是如何运作的;我知道它是什么以及何时使用它。
以下是用例 -
class A {}
class B : A {}
class C
{
B b = new B();
}
现在,在内存中创建了多少个对象( EXCLUDING C类的对象,因为它将是入口点,任何默认的DotNet / CLR对象)?是两个(一个用于A,另一个用于B)?或者它只是B的一个,也包含A的成员?一些解释会有所帮助。
答案 0 :(得分:4)
为了论证,我们假设您创建了C
var c = new C();
此时您有两个对象实例,因为在构造期间C
会生成B
的实例。
要回答您的问题,您的实例为C
,实例为B
。您没有A
的实例,即使B
来自A
。 (更新:忽略C
和任何reflection,您有一个B
的对象实例。)
你可以用一些代码证明这一点:
class A { }
class B : A { }
class C
{
public B B = new B();
}
class Program
{
static void Main(string[] args)
{
var c = new C();
var b = c.B;
var BasA = (A)b;
bool BisA = BasA.GetType() == typeof (A);
Console.WriteLine($"Assert That B is not A: {!BisA}");
}
}
另外,您可以通过调试器查看所有内存:
还要注意术语。 A
,B
和C
是类。对象是类的实例。在C#中,描述类的信息可以封装在System.Type
类的实例中。
让我们一点儿走下兔子洞; 在执行程序集中,你在内存中有多少个对象?
将我们的范围仅限于这些类,除了从实例C
获得的两个对象之外,您还将有System.RuntimeType
的三个实例,A
,{{1} }和B
:
C
同样,这显示了您有三个 var assemblyTypes = Assembly.GetExecutingAssembly().GetTypes();
foreach (var classType in assemblyTypes)
Console.WriteLine("Type instance: " + classType);
实例,描述 类 System.RuntimeType
,A
和B
。
迂腐,您还将获得C
(对于您的可执行文件)和RuntimeAssembly
(对于您的控制台程序类)以及其他人的实例
答案 1 :(得分:1)
如果忽略C
(作为程序条目),将有一个B
对象和两个描述System.RuntimeType
和A
类的B
个对象。
通过C#,第四版,P100-110参考CLR
答案 2 :(得分:1)
使用关键字新时会创建新对象。
源代码更像是一个蓝图,为简单起见,您指定一个对象扩展行为和另一个对象的成员(继承它)。描述类型本身需要此信息。实际对象是使用 new 关键字基于类型描述构建的。
在您的情况下,只会创建一个对象。
答案 3 :(得分:1)
因为你的问题的目的似乎是基本上看到" physical"使用构图和继承之间的区别,我将专注于此。
当你使用new
时,会创建一个类型的实例,并且该类型的相应构造函数(及其所有" parent")将被执行一次。
在C#中,默认的继承方法(B : A
种类)是子类化。在这种方法中,派生类基本上是其父类的副本,加上派生类的实例字段,以及与例如相关联的元数据。任何新的虚拟方法。
这意味着在您的情况下,调用new B()
只会创建一个对象实例,而这就是它。 B
的实例本身包含A
的字段和元数据,但不包含A
实例的引用。
如果你这样定义B2
:
class A2
{
int myInt;
}
class B2
{
A2 aInstance = new A2();
}
然后B2
构造函数还会创建A2
的实例,因此您有两个对象实例,一个类型为A2
,另一个类型为B2
。 B2
仅包含对A2
实例的引用,而不是其副本。
这如何转化为运行时成本?
A2
往往会分配在B2
后面。结果呢?好吧,我不认为这是你需要提前关心的事情。拥有额外的实例需要付出代价,但除非您分配数百万个实例,否则它可能不会产生很大的可观察差异。如果您的应用程序允许,您甚至可能获得净收益,因为组合模型可以允许您在多个地方重用相同的实例,这对于子类化是不可能的。有时这是有道理的,有时它不会:)
当然,请注意,您不必总是使用课程。例如,A2
可以很容易地成为struct
,从而消除了额外的实例 - 再次,不可能通过子类化,因为struct
不能继承。在这种情况下,这两种方法就相同了。
通常情况就是如此,你真的需要做一些实用的分析来得到你的答案。结果可能就像" 99.9%的代码表现不错,但如果我们将它改为struct
并将多态性移动到一个类,那么这一个类可以为我们节省大量的CPU / RAM更高层"。
最后,我非常确定这些都不是合同的一部分。如果Microsoft决定改变继承在.NET框架的未来版本中的工作方式,并使其创建一个新实例而不是" inlining"父母,我不认为它会以任何方式违反规范。除非你绝对需要依赖这些信息,否则不要。