Dot-Net

對像初始化器性能

  • October 19, 2017

c# 3.0 中的對像初始化器是否比正常方式更快?

這是不是更快

Object object = new Object
{
   id = 1;
}

比這個 ?

Object object = new Object()

object.id = 1;

在發布模式下,它們將編譯為完全相同的IL 程式碼(假設您實際上使用的是具有id屬性的類型而不是Object

因此,根據定義,不會有性能差異。

我不知道哪個編譯速度更快,但編譯時間會略有不同,您可能不在乎。

但是,對像初始值設定項語法編寫得更快(鍵入更少),因此您可能應該使用它。

好的,根據 [SLaks][2] 的評論,並在閱讀後測試自己,結果發現我在這裡描述的差異僅存在於調試模式下。如果您為發布而編譯,它們都編譯為相同的程式碼。每天學些新東西 :)


(因此其餘答案假定為調試模式。)

產生的 IL存在差異,與此處其他人的回答相反,但差異可以忽略不計,實際上根本不會對您的程序產生任何性能影響。

不同之處在於使用對像初始化器,如下所示:

Object object = new Object
{
   id = 1;
}

程式碼實際上是編譯的,就好像你寫了這個:

Object temp = new Object();
temp.id = 1;
Object object = temp;

(當然,除非 Object 沒有 Id 欄位/屬性,並且您實際上不能在不使用逐字標識符語法“@object”的情況下將變數命名為“object”。)

為什麼這很重要?好吧,您可能會注意到的一個區別是,如果任何賦值拋出異常(將值寫入對象,或者從表達式或函式中獲取值拋出異常),那麼使用對像初始化器,您將不會t 實際上看到變數中的任何對象,而在您的“手動”程式碼中,該對象將在那裡,初始化直到發生異常的點。

一個微小的差異,不應該有太大的性能差異,但可能會改變程序的行為。

這可以通過查看 IL 來驗證。以這個 C# 程序為例:

using System;

namespace ConsoleApplication3
{
   class Test
   {
       public Int32 Id { get; set; }
   }

   class Program
   {
       static void Main(string[] args)
       {
           M1();
           M2();
       }

       static void M1()
       {
           Test t = new Test();
           t.Id = 1;
       }

       static void M2()
       {
           Test t = new Test { Id = 1 };
       }

       static void M3()
       {
           Test t;
           Test temp = new Test();
           temp.Id = 1;
           t = temp;
       }
   }
}

並編譯它,通過Reflector執行它,你會得到 M1、M2 和 M3 的:

.method private hidebysig static void M1() cil managed
{
   .maxstack 2
   .locals init (
       [0] class ConsoleApplication3.Test t)
   L_0000: nop 
   L_0001: newobj instance void ConsoleApplication3.Test::.ctor()
   L_0006: stloc.0 
   L_0007: ldloc.0 
   L_0008: ldc.i4.1 
   L_0009: callvirt instance void ConsoleApplication3.Test::set_Id(int32)
   L_000e: nop 
   L_000f: ret 
}

.method private hidebysig static void M2() cil managed
{
   .maxstack 2
   .locals init (
       [0] class ConsoleApplication3.Test t,
       [1] class ConsoleApplication3.Test <>g__initLocal0)
   L_0000: nop 
   L_0001: newobj instance void ConsoleApplication3.Test::.ctor()
   L_0006: stloc.1 
   L_0007: ldloc.1 
   L_0008: ldc.i4.1 
   L_0009: callvirt instance void ConsoleApplication3.Test::set_Id(int32)
   L_000e: nop 
   L_000f: ldloc.1 
   L_0010: stloc.0 
   L_0011: ret 
}

.method private hidebysig static void M3() cil managed
{
   .maxstack 2
   .locals init (
       [0] class ConsoleApplication3.Test t,
       [1] class ConsoleApplication3.Test temp)
   L_0000: nop 
   L_0001: newobj instance void ConsoleApplication3.Test::.ctor()
   L_0006: stloc.1 
   L_0007: ldloc.1 
   L_0008: ldc.i4.1 
   L_0009: callvirt instance void ConsoleApplication3.Test::set_Id(int32)
   L_000e: nop 
   L_000f: ldloc.1 
   L_0010: stloc.0 
   L_0011: ret 
}

如果您查看程式碼,M2 和 M3 之間唯一不同的是第二個本地 ( <>g__initLocal0vs temp) 的名稱。

但正如其他人已經回答的那樣,這種差異不會產生任何你應該注意到的性能差異。

引用自:https://stackoverflow.com/questions/1509983