2011-06-07 79 views
3

爲什麼這個代碼輸出50的值?C# - 爲什麼不構造函數寫入初始化值?

class Program 
{ 
    static void Main(string[] args) 
    { 
     var myClass = new TestConstructor() { MyInt = 50 }; 
    } 
} 

class TestConstructor 
{ 
    public int MyInt { get; set; } 

    public TestConstructor() 
    { 
     Console.WriteLine(this.MyInt); 
     Console.Read(); 
    } 
} 
+0

一般來說它是壞主意,使用性能和especia從構造函數中提取虛擬方法。我認爲這是Microsoft試圖通過允許不可見字段變量支持屬性並強制僅通過這些屬性進行訪問來簡化屬性的結果。 – ja72 2011-06-07 14:32:42

+1

@ ja72:爲什麼你不使用屬性,當他們是非虛擬的?我同意從構造函數調用虛擬方法的風險,但屬性應該沒問題。特別是,來自構造函數的*設置*屬性是完全正常的。 – 2011-06-07 15:08:06

+0

@Jon - 我明白了你的觀點,但是當字段可用時,仍然讓我不自在地使用構造函數中的屬性。基本類屬性可能需要字段是私有的(但是應該首選':base(...)'語法)。也許我不夠務實......哦,好吧。 – ja72 2011-06-08 01:13:53

回答

11

此代碼:

var myClass = new TestConstructor() { MyInt = 50 }; 

有效地轉化爲:

var tmp = new TestConstructor(); 
tmp.MyInt = 50; 
var myClass = tmp; 

你怎麼會想到要設置的屬性的構造函數之前被執行?

(在這裏使用一個臨時變量的是在這種情況下並不重要,但它可以在其他情況下:

var myClass = new TestConstructor { MyInt = 50 }; 
myClass = new TestConstructor { MyInt = myClass.MyInt + 2 }; 

在第二行中,很重要的一點myClass.MyInt還是指第一對象,而不是新創建的一個。)

10

這一段代碼首先構造的類,並且然後 50賦予MyInt屬性,Console.WriteLine已經被執行。

1

由於您首先使用的語法會創建對象並調用構造函數,然後設置您的值。

1

您正在調用新的TestConstructor(),並且只有在您第二次坐下時!

3

您使用object initializer基本上轉化爲這樣:

var temp = new TestConstructor(); 
temp.MyInt = 50; 
var myClass = temp; 

的屬性被設置後的構造完成。如果你想確保財產在構造函數中設置你需要提供一個接受參數的構造函數:

public TestConstructor(int myInt) 
{ 
    MyInt = myInt; 
    Console.WriteLine(MyInt); 
} 

以下方式使用它會顯示所提供的整數控制檯窗口:

var myClass = new TestConstructor(50); 
+0

更確切地說,它被翻譯成臨時創建,然後是構造函數調用,然後是賦值給屬性,然後是臨時賦值給變量。看Jon的答案。 – 2011-06-07 16:51:05

+0

@Eric感謝您的反饋。更新了準確性。 – 2011-06-07 17:20:33

1

當使用像您使用的對象初始值設定項時,首先調用默認構造函數,然後設置您設置的各種屬性和字段。

這意味着,你可能看到的default(int)值在控制檯這裏,因爲你不設置在構造本身的價值。

+0

這裏你說的「價值設定構造函數」究竟是什麼意思?我懷疑你的意思是「一個對象初始值設定項」,但值得說明。 – 2011-06-07 14:30:51

+0

當我找到它時,我正要忍者編輯這個詞。 :-) – 2011-06-07 14:34:44

2

你的代碼翻譯成

var myClass = new TestConstructor(); //Here occures Console.Write(). myInt is 0 now 
myClass.MyInt = 50;