Trong cuốn sách xuất sắc của mình, CLR Via C #, Jeffrey Richter nói rằng ông không thích tài sản và khuyến cáo không nên sử dụng chúng. Anh ấy đưa ra một số lý do, nhưng tôi không thực sự hiểu. Bất cứ ai có thể giải thích cho tôi tại sao tôi nên hoặc không nên sử dụng thuộc tính? Trong C # 3.0, với thuộc tính tự động, điều này có thay đổi không?
Để tham khảo, tôi đã thêm ý kiến của Jeffrey Richter:
• Một thuộc tính có thể ở chế độ chỉ đọc hoặc chỉ ghi; truy cập trường luôn có thể đọc và ghi được. Nếu bạn xác định một thuộc tính, tốt nhất là cung cấp cả hai phương thức truy cập get và set.
• Một phương thức thuộc tính có thể đưa ra một ngoại lệ; truy cập trường không bao giờ ném một ngoại lệ.
• Một thuộc tính không thể được truyền dưới dạng tham số out hoặc ref cho một phương thức; một lĩnh vực có thể. Ví dụ: mã sau sẽ không biên dịch:
using System;
public sealed class SomeType
{
private static String Name
{
get { return null; }
set {}
}
static void MethodWithOutParam(out String n) { n = null; }
public static void Main()
{
// For the line of code below, the C# compiler emits the following:
// error CS0206: A property or indexer may not
// be passed as an out or ref parameter
MethodWithOutParam(out Name);
}
}
• Một phương thức thuộc tính có thể mất nhiều thời gian để thực thi; truy cập trường luôn hoàn thành ngay lập tức. Một lý do phổ biến để sử dụng thuộc tính là thực hiện đồng bộ hóa luồng, điều này có thể dừng luồng mãi mãi và do đó, không nên sử dụng thuộc tính nếu đồng bộ hóa luồng được yêu cầu. Trong tình huống đó, một phương pháp được ưu tiên hơn. Ngoài ra, nếu lớp của bạn có thể được truy cập từ xa (ví dụ: lớp của bạn có nguồn gốc từ System.MashalByRefObject), việc gọi phương thức thuộc tính sẽ rất chậm và do đó, một phương thức được ưu tiên hơn một thuộc tính. Theo tôi, các lớp có nguồn gốc từ MarshalByRefObject không bao giờ được sử dụng thuộc tính.
• Nếu được gọi nhiều lần liên tiếp, một phương thức thuộc tính có thể trả về một giá trị khác nhau mỗi lần; một trường trả về cùng một giá trị mỗi lần. Lớp System.DateTime có thuộc tính readonly Now trả về ngày và giờ hiện tại. Mỗi lần bạn truy vấn thuộc tính này, nó sẽ trả về một giá trị khác. Đây là một sai lầm và Microsoft mong muốn rằng họ có thể sửa lớp này bằng cách biến Now thành một phương thức thay vì một thuộc tính.
• Một phương pháp đặc tính có thể gây ra các phản ứng phụ có thể quan sát được; truy cập thực địa không bao giờ làm. Nói cách khác, người dùng của một loại sẽ có thể đặt các thuộc tính khác nhau được xác định bởi một loại theo bất kỳ thứ tự nào mà họ chọn mà không nhận thấy bất kỳ hành vi khác nhau nào trong loại.
• Một phương thức thuộc tính có thể yêu cầu thêm bộ nhớ hoặc trả về một tham chiếu đến một cái gì đó không thực sự là một phần của trạng thái của đối tượng, vì vậy việc sửa đổi đối tượng được trả về không có ảnh hưởng gì đến đối tượng ban đầu; truy vấn một trường luôn trả về một tham chiếu đến một đối tượng được đảm bảo là một phần của trạng thái của đối tượng ban đầu. Làm việc với một thuộc tính trả về một bản sao có thể rất khó hiểu đối với các nhà phát triển và đặc điểm này thường không được ghi lại.