[英]What is the difference between inheriting from Abstract class vs Inheriting from a similar Concrete class in terms of memory consumption in C#?
我有兩個這樣的類:
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之間在內存消耗方面是否會有任何區別? 請解釋。
objC和objD之間在內存消耗方面是否會有任何區別?
不。所有重要的是實際的實例化類(即調用new ...
)。 僅當創建類的實例時,才會分配內存。 因此,其存儲量等於實例化的實際類。 指向該實例的引用的類型與您的內存消耗完全無關。 這么說是因為您的兩個實例化的類C
和D
具有相同的成員,所以它們也具有相同的內存占用。
另一方面,如果您要實例化不是抽象的基類B
的實例,則可能會有所不同,因為它的成員可能少於派生類D
的成員(例如, D
還包含成員FurtherProperty
不是B
一部分)。
抽象類是一個有一些例外的類,它們都可以具有構造函數和方法,運行時不會創建基類和子類的單獨實例。 因此,在內存消耗方面沒有區別。
以下是抽象類和常規類的繼承的簡化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();
}
}
白介素
.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));
}
}
白介素
.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
如您所見,沒有任何跡象表明有任何額外的內存消耗。
我對該問題進行了如下基准測試,得出的結論是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
{
}
謝謝大家的幫助。 附言 如果有問題,我可以在.NET Core 2.0控制台應用程序中運行基准測試。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.