2016-05-08 13 views
5

Ví dụ, tôi có một loại bất biếnloại bất di bất dịch với đối tượng initializer cú pháp

class Contact 
{ 
    // Read-only properties. 
    public string Name { get; } 
    public string Address { get; } 
} 

Và tôi hy vọng tôi có thể sử dụng cú pháp đối tượng khởi tạo để tạo ra một Liên

Contact a = new Contact { Name = "John", Address = "23 Tennis RD" }; 

Nhưng tôi không thể. Bất kỳ cách nào có thể để sử dụng cú pháp khởi tạo đối tượng mạnh trong trường hợp này?

Trả lời

4

Điều gần nhất sẽ là một nhà xây dựng với các thông số tùy chọn:

class Contact 
{ 
    public string Name { get; } 
    public string Address { get; } 
    public Contact(string name = null, string address = null) { 
     Name = name; 
     Address = address; 
    } 
} 

Sau đó, bạn có thể gọi nó với tên tham số:

new Contact(
    name: "John", 
    address: "23 Tennis RD" 
) 

Cú pháp là hơi khác nhau từ một initializer đối tượng, nhưng nó cũng như có thể đọc được; và IMO, sự khác biệt là một điều tốt, bởi vì các tham số của hàm tạo có xu hướng đề xuất các thuộc tính bất biến. Và bạn có thể chỉ định các tham số theo thứ tự bất kỳ, hoặc để lại một số, vì vậy nó chỉ mạnh mẽ như cú pháp khởi tạo đối tượng.

Điều này đòi hỏi một số mã phụ (xác định hàm tạo, gán tất cả các thuộc tính), vì vậy nó hoạt động nhiều hơn cú pháp khởi tạo đối tượng. Nhưng không quá khủng khiếp, và giá trị của những vật thể bất biến là đáng giá.

(Đối với những gì nó có giá trị, C# 7 có thể nhận được immutable "record types" có cú pháp đơn giản hơn nhiều Đây có thể hoặc không thể làm cho nó thành phiên bản chính thức, nhưng họ âm thanh khá mát mẻ..)

0

Trình khởi tạo đối tượng trước tiên sẽ xây dựng đối tượng, sau đó đặt giá trị thuộc tính. Nó cần setters.

Đó là tay viết tắt của:

Contact a = new Contact(); 
a.Name = "John"; 
a.Address = "23 Tennis RD"; 

Một lĩnh vực readonly không thể có nó là giá trị thiết lập một khi đối tượng đã được xây dựng. Để có lớp đó không thay đổi, bạn sẽ cần phải tạo một hàm tạo để lấy các giá trị đó:

class Contact // Immutable class 
{ 
    // Read-only properties. 
    public string Name { get; } 
    public string Address { get; } 
    public Contact(string name, string address) 
    { 
     this.Name = name; 
     this.Address = address; 
    } 
} 
+0

Tôi cần setters - nope nó không phải! Nó yêu cầu quyền truy cập ghi trên trường hoặc thích hợp. Trong trường hợp của một tài sản nó thực sự cần một setter. Trong trường hợp của một trường, nó không thể là tĩnh hoặc chỉ đọc được. –

+0

Chính xác. Lý do tại sao tôi nói: "sau đó đặt giá trị thuộc tính, yêu cầu setter". Ngay cả với một setter công cộng, nếu các lĩnh vực sao lưu là chỉ đọc, cố gắng để viết cho nó thậm chí sẽ không biên dịch. –

1

Không, bạn không thể sử dụng nó với các thuộc tính chỉ đọc.
Dưới đây là các loại thuộc tính và trường khác nhau trong so sánh.

public class sometype { 
    public int readonlyProp{ 
     get; 
    } 
    public int normalProp { 
     get; 
     set; 
    } 

    public const int constField = 3; 
    public readonly int readonlyField = 3; 
    public int normalField = 3; 

    public void test() { 
     sometype test = new sometype() { readonlyProp = 3}; //  Doesn't work -> Property or indexer is readonly 
     sometype test1 = new sometype() { normalProp = 3 }; //  ok 
     sometype test2 = new sometype() { constField = 3 }; //  Doesn't work -> Static field or property 
     sometype test3 = new sometype() { readonlyField = 3 }; // Doesn't work -> readonly field 
     sometype test4 = new sometype() { normalField = 3 }; //  ok 
    } 
} 

Điều quan trọng là phải hiểu rằng các trường const được coi là tĩnh và do đó không phải là thành viên cá thể. Và kể từ khi khởi tạo đối tượng được sử dụng cho các thành viên ví dụ này không hoạt động.

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