2009-11-09 42 views
5

Trong Visual Studio 2008 Team System, tôi vừa chạy Phân tích mã (từ trình đơn Phân tích) trên một trong các dự án C# của tôi. Một trong những cảnh báo được tạo ra như sau:Trường C# được bảo vệ thành riêng tư, thêm thuộc tính - tại sao?

Microsoft.Design: Vì trường 'Connection._domain' hiển thị ở chế độ riêng tư và thêm thuộc tính, với khả năng truy cập tương tự như hiện tại, để cung cấp quyền truy cập vào trường đó.

Nó đề cập đến các lĩnh vực sau:

public abstract class Connection 
{ 
    protected string _domain; 
} 

Tôi không hiểu lý do đằng sau sự gợi ý. Đây là những gì tôi nghĩ rằng nó muốn tôi phải làm:

public abstract class Connection 
{ 
    private string _domain; 
    protected string Domain { get { return _domain; } set { _domain = value; } } 
} 

Hai câu hỏi:

  1. Tôi đã hiểu một cách chính xác những gì các gợi ý muốn tôi làm, mã khôn ngoan?
  2. Tại sao tôi muốn tôi làm điều này?
+0

Xem thêm http://stackoverflow.com/questions/1410645/are-public-fields-ever-ok, http://stackoverflow.com/questions/480627/why-wont-anyone-accept-public-fields -in-c, http://stackoverflow.com/questions/1277572/should-i-use-public-properties-and-private-fields-or-public-fields-for-data và một vài mục khác (tìm kiếm trên 'công khai lĩnh vực'). Tất cả đều thảo luận về lĩnh vực công cộng nhưng thường áp dụng cho các lĩnh vực được bảo vệ là tốt. –

Trả lời

13

Vâng, tôi nghĩ rằng bạn hiểu một cách chính xác - mặc dù trong các phiên bản sau này của C#, có một cách ngắn gọn hơn để viết nó:

public string Domain { get; set; } 

Tại sao? Đó là tất cả về đóng gói. Nếu bạn làm như nó gợi ý, sau này bạn có thể thay đổi định nghĩa của thuộc tính Miền mà không ảnh hưởng đến bất kỳ mã gọi nào sử dụng thuộc tính đó. Vì lớp của bạn là công khai và có thể được gọi bằng mã mà bạn không viết, điều đó có khả năng khá quan trọng.

+0

trong trường hợp của anh ta, 'chuỗi ký tự được bảo vệ {get; bộ; } ' – nawfal

2

Đúng. Đó là gợi ý. Bạn không nên có bất kỳ khả năng truy cập nào cao hơn mức riêng tư được hiển thị dưới dạng trường mẫu trực tiếp.

Đó là một trong những nguyên tắc chính của OOD - đóng gói cũng được gọi là 'ẩn dữ liệu'.

2
  1. Có, bạn đã sửa mã vấn đề một cách khôn ngoan.
  2. Đó là về đóng gói. _domain là dữ liệu về đối tượng của bạn. Thay vào đó, để lộ nó trực tiếp để bất kỳ khách hàng nào có quyền truy cập chưa được lọc, bạn nên cung cấp một giao diện để họ truy cập nó. Thực tế điều này có thể là thêm xác nhận hợp lệ cho trình thiết lập để nó không thể được đặt thành bất kỳ giá trị nào. Nó có vẻ ngớ ngẩn nếu bạn là người duy nhất viết mã bởi vì bạn biết cách hoạt động của API. Nhưng hãy cố gắng suy nghĩ về mọi thứ ở cấp độ doanh nghiệp lớn, tốt hơn là nên có một API để đối tượng của bạn có thể được xem như là một hộp chứa accomiplishes một nhiệm vụ. Bạn có thể nói rằng bạn sẽ không bao giờ có nhu cầu thêm một cái gì đó như xác nhận cho đối tượng đó, nhưng mọi thứ được thực hiện theo cách đó để giữ cho khả năng của nó, và cũng phải nhất quán.
2

Điều này là do nếu bạn muốn thay đổi trường thành thuộc tính trong tương lai, bạn sẽ phá vỡ bất kỳ hội đồng nào khác phụ thuộc vào nó. Bạn có thể tùy chọn thêm xác thực hoặc logic khác trong tương lai mà không cần biên dịch lại tất cả người tiêu dùng (hoặc trong trường hợp này là người kế thừa) của lớp học của bạn.

+0

Tại sao lại là downvote? Về mặt kỹ thuật điều này là đúng. IL để truy cập một lĩnh vực khác với khi truy cập một proprty. Nếu bạn biên dịch một assembly (A) tham chiếu các trường trong một assembly khác (B), sau đó cập nhật assembly (B) và thay đổi các trường thành thuộc tính, assembly (A) sẽ bị hỏng. – Bob

+0

Tôi đồng ý, Bob, tôi nghĩ đây là một điều rất quan trọng. (+1) Thay đổi một trường thành thuộc tính (vì bạn muốn thêm logic hợp lệ hoặc ghi nhật ký hoặc muốn biến nó thành ảo, hoặc bất kỳ lý do nào khác có thể có) là một thay đổi phá vỡ nhị phân đối với bất kỳ người dùng nào của lớp. Nó cũng có khả năng là một ngắt cấp nguồn nếu bạn đặt tên trường của bạn là chữ thường và thuộc tính chữ hoa, như là quy ước. – Joren

+0

Và đó là lý do tại sao bạn nên sử dụng tài sản. Nếu nó không phải là trường hợp sau đó sẽ không có lý do để sử dụng tài sản cho đến khi bạn quyết định bạn cần chúng. Tôi nghĩ rằng đã trả lời câu hỏi/nhún vai :) – GraemeF

2

Bản dịch của bạn là chính xác.Đối số tương tự cho có thể được thực hiện để sử dụng các thuộc tính 'được bảo vệ' có thể được thực hiện để sử dụng các thuộc tính 'công khai' thay vì hiển thị trực tiếp các biến thành viên.

Nếu điều này chỉ dẫn đến sự gia tăng của getters và setters đơn giản sau đó tôi nghĩ rằng thiệt hại mã readablity outweighs lợi ích của việc có thể thay đổi mã trong tương lai. Với sự phát triển bất động sản trình biên dịch tạo ra trong C# đây không phải là khá xấu như vậy, chỉ cần sử dụng:

protected string Domain { get; set; } 
0

Trong câu trả lời cho câu hỏi của bạn ... vâng.

Tuy nhiên, tôi sẽ chỉ sử dụng cú pháp tự động bất động sản:

public abstract class Connection 
{ 
    protected string Domain { get; set; } 
} 
0

Về cơ bản, tính chất cung cấp nhiều hơn trở về hoặc thiết lập một thành viên. Chúng cho phép bạn thêm logic có thể xác minh định dạng đầu vào thích hợp, xác thực phạm vi, v.v.

Câu trả lời được chọn từ liên kết đặt tốt nhất, "Thuộc tính cung cấp đóng gói. Bạn có thể đóng gói bất kỳ xác thực/định dạng/chuyển đổi cần thiết nào Điều này sẽ gây khó khăn cho các lĩnh vực. "

http://social.msdn.microsoft.com/Forums/en-IE/netfxbcl/thread/985f4887-92ae-4ec2-b7ae-ec8cc6eb3a42

0

Bên cạnh những câu trả lời khác đề cập ở đây, công chúng/Các thành viên protected bắt đầu với một dấu gạch dưới không CLS-compliant, trong đó không có yêu cầu cho các ngôn ngữ .NET để hỗ trợ các thành viên với dấu gạch hàng đầu, vì vậy một người nào đó kế thừa từ lớp của bạn bằng ngôn ngữ .NET khác nhau có thể không truy cập được thành viên được bảo vệ cụ thể đó.

Tôi biết, nó có thể không áp dụng cho bạn, nhưng nó có thể là một phần lý do cho cảnh báo phân tích mã.

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