首页 > 解决方案 > 关于类实例的性能变化

问题描述

学生.cs

class Student
{
   public int getAge()
   {
      return 10;
   }
}

程序.cs

class Program
{
   public static void Main(string[] args)
   {
      Student s = new Student();
      int a = s.getAge();
      int b = new Student().getAge();
   }
}

以上述方式访问一个类时会不会有性能差异

标签: c#

解决方案


以上述方式访问一个类时会不会有任何性能或安全性差异

不。

寻找性能差异的一种方法是观察编译给定代码时生成的 IL 语句。当您在调试模式下编译程序时,您会发现这两种获取年龄的方式略有不同:

.locals init (
    [0] class Student,
    [1] int32,
    [2] int32
)

IL_0000: nop
IL_0001: newobj instance void Student::.ctor()
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: callvirt instance int32 Student::getAge()
IL_000d: stloc.1
IL_000e: newobj instance void Student::.ctor()
IL_0013: call instance int32 Student::getAge()
IL_0018: stloc.2
IL_0019: ret

请注意,直到语句IL_000d用于分配变量sa。语句IL_000eIL_0013用于分配变量b。注意在后者中没有分配局部变量的中间语句。

但是,当您使用发布配置编译代码时,差异完全消失了,因为编译器可以轻松确定变量sa并且b不会在任何后续语句中使用。

IL_0000: newobj instance void Student::.ctor()
IL_0005: callvirt instance int32 Student::getAge()
IL_000a: pop
IL_000b: newobj instance void Student::.ctor()
IL_0010: call instance int32 Student::getAge()
IL_0015: pop
IL_0016: ret

即使您要指示这些变量ab在以后使用,IL 代码对于这两种情况仍然是相同的。

例如,如果源代码修改如下:

Student s = new Student();
int a = s.getAge();
int b = new Student().getAge();
Console.WriteLine(a);
Console.WriteLine(b);

IL 现在更改为,

IL_0000: newobj instance void Student::.ctor()
IL_0005: callvirt instance int32 Student::getAge()
IL_000a: stloc.0
IL_000b: newobj instance void Student::.ctor()
IL_0010: call instance int32 Student::getAge()
IL_0015: ldloc.0
IL_0016: call void [System.Console]System.Console::WriteLine(int32)
IL_001b: call void [System.Console]System.Console::WriteLine(int32)
IL_0020: ret

所以我想说这两种情况之间不应该有任何性能差异。

关于安全性,我观察到的唯一区别是在第二种情况下没有存储实例对象。但这也不应该有任何区别。


推荐阅读