簡體   English   中英

就C#中的內存消耗而言,從Abstract類繼承與從類似的Concrete類繼承之間有什么區別?

[英]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 ... )。 僅當創建類的實例時,才會分配內存。 因此,其存儲量等於實例化的實際類。 指向該實例的引用的類型與您的內存消耗完全無關。 這么說是因為您的兩個實例化的CD具有相同的成員,所以它們也具有相同的內存占用。

另一方面,如果您要實例化不是抽象的基類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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM