我有两个班级:
public abstract class A
{
public int TheInt {get;set;}
public string GetString(double dbl)
{
return dbl.ToString();
}
}
public class B
{
public int TheInt {get;set;}
public string GetString(double dbl)
{
return dbl.ToString();
}
}
我还有另外两个类,每个类都来自A或B:
public class C : A
{
}
public class D : B
{
}
我有两个对象:
C objC = new C();
D objD = new D();
objC和objD之间的内存消耗会有什么不同吗?请解释一下。
答案 0 :(得分:0)
两者之间的内存消耗会有什么不同吗? objC和objD?
没有。重要的是实际的实例化类(即调用C
时)。只有当您创建类的实例时,才会分配内存。其内存量等于实例化的实际类。指向该实例的引用的类型与内存消耗完全无关。说过这两个实例化的类D
和B
具有相同的成员,它们也具有相同的内存占用。
如果您想要实例化非抽象的基类D
的实例,那么可能会有一些区别,因为它的成员可能少于派生类D
(例如FurtherProperty
也包含不属于B
的成员{{1}}。
答案 1 :(得分:0)
抽象类是一个有一些例外的类,两者都可以有构造函数和方法,运行时不会创建基类和子类的单独实例。所以没有什么可以区分两者之间的内存消耗。
答案 2 :(得分:0)
以下是简化抽象和通常类的继承的IL代码:
不抽象:
<强> C#强>
public class NotAbstract
{
public void PrintOut()
{
Console.WriteLine(nameof(NotAbstract));
}
}
class Program : NotAbstract
{
static void Main(string[] args)
{
var p = new Program();
p.PrintOut();
}
}
<强> IL 强>
.class public auto ansi beforefieldinit Abstract_Test_Abstract.NotAbstract
extends [mscorlib]System.Object
{
.method public hidebysig instance void
PrintOut() cil managed
{
//000012: {
IL_0000: nop
//000013: Console.WriteLine(nameof(NotAbstract));
IL_0001: ldstr "NotAbstract"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
//000014: }
IL_000c: ret
} // end of method NotAbstract::PrintOut
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
} // end of method NotAbstract::.ctor
} // end of class Abstract_Test_Abstract.NotAbstract
.class private auto ansi beforefieldinit Abstract_Test_Abstract.Program
extends Abstract_Test_Abstract.NotAbstract
{
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.maxstack 1
.locals init ([0] class Abstract_Test_Abstract.Program p)
//000012: {
IL_0000: nop
//000013: var p = new Program();
IL_0001: newobj instance void Abstract_Test_Abstract.Program::.ctor()
IL_0006: stloc.0
//000014: p.PrintOut();
IL_0007: ldloc.0
IL_0008: callvirt instance void Abstract_Test_Abstract.NotAbstract::PrintOut()
IL_000d: nop
//000015: }
IL_000e: ret
} // end of method Program::Main
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
} // end of method Program::.ctor
} // end of class Abstract_Test_Abstract.Program
<强>摘要:强>
<强> C#强>
public abstract class IsAbstract
{
public abstract void PrintOut();
}
class Program : IsAbstract
{
static void Main(string[] args)
{
var p = new Program();
p.PrintOut();
}
public override void PrintOut()
{
Console.WriteLine(nameof(IsAbstract));
}
}
<强> IL 强>
.class public abstract auto ansi beforefieldinit Abstract_Test_NotAbstract.IsAbstract
extends [mscorlib]System.Object
{
.method public hidebysig newslot abstract virtual
instance void PrintOut() cil managed
{
} // end of method IsAbstract::PrintOut
.method family hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
} // end of method IsAbstract::.ctor
} // end of class Abstract_Test_NotAbstract.IsAbstract
.class private auto ansi beforefieldinit Abstract_Test_NotAbstract.Program
extends Abstract_Test_NotAbstract.IsAbstract
{
.method private hidebysig static void Main(string[] args) cil managed
{
//000012: {
IL_0000: nop
//000013: var p = new Program();
IL_0001: newobj instance void Abstract_Test_NotAbstract.Program::.ctor()
IL_0006: stloc.0
//000014: p.PrintOut();
IL_0007: ldloc.0
IL_0008: callvirt instance void Abstract_Test_NotAbstract.IsAbstract::PrintOut()
IL_000d: nop
//000015: }
IL_000e: ret
} // end of method Program::Main
.method public hidebysig virtual instance void
PrintOut() cil managed
{
.maxstack 8
//000016:
//000017: public override void PrintOut()
//000018: {
IL_0000: nop
//000019: Console.WriteLine(nameof(IsAbstract));
IL_0001: ldstr "IsAbstract"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
//000020: }
IL_000c: ret
} // end of method Program::PrintOut
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
} // end of method Program::.ctor
} // end of class Abstract_Test_NotAbstract.Program
正如您所看到的,没有任何额外内存消耗的证据。
答案 3 :(得分:0)
我在问题上运行了如下基准测试,得出的结论是objC和objD 的内存消耗相同。
class Program
{
static void Main(string[] args)
{
BenchmarkC(); //Gives 24
//BenchmarkD(); //Gives 24
}
static void BenchmarkC()
{
long StopBytes = 0;
long StartBytes = System.GC.GetTotalMemory(true);
C objC = new C();
StopBytes = System.GC.GetTotalMemory(true);
GC.KeepAlive(objC);
Console.WriteLine(StopBytes - StartBytes);
Console.ReadKey();
}
static void BenchmarkD()
{
long StopBytes = 0;
long StartBytes = System.GC.GetTotalMemory(true);
D objD = new D();
StopBytes = System.GC.GetTotalMemory(true);
GC.KeepAlive(objD);
Console.WriteLine(StopBytes - StartBytes);
Console.ReadKey();
}
}
public abstract class A
{
public int TheInt { get; set; }
public string GetString(double dbl)
{
return dbl.ToString();
}
}
public class B
{
public int TheInt { get; set; }
public string GetString(double dbl)
{
return dbl.ToString();
}
}
public class C : A
{
}
public class D : B
{
}
谢谢大家的帮助。 PS。如果重要,我在.NET Core 2.0控制台应用程序中运行基准测试。