2010-08-20 41 views
13
private List<Date> _dates; 

public List<Date> Dates 
{ 
    get { return _dates; } 
    set { _dates = value; } 
} 

HOẶCsử dụng đúng của C thuộc tính #

public List<Date> Dates 
{ 
    get;   
    set;  
} 

Tôi đã luôn được sử dụng trước đây, là thực hành sai hay xấu? Nó không bao giờ xảy ra với tôi rằng tôi chỉ có thể sử dụng tùy chọn thứ hai. Tôi thích có các biến đóng gói của tôi để bắt đầu với dấu gạch dưới để tôi có thể phân biệt chúng với các tham số phương thức. Và tôi đã luôn luôn làm theo cách đó.

Có thể sử dụng tùy chọn đầu tiên sẽ dẫn đến một đối tượng thêm List<Date> được khởi tạo và sau đó toàn bộ _dates được thay thế bằng value hoặc thông minh hơn?

Ngoài ra, điều nổi bật nhất trong ngành hoặc là hoàn toàn chủ quan?

+0

thể trùng lặp của [C# 3.0 tự động tính - hữu ích hay không] (http://stackoverflow.com/questions/9304/c-sharp-3-0-auto- thuộc tính hữu ích hoặc không) – nawfal

Trả lời

7

Chúng tương đương với biểu mẫu được biên dịch bên trong, ngoại trừ việc bạn không thể truy cập biến riêng được tạo trong trình biên dịch ở dạng thứ hai.

Từ quan điểm mã hiệu quả, chúng tương đương nhau, trình biên dịch trong thời gian thường trực tiếp truy cập biến riêng tư mà không cần gọi hàm truy cập (sau khi môi trường thời gian chạy đã kiểm tra khả năng truy cập v.v.).

Từ góc độ mã hóa, tôi thích phiên bản thứ hai gọn hơn (ít viết hơn, ít đọc hơn).

Cú pháp thứ hai được giới thiệu trong C# 3.0. Vì vậy, biến thể đầu tiên sẽ tương thích hơn với các trình biên dịch cũ.

+0

Thông tin tốt về khả năng tương thích ngược và mã được biên dịch, cảm ơn. – Nobody

7

Cả hai đều cơ bản giống nhau vì cách .NET biên dịch các thuộc tính tự động. Các thuộc tính tự động đã có sẵn với .NET 3.5.

+1

3.0 thực sự http://msdn.microsoft.com/en-us/library/bb384054.aspx – CaffGeek

+2

@Chad C# 3.0, nhưng .NET 3.5. –

+0

touche! Tôi luôn luôn quên số phiên bản không đồng bộ – CaffGeek

19

Sử dụng tên cũ nếu bạn cần thêm một số loại logic vào bộ thu thập/giải quyết của bạn.

Sử dụng cách khác. Nó làm cho mọi thứ sạch hơn nhiều. Bạn cũng có thể đạt được chỉ đọc thuộc tính sử dụng các thuộc tính tự động:

public List<Date> Dates { get; private set; } 

Hoặc, nếu bạn không muốn mọi người thêm bất kỳ mặt hàng vào danh sách thông qua sở hữu, bạn có thể dùng đến cú pháp cũ:

private List<Date> _dates = new List<Date>(); 
private ReadOnlyCollection<Date> _readOnlyDates = 
    new ReadOnlyCollection<Date>(_dates); 

public ReadOnlyCollection<Date> Dates 
{ 
    get { return _readOnlyDates; } 
} 
+0

Tôi sẽ không tiếp tục trả về một 'ReadOnlyCollection' mới. Bên trong nó giữ một tham chiếu đến danh sách để mọi thay đổi sẽ hiển thị. – ChaosPandion

+1

Vấn đề là người gọi sẽ không thể sửa đổi nó. – recursive

+0

Tôi sẽ không gọi thuộc tính tự động với một setter riêng "chỉ đọc": nó vẫn có thể được thay đổi từ bên trong lớp mà nó được định nghĩa, tức là nó không đồng nghĩa với từ khóa 'readonly' trên các trường. –

0

Nó không quan trọng. Thứ hai chỉ là đường. Tôi luôn luôn sử dụng thứ hai bởi vì nó sạch hơn, nhưng mỗi một lần trong một thời gian tôi cần truy cập vào giá trị ủng hộ.

0

Miễn là bạn không phải đảm bảo rằng List<Date> được khởi tạo trong trình khởi động, bạn có thể sử dụng cả hai phiên bản. Tôi chỉ gợi ý rằng bạn đang sử dụng một phiên bản và bạn không pha trộn nó trong mã của bạn ...

Nếu bạn cần khởi tạo bạn phải đi cho phiên bản đầu tiên ...

private List<Date> _dates; 

public List<Date> Dates 
{ 
    get { if (_dates == null) _dates = new List<Date>(); return _dates; } 
    set { _dates = value; } 
} 
+1

Điều này thật ngớ ngẩn. Chỉ cần làm "Danh sách riêng _dates = new List ()" hoặc khởi tạo trong hàm tạo. Tôi nghi ngờ lười biếng-khởi tạo danh sách đơn giản này sẽ mua bất cứ điều gì khác hơn là mã phức tạp hơn. – siride

+1

@siride - Tôi đồng ý, bây giờ nếu bạn đang khởi tạo danh sách từ cơ sở dữ liệu là một câu chuyện hoàn toàn khác. – ChaosPandion

0

tôi tin rằng họ biên dịch thành cùng một mã. Sau này chỉ là cú pháp để đại diện cho cái cũ. Tôi có xu hướng nghĩ về sau này như một trình giữ chỗ cho logic trong tương lai mà có thể cần phải được đặt trong các thuộc tính, tại thời điểm đó tôi muốn chuyển đổi các thuộc tính bị ảnh hưởng cho trước đó.

0

Hai số này được biên dịch gần như giống nhau (Tôi không biết rằng tên của trường sao lưu sẽ giống nhau, nhưng chúng sẽ có chức năng tương đương).

IIRC, khả năng thực hiện Thuộc tính tự động (public List<Date> Dates {get; set;}) đã được thêm vào trong .NET 3.0 hoặc 3.5.

4

Tôi có xu hướng sử dụng thuộc tính tự động hơn vì thuộc tính là cách hay để thể hiện ý định về những gì đối tượng của bạn đang làm, nhưng vẫn có một số bảo vệ.

Hầu như tất cả các tờ khai tài sản của tôi trông giống như:

public bool IsBlah { get; private set; } 

này làm cho nó một getter đẹp, dễ đọc, và được bảo vệ.

Nhưng có những lúc bạn muốn có một lĩnh vực ủng hộ rõ ràng:

private bool? _isBlah; 
public bool IsBlah 
{ 
    get 
    { 
     if (_isBlah == null) 
     { 
      // Do something expensive here and set _isBlah 
      _isBlah = true; 
     } 
     return _isBlah; 
    } 
} 
1

Điều thứ nhất là cách tiếp cận ban đầu, sau này là một ví dụ về các thiết bị mới hơn 'thuộc tính tự động' theo đó trình biên dịch sẽ tạo ra một lĩnh vực sao lưu cho bạn tự động.

Một số người (trong đó có tôi) né tránh các thuộc tính tự động vì cú pháp là dễ nhầm lẫn đối với tài sản trừu tượng, không có cơ sở cho 'readonly' tài sản và cú pháp cho các thuộc tính tự động với setters tin là vụng về:

public List Dates 
{ 
    get; 
    private set; 
}

Tôi cũng cảm thấy không thoải mái khi có các trường truy cập triển khai nội bộ của lớp học thông qua API lớp học.

+0

'Tôi cũng cảm thấy không thoải mái khi có các trường truy cập triển khai nội bộ của lớp học của tôi thông qua API lớp học.' Chính xác! Tôi sẽ dính vào những gì tôi sử dụng. Cảm ơn – Nobody

1

Biến thể thứ hai được biết là auto-implemented properties và được giới thiệu trong C# 3.0 (do đó tại sao bạn có thể chưa gặp phải trước đó).

Nên sử dụng định dạng này nếu bạn muốn tạo thuộc tính đơn giản với trường sao lưu và không cần thực hiện bất kỳ logic nào trong 'getter' và 'setter'. Nó không chỉ ngắn gọn hơn, mà nó còn buộc bạn truy cập trực tiếp vào tài sản, thay vì trải qua lĩnh vực sao lưu, đó là cách thực hành tốt nhất.

Lưu ý rằng bạn vẫn có thể khởi tạo thuộc tính, bạn chỉ cần thực hiện thông qua hàm tạo.

public class MyClass 
{ 

    public List<Date> Dates 
    { 
     get;   
     set;  
    } 

    public MyClass() 
    { 
     Dates = new List<Date>(); 
    } 

} 
0

Theo như tôi có thể nhớ, tôi luôn quản lý các thuộc tính danh sách của mình từ bên trong đối tượng, làm cho chúng chỉ đọc.

private IList<DateTime> _dates; 

public MyClass() { 
    _dates = new List<DateTime>(); 
} 

public IList<DateTime> Dates { 
    get { 
     return _dates; 
    } 
} 

Bằng cách đó, tôi đảm bảo rằng danh sách của tôi là không bao giờ null khi tôi truy cập vào nó, kể từ khi khách hàng không thể gán nó.

Tuy nhiên, ví dụ của bạn, bạn chỉ cần sử dụng phương pháp tiếp cận cũ nếu bạn cần một số loại logic khi nhận hoặc đặt thuộc tính. Nếu không, các thuộc tính tự động thực hiện chính xác như bạn muốn, chỉ nhận và thiết lập một giá trị cho một trường riêng. Hơn nữa, các { get; set; } cải thiện khả năng đọc và giúp các lập trình viên khác hiểu ý định của bạn, theo quan điểm khiêm nhường của tôi.

Ví dụ:

public class MyClass { 
    private IList<DateTime> _dates; 

    public IList<DateTime> Dates { 
     get { 
      return _dates; 
     } set { 
      _dates = value; 
     } 
    } 
} 

so

public class MyClasse { 
    public IList<DateTime> Dates { get; set; } 
} 

Cách thứ hai làm cho nó gọn gàng hơn và mau lẹ hơn, ít nhất là với tôi, những gì mục đích là. Và nó trở nên nhanh hơn để mã hóa một lớp, khi không có logic bên trong getter và setter là cần thiết.

Nếu không, cái này không tốt hơn cái kia và hoàn toàn giống nhau, nói về việc nhận và đặt đơn giản giá trị của tài sản mà không có logic.

Quan trọng nhất, bạn cần phải thoải mái với mã của mình. Nếu nó kết thúc cho bạn không nhận được bất kỳ cải tiến, và bạn thích những gì bạn đang làm, hơn là chỉ làm điều đó. =)

+0

Bạn có thể thêm 'tập hợp cá nhân' vào ví dụ cuối cùng của bạn để có được kết quả tương tự với mã sạch hơn. Nhưng cũng nên nhớ đưa ra một tham chiếu đến 'IList' có nghĩa là nó không chỉ đọc, vì' IList' hỗ trợ 'Add',' Remove', 'Clear', vv Cấp, nếu người gọi của bạn thực sự muốn thay đổi danh sách, họ sẽ làm điều đó bất kể bạn đưa họ ra sao. –

+0

@Matt Greer: Vâng, thực sự! Đó thường là những gì tôi cần, có nghĩa là cho phép một để Thêm() hoặc để Hủy bỏ() từ danh sách, nếu không tôi sẽ đi cho một đối tượng cấp bậc cao hơn. Thêm vào đó, khả năng của C# đã định nghĩa một phạm vi truy cập cho trình thu thập và một phạm vi khác cho trình thiết lập, làm cho nó rất linh hoạt để làm việc với nó. Đó là một trong số nhiều thứ khác mà tôi bỏ lỡ khi làm việc với C#, vì tôi hiện đang làm việc trong VB.NET 2.0. –

1

Cá nhân tôi thích phương pháp đầu tiên vì nó cho phép bạn thực hiện một vài thao tác trước khi trả lại.

E.G. (Một ví dụ thực sự nghèo)

private int _limit; 
    private int _onHand; 
    private bool returnToVendor; 

    public Item(int limit, int onHand) 
    { 
     _limit = limit; 
     _onHand = onHand; 
    } 

    public int ReturnStock 
    { 
     get 
     { 
     if(_onHand > _limit) 
     { 
      returnToVendor = true; 
      return _onHand; 
     } 
     } 

     set 
     { 
      _onHand = value; 

      if(_onHand < _limit) 
      { 
       returnToVendor = false; 
      } 
     } 
    } 
Các vấn đề liên quan