2016-01-12 25 views
61

Tôi tạo ra một tài sản tự động:Thuộc tính tự động với chỉ getter, có thể được thiết lập, tại sao?

public int Foo { get; } 

Đây chỉ là getter. Nhưng khi tôi xây dựng một nhà xây dựng, tôi có thể thay đổi giá trị:

public MyClass(string name) 
{ 
    Foo = 5; 
} 

Tại sao nó có thể, mặc dù đây là get-chỉ?

+0

Nó không thực sự sử dụng một setter (bởi vì nó không có). Nó trực tiếp thiết lập trường cơ bản (được ẩn từ chúng tôi, đó là lý do tại sao bạn cần sử dụng tên thuộc tính) –

+10

Sử dụng nào là thuộc tính, nếu nó có thể ** không bao giờ ** được khởi tạo/thiết lập? Yacoub Massad đã trả lời nó một cách hoàn hảo – Vikhram

Trả lời

81

Đây là một C# 6 tính năng mới, "Getter chỉ tự động tính", còn được gọi là "Initializers Auto-Bất động sản Read-Only Properties" như đã thảo luận trong MSDN magazine article 'C# : The New and Improved C# 6.0' by Mark Michaelis này và trong C# 6.0 draft Language Specification.

Chỉ có thể truy cập bộ chỉ mục của trường chỉ đọc trong hàm tạo, trong tất cả các trường hợp khác, trường này vẫn chỉ đọc và hoạt động như trước.

Đây là cú pháp tiện lợi để giảm số lượng mã bạn cần nhập và loại bỏ nhu cầu khai báo rõ ràng biến số mô-đun riêng để giữ giá trị.

Tính năng này được xem là quan trọng vì việc giới thiệu Thuộc tính tự động trong C# 3, các thuộc tính có thể thay đổi (những người có bộ thu thập và thiết lập) đã nhanh hơn viết so với những người không có người thay đổi. , có nghĩa là mọi người đã bị cám dỗ để sử dụng các thuộc tính có thể thay đổi để tránh phải nhập mã cho trường sao lưu thường được yêu cầu cho thuộc tính chỉ đọc. Có nhiều cuộc thảo luận về các thuộc tính được Tự động triển khai trong các relevant section of the Microsoft C# Programming Guide.

This blog post, '#1,207 – C# 6.0 – Auto-Property Initializers for Read-Only Properties' by Sean Sexton Có một lời giải thích tốt và ví dụ như sau:

Trước C# 6.0, nếu bạn muốn có một read-only (không thay đổi) thuộc tính, bạn muốn thường sử dụng một trường chỉ đọc ủng hộ mà được khởi tạo trong hàm tạo , như được hiển thị bên dưới.

public class Dog 
{ 
    public string Name { get; set; } 

    // DogCreationTime is immutable 
    private readonly DateTime creTime; 
    public DateTime DogCreationTime 
    { 
     get { return creTime; } 
    } 

    public Dog(string name) 
    { 
     Name = name; 
     creTime = DateTime.Now; 
    } 
} 

Trong C# 6.0, bạn có thể sử dụng tính năng tự động thực hiện để thực hiện một thuộc tính chỉ đọc. Bạn thực hiện việc này bằng cách sử dụng trình khởi tạo tự động . Kết quả là sạch hơn nhiều so với ví dụ trên, trong đó chúng tôi phải khai báo rõ ràng trường sao lưu.

public class Dog 
{ 
    public string Name { get; set; } 

    // DogCreationTime is immutable 
    public DateTime DogCreationTime { get; } = DateTime.Now; 

    public Dog(string name) 
    { 
     Name = name; 
    } 
} 

Thông tin chi tiết cũng có thể được tìm thấy trong the dotnet Roslyn repo on GitHub:

Auto-tính bây giờ có thể được khai báo mà không có một setter.

Trường sao lưu của thuộc tính tự động chỉ getter được ẩn hoàn toàn được khai báo là chỉ đọc (mặc dù điều này chỉ quan trọng cho mục đích phản ánh ). Nó có thể được khởi tạo thông qua một bộ khởi tạo trên thuộc tính như trong ví dụ trên. Ngoài ra, một tài sản getter-chỉ có thể là giao cho trong cơ thể constructor kiểu tuyên bố, mà làm cho giá trị được gán trực tiếp đến lĩnh vực cơ bản:

Đây là bày tỏ những loại chính xác hơn, nhưng lưu ý rằng nó cũng loại bỏ sự khác biệt quan trọng trong ngôn ngữ giữa các loại có thể thay đổi và : các thuộc tính tự động là viết tắt chỉ có sẵn nếu bạn sẵn sàng làm cho lớp của bạn có thể thay đổi được và do đó, cám dỗ là . Giờ đây, với các thuộc tính tự động chỉ dành cho getter, trường chơi đã được cân bằng giữa tính có thể thay đổi và không thay đổi được.

và trong C# 6.0 draft Language Specification:

tính thực hiện tự động

Một tính chất tự động thực hiện (hoặc tự động tài sản cho ngắn), là một tổ chức phi trừu tượng phi extern tài sản với accessorolon-only accessor cơ quan. Thuộc tính tự động phải có trình truy cập nhận và có thể tùy chọn có bộ truy cập đã đặt.

Khi thuộc tính được chỉ định là thuộc tính được tự động triển khai, trường sao lưu ẩn tự động có sẵn cho thuộc tính, và người truy cập được triển khai để đọc và ghi vào trường sao lưu đó . Nếu thuộc tính tự động không có bộ truy cập đã đặt, trường ủng hộ được coi là chỉ đọc (các trường chỉ đọc). Cũng giống như một trường chỉ đọc chỉ đọc, một thuộc tính tự động chỉ getter cũng có thể được gán vào phần thân của một hàm tạo của lớp kèm theo. Bài tập này chỉ định trực tiếp đến trường ủng hộ chỉ đọc của thuộc tính.

Thuộc tính tự động có thể tùy ý có thuộc tính property_initializer, là được áp dụng trực tiếp vào trường sao lưu dưới dạng biến_initializer (Trình khởi tạo biến).

+0

Đây là thiết kế ngu ngốc. Đây phải là lỗi thời gian biên dịch nếu được đặt ở vị trí mà thuộc tính được coi là chỉ đọc. – Shiv

22

Đây là a new feature in C#6 cho phép bạn tạo thuộc tính chỉ đọc và khởi tạo giá trị của chúng từ hàm tạo (hoặc nội dòng khi bạn khai báo).

Nếu bạn cố gắng thay đổi giá trị của thuộc tính này bên ngoài hàm tạo, nó sẽ cung cấp cho bạn một lỗi biên dịch.

Chỉ đọc theo nghĩa là khi bạn khởi tạo giá trị của nó (nội tuyến hoặc bên trong hàm tạo), bạn không thể thay đổi giá trị của nó.

+0

Vì vậy, giải thích là gì? Định nghĩa của getter là gì? –

+1

Nó giống như một trường chỉ đọc – pseudoDust

4

Tính năng thuộc tính tự động đã được thêm vào ngôn ngữ trong khi phát hành C# 3.0. Nó cho phép bạn định nghĩa một thuộc tính mà không có bất kỳ trường sao lưu nào, tuy nhiên bạn vẫn cần sử dụng hàm tạo để khởi tạo các thuộc tính tự động này thành giá trị không mặc định. C# 6.0 giới thiệu một tính năng gọi là khởi tạo tài sản tự động mới cho phép bạn khởi tạo các tài sản mà không có một constructor như dưới đây:

Trước đây, một nhà xây dựng là cần thiết nếu bạn muốn tạo các đối tượng sử dụng một tính năng tự động tài sản và khởi tạo một tự động tài sản cho một giá trị không phải mặc định như dưới đây:

public class MyClass 
{ 
    public int Foo { get; } 

    public Foo(int foo) 
    { 
     Foo = foo; 
    } 
} 

Bây giờ trong C# 6.0, khả năng sử dụng một initializer với tính năng tự động tài sản nghĩa là không explici Mã hàm xây dựng là bắt buộc.

public string Foo { get; } = "SomeString"; 

public List<string> Genres { get; } = new List<string> { "Comedy", "Drama" }; 

You can find more information on this here

10

Nếu không thể khởi tạo thuộc tính chỉ đọc từ các nhà xây dựng (hoặc một initializer tự động tài sản), sau đó nó sẽ là vô ích, vì nó sẽ luôn luôn trả lại giá trị mặc định cho loại của nó (0 cho số, null cho các loại tham chiếu). Các ngữ nghĩa tương tự được áp dụng cho các trường readonly trong tất cả các phiên bản C#.

Để xác định một tài sản getter-chỉ đúng (mà không thể được khởi tạo từ các nhà xây dựng), bạn cần phải xác định những gì nó sẽ trả về như là một phần của định nghĩa:

public int Foo { get { return 5; } } 

Hoặc, chính xác hơn trong C# 6:

public int Foo => 5; 
+0

Không hoàn toàn đúng, chỉ đọc thuộc tính rất hữu ích để đóng gói một số điều kiện trong mã của bạn. Bạn có thể viết câu lệnh if và hầu như bất kỳ mã nào để đánh giá các thuộc tính hoặc điều kiện khác và trả về một giá trị thích hợp mỗi khi bạn đọc thuộc tính – sebagomez

+1

@sebagomez: Tôi không chắc là tôi đang nhận được ý của bạn - không phải là điều tôi thể hiện trong ví dụ của tôi? – Douglas

1

Biến được khai báo readonly có thể được viết trong một hàm tạo, nhưng trong ngôn ngữ tôn trọng thuộc tính, không thể sửa đổi sau khi hàm tạo trả về. Vòng loại đó được cung cấp dưới dạng một tính năng ngôn ngữ vì nó thường cần thiết cho các trường có giá trị sẽ thay đổi dựa trên tham số của hàm tạo (nghĩa là chúng không thể được khởi tạo trước khi hàm khởi tạo) nhưng sẽ không phải thay đổi sau khi hàm tạo trở lại. chỉ có thể sử dụng cho các biến được hiển thị dưới dạng trường. Ngữ nghĩa của readonly trường hợp đủ điều kiện sẽ trong nhiều trường hợp đã được hoàn hảo cho các thành viên công cộng ngoại trừ việc nó thường tốt hơn cho các lớp học để trưng ra các thành viên - ngay cả những người không thay đổi - như các thuộc tính chứ không phải là các trường. Cũng giống như các thuộc tính tự động đọc-ghi tồn tại để cho phép các lớp hiển thị các thuộc tính có thể thay đổi dễ dàng như các trường thông thường, các thuộc tính tự động chỉ đọc tồn tại để cho phép các lớp hiển thị các thuộc tính không thay đổi dễ dàng như readonly trường cấp đủ điều kiện. Cũng giống như readonly trường đủ điều kiện có thể được viết trong một hàm tạo, do đó, quá với các thuộc tính chỉ có.

3

“thuộc tính readonly tự động thực hiện”

Trước hết tôi muốn làm rõ rằng các tài sản như

public string FirstName { get; } 

Được biết đến như là “thuộc tính readonly tự động thực hiện”

Để xác minh điều này bạn có thể chạy & kiểm tra mã ở trên bằng Visual Studio. Nếu bạn thay đổi phiên bản ngôn ngữ từ C# 6.0 sang C# 5.0 thì trình biên dịch sẽ ném ngoại lệ sau Tính năng 'tự động chỉ đọc được thực hiện' không có sẵn trong C# 5. Vui lòng sử dụng ngôn ngữ phiên bản 6 hoặc cao hơn.

để thay đổi ngôn ngữ C# phiên bản lần here

Bây giờ tôi đến với câu hỏi thứ hai của bạn

“Đây chỉ là getter. Nhưng khi tôi xây dựng một hàm tạo, tôi có thể thay đổi giá trị ”

Microsoft giới thiệu“ các thuộc tính được tự động chỉ đọc ”trên logic chỉ đọc. Như chúng ta biết từ khóa “chỉ đọc” có sẵn từ C# 1.0. chúng tôi sử dụng từ khóa “chỉ đọc” làm công cụ sửa đổi trên trường và trường đó có thể được chỉ định trong 2 cách hoặc tại thời điểm khai báo hoặc trong một hàm tạo trong cùng một lớp.

Trong giá trị theo cùng một cách của “thuộc tính readonly tự động thực hiện” có thể được gán theo 2 cách

Way1 (tại thời điểm kê khai):

public string FirstName { get; } = "Banketeshvar"; 

Way2 (trong một người xây dựng trong cùng một lớp)

Person() 
{ 
FirstName = "Banketeshvar"; 
} 

Hoàn toàn ReadOnly tài sản

Nếu bạn đang tìm kiếm bất động sản đơn thuần chỉ đọc sau đó đi cho điều này

public string FullName => "Manish Sharma"; 

bây giờ bạn không thể gán giá trị của “FullName” Propery từ constructor. Nếu bạn cố gắng làm điều đó nó sẽ ném ngoại lệ sau

“tài sản hoặc indexer 'Person.FullName' không thể được gán cho - đó là chỉ đọc”

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