簡體   English   中英

C#中的構造函數與對象初始值設定項的優先級

[英]Constructor vs Object Initializer Precedence in C#

我最近一直在學習 C# 中的對象初始值設定項,但現在我想知道當它與構造函數沖突時它是如何工作的。

public class A
{
    public bool foo { get; set; }

    public A()
    {
        foo = true;
    }

    public A(bool bar)
    {
        foo = bar;
    }
}

當我嘗試這個時會發生什么?

public class B
{
    private A a = new A() { foo = false };

    private A b = new A(true) { foo = false };
}

構造函數中的默認值是否是讓bool開始為 true 並且可以更改的好方法?

public A(bool bar = true)
{
    foo = bar;
}

文檔

編譯器通過首先訪問默認實例構造函數然后處理成員初始化來處理對象初始值設定項。

這意味着在最簡單的情況下(命名對象初始化),它基本上是調用默認構造函數然后調用屬性設置器的簡寫(或語法糖)。 在匿名類型的情況下,這種初始化實際上是必需的,而不僅僅是糖。

對於您問題的第二部分:這更多是風格問題,但如果您有一個關鍵屬性,我不會創建具有默認值的構造函數。 使客戶端代碼顯式設置該值。 我也不知道為什么要這樣做: b = A(true) {foo = false}; 除非您參加代碼混淆競賽,否則這將是一個好主意。

不過要小心一點:

...如果默認構造函數在類中聲明為私有,則需要公共訪問的對象初始值設定項將失敗。

對象初始值設定項只是語法糖,在您編譯的程序集 IL 中,它們轉換為單獨的語句,請在ILSpy檢查

在此處輸入圖片說明

構造函數首先出現,然后是對象初始值設定項。 只要記住

a = new A() { foo = false };

var temp = new A();
temp.foo = false;
a = temp;
b = new A(true) {foo = false};

是有效的縮寫:

A temp = new A(true);
temp.foo = false;
A b = temp;

其中temp是一個否則無法訪問的變量。 構造函數總是首先執行,然后是任何初始化的屬性。

基本上保羅已經鏈接的內容:

來自C# 5 語言規范(7.6.10.1)

包含對象初始值設定項或集合初始值設定項的對象創建表達式的處理包括首先處理實例構造函數,然后處理由對象初始值設定項或集合初始值設定項指定的成員或元素初始化。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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