2013-06-26 33 views
38

Tôi đã học bộ khởi tạo đối tượng trong C# gần đây, nhưng bây giờ tôi tự hỏi nó hoạt động thế nào khi nó xung đột với hàm tạo.Constructor vs Object Initializer Ưu tiên trong C#

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

Điều gì xảy ra khi tôi thử tính năng này?

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

Là giá trị mặc định trong hàm tạo một cách tốt để có một bool bắt đầu đúng và có thể thay đổi?

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

Hãy thử ví dụ của bạn. –

+3

Mã của tất cả chỉ có hit chạy – Jonesopolis

+0

có nó vẫn còn hợp lệ với initializer mặc định, nhưng nếu bạn muốn nhiều hơn một tham số, tham số (s) bạn có thể quên chỉ là tham số đuôi (s). – arifnpm

Trả lời

35

Từ documentation:

Trình biên dịch các quá trình đối tượng initializers bằng cách đầu tiên truy cập vào constructor dụ mặc định và sau đó xử lý các thành viên khởi tạo.

Điều này có nghĩa là trong trường hợp đơn giản nhất (khởi tạo đối tượng) về cơ bản là viết tắt (hoặc cú pháp cú pháp) để gọi hàm khởi tạo mặc định và sau đó gọi (các) trình tạo thuộc tính. Trong trường hợp các kiểu vô danh, kiểu khởi tạo này thực sự được yêu cầu và không chỉ là đường.

Đối với phần thứ hai của câu hỏi của bạn: Đó là một vấn đề về phong cách nhưng nếu bạn có tài sản quan trọng, tôi sẽ không tạo một hàm tạo với giá trị mặc định. Làm cho mã máy khách đặt giá trị một cách rõ ràng. Tôi cũng không chắc chắn tại sao làm một cái gì đó như thế này: b = A(true) {foo = false}; sẽ là một ý tưởng tốt, trừ khi bạn đang ở trong một cuộc thi obfuscation mã.

Bit thận trọng mặc dù:

... nếu constructor mặc định được khai báo là tin trong lớp, initializers đối tượng yêu cầu truy cập công cộng sẽ thất bại.

15

Hàm khởi tạo xảy ra trước rồi khởi tạo đối tượng. Chỉ cần nhớ rằng

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

là giống như

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

Chúng không giống nhau. 'a = new A(); a.foo = false; 'để lại một nửa đối tượng được khởi tạo nếu một ngoại lệ được ném trong khi đưa ra các giá trị cho các thuộc tính của nó. Và việc sử dụng các thành viên đối tượng sẽ cho kết quả không mong muốn (chúng sẽ sử dụng các giá trị mặc định của các kiểu cơ bản, ví dụ: false cho các thành viên boolean) thay vì ném NullReferenceException. Mặt khác, sử dụng Object Initializer hoặc Object constructors sẽ đảm bảo rằng nếu một ngoại lệ xảy ra, đối tượng sẽ không được khởi tạo và sẽ cho NullReferenceException nếu chúng ta cố gắng sử dụng thành viên của nó (vì nó chưa bao giờ được khởi tạo). – WaelAlshabani

+2

@WaelAlshabani Có, có một đối tượng tạm thời được tạo và sau đó thuộc tính được đặt thành nó trước khi tham chiếu được gán cho biến đó. Và có, đó là một sự khác biệt tinh tế nhưng quan trọng nếu tài sản của bạn có thể ném một ngoại lệ và bạn định bắt nó và vẫn sử dụng tham chiếu được gán cho biến vì một lý do nào đó. Nhưng không ai trong số đó áp dụng cho ví dụ chính xác này. Nhưng tôi sẽ cập nhật để làm cho điều này rõ ràng hơn. – juharr

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

là một cách hiệu quả viết tắt của:

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

nơi temp là một biến số khác không thể tiếp cận. Hàm khởi tạo luôn được thực thi đầu tiên, theo sau là bất kỳ thuộc tính khởi tạo nào.

2

Về cơ bản những gì Phaolô đã liên kết:

Từ 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

Object initializers chỉ là cú pháp đường, trong hội đồng biên soạn ur IL họ chuyển thành báo cáo riêng biệt, kiểm tra nó trên ILSpy.

enter image description here

Các vấn đề liên quan