继承自抽象类与从C#中的内存消耗方面继承类似的Concrete类有什么区别?

时间:2017-12-12 09:46:26

标签: c# .net inheritance memory memory-management

我有两个班级:

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之间的内存消耗会有什么不同吗?请解释一下。

4 个答案:

答案 0 :(得分:0)

  

两者之间的内存消耗会有什么不同吗?   objC和objD?

没有。重要的是实际的实例化类(即调用C时)。只有当您创建类的实例时,才会分配内存。其内存量等于实例化的实际类。指向该实例的引用的类型与内存消耗完全无关。说过这两个实例化的DB具有相同的成员,它们也具有相同的内存占用。

如果您想要实例化非抽象的基类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控制台应用程序中运行基准测试。