2013-06-26 105 views
38

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

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

當我嘗試此操作時會發生什麼?

public class B 
{ 
    a = A() {foo = false}; 
    b = A(true) {foo = false}; 
} 

在構造函數中默認有一個bool啓動真正的和可以改變的好辦法?

public A(bar=true) 
{ 
    foo = bar; 
} 
+18

試試你的例子。 –

+3

代碼全部只是運行 – Jonesopolis

+0

是的,它仍然對默認初始化程序有效,但是如果你想要多個參數,你可以忘記的參數只是尾部參數。 – arifnpm

回答

35

documentation

編譯器處理由第一訪問 默認實例構造函數,然後處理所述構件 初始化對象初始化。

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

對於你的問題的第二部分:它更多的是風格的問題,但如果你有一個關鍵的屬性,我不會創建一個默認值的構造函數。使客戶端代碼明確設置值。我也不確定爲什麼要這樣做:b = A(true) {foo = false};會是一個好主意,除非您在代碼混淆比賽中。

謹慎位,但:

...如果默認構造函數聲明爲類私有的,需要公共接入 對象初始化將失敗。

15

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

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

是相同

var temp = new A(); 
temp.foo = false; 
a = temp; 
+0

他們不一樣。 'a = new A(); a.foo = false;'如果在給它的屬性賦值的時候拋出異常,則保持對象一半被初始化。而使用對象成員會給出意想不到的結果(他們將使用基礎類型的默認值,例如布爾成員爲false)而不是拋出NullReferenceException。 另一方面,使用Object Initializer或Object構造函數將確保如果發生異常,對象將不會被初始化,並且如果我們嘗試使用它的成員(因爲它從未被初始化),將會給予NullReferenceException。 – WaelAlshabani

+2

@WaelAlshabani是的,有一個臨時對象被創建,然後該屬性被設置爲它,然後它的引用被分配給該變量。是的,如果你的屬性可能拋出一個異常,並且你打算捕捉異常並且由於某種原因仍然使用分配給該變量的引用,那麼這是一個微妙但重要的區別。但沒有一個適用於這個確切的例子。但我會更新以使其更清楚。 – juharr

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

是有效簡稱:

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

其中temp是一個難以接近的變量。構造函數總是先執行,後面是任何初始化的屬性。

2

本質保羅已經鏈接:

C# 5 language specification(7.6.10.1)

Processing of an object creation expression that includes an object initializer or 
collection initializer consists of first processing the instance constructor and then 
processing the member or element initializations specified by the object initializer or 
collection initializer. 
24

對象初始只是語法糖,在烏拉圭回合編譯的程序集IL它們轉換成單獨的語句,檢查ILSpy

enter image description here

相關問題