Sự khác biệt về C # giữa các kiểu getter khác nhau


154

Đôi khi tôi thấy viết tắt trong các thuộc tính cho getter. Ví dụ: hai loại đó:

public int Number { get; } = 0

public int Number => 0;

Ai đó có thể vui lòng cho tôi biết nếu có bất kỳ sự khác biệt giữa hai. Họ cư xử thế nào? Cả hai đều chỉ đọc?

Câu trả lời:


266

Vâng, cả hai đều chỉ đọc, nhưng có một sự khác biệt. Trong trường đầu tiên, có một trường sao lưu được khởi tạo thành 0 trước khi hàm tạo được thực thi. Bạn chỉ có thể thay đổi giá trị trong hàm tạo , giống như trường chỉ đọc thông thường. Bản thân getter chỉ trả về giá trị của trường.

Trong cái thứ hai, getter chỉ trả về 0 mỗi lần, không có trường nào liên quan.

Vì vậy, để tránh sử dụng bất kỳ thuộc tính được thực hiện tự động hoặc các thành viên thân biểu hiện nào, chúng tôi có:

Phiên bản đầu tiên

private readonly int _number = 0;
public int Number { get { return _number; } }

Phiên bản thứ hai

public int Number { get { return 0; } }

Một ví dụ rõ ràng hơn về sự khác biệt có thể được nhìn thấy như thế này:

public DateTime CreationTime { get; } = DateTime.UtcNow;
public DateTime CurrentTime => DateTime.UtcNow;

Nếu bạn tạo một đối tượng, thuộc tính của nó CreationTimesẽ luôn cho kết quả tương tự - bởi vì nó được lưu trữ trong trường chỉ đọc, được khởi tạo khi xây dựng đối tượng. Tuy nhiên, mỗi khi bạn truy cập vào CurrentTimetài sản, điều đó sẽ DateTime.UtcNowđược đánh giá, do đó bạn sẽ nhận được một kết quả khác.


23
Xin lưu ý rằng phiên bản thứ hai không phải lúc nào cũng trả về cùng một giá trị. Một ví dụ điển hình là nếu bạn quay trở lại random.NextInt(). Phiên bản đầu tiên sẽ đánh giá rằng một lần và luôn có cùng giá trị. Thứ hai sẽ trả về một giá trị mới mỗi lần.

248

Một sự khác biệt là khi điều đó 0được đánh giá: khi tạo đối tượng hoặc khi tài sản được sử dụng.

Bạn có thể thấy điều này tốt hơn với các thuộc tính DateTime:

class SomeTestClass
{
    public DateTime Start { get; } = DateTime.Now;

    public DateTime Now => DateTime.Now;
}

Các Startbất động sản tiếp tục quay trở lại cùng một lúc (trong khi các trường hợp đã được tạo ra), trong khi Nowthay đổi để phản ánh thời gian hiện tại.

Giải thích :

Phiên bản đầu tiên ("Bắt đầu") cung cấp một giá trị ban đầu thậm chí có thể được ghi đè bởi nhà xây dựng. Vì vậy, điều này được đánh giá chỉ một lần.
Phiên bản thứ hai ("Bây giờ") cung cấp biểu thức sẽ là "getter" của thuộc tính này. Vì vậy, điều này được đánh giá mỗi khi tài sản được đọc. Thậm chí không có trường sao lưu mà hàm tạo có thể ghi đè.


26
Đây là sự phân biệt quan trọng nhất tôi nghĩ.
Matthew

14
Câu trả lời được chấp nhận xác định chính xác nhất sự khác biệt trong mã ví dụ, nhưng điều này giải thích sự khác biệt hữu ích hơn trong hai cấu trúc.
Kamil Drakari

3
Ồ, bạn đã nhận được nhiều phiếu bầu hơn chính Jon Skeet nổi tiếng.
máy_1

21

Đây là các tính năng ngôn ngữ C # 6.

Ví dụ đầu tiên

public int Number { get; } = 0

Ví dụ đầu tiên là một thuộc tính tự động chỉ getter . Trường sao lưu của thuộc tính tự động chỉ getter được khai báo ngầm là chỉ đọc.

Ví dụ thứ hai

public int Number => 0;

Và ví dụ thứ hai là các biểu thức trên các thành viên hàm giống như thuộc tính . Lưu ý rằng không có bất kỳ gettừ khóa nào : Nó được ngụ ý bởi việc sử dụng cú pháp thân biểu thức.

Cả hai đều chỉ đọc.


5
... nhưng như Jon Skeet giải thích, bạn có thể thay đổi giá trị mà cái đầu tiên trả về.
Martin Bonner hỗ trợ Monica

2
@MartinBonner ... nhưng chỉ trong hàm tạo.
Dennis Kuypers

5
hoặc, như mọi khi, thông qua sự phản chiếu (nitpicking nhỏ)
Marco Mp
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.