Bạn có nên sử dụng riêng tư trên các trường và phương thức trong C # không?


8

Tôi hơi mới đối với C # và chỉ phát hiện ra rằng: trong C # tất cả các trường và phương thức trong một lớp là mặc định riêng tư. Có nghĩa là điều này:

class MyClass
{

string myString

}

giống như:

class MyClass
{

private string myString

}

Vì vậy, vì chúng giống nhau nên tôi có bao giờ sử dụng từ khóa private trên các trường và phương thức không? Nhiều mẫu mã trực tuyến sử dụng từ khóa private trong mã của họ, tại sao vậy?


34
Vâng, đối với người mới bắt đầu, rõ ràng là bạn có ý định đặt trường của mình ở chế độ riêng tư, thay vì chỉ quên bao gồm một công cụ xác định phạm vi.
KChaloux

4
Tôi không thoải mái khi sử dụng private. Nó làm cho sự bất hòa về nhận thức ít hơn đối với tôi nếu tôi luôn có thể mong đợi xem công cụ xác định phạm vi là phần đầu tiên của một tuyên bố định danh. Tôi mất ít thời gian để đọc "riêng tư" hơn là tìm ra từ đầu tiên không phải là từ định nghĩa phạm vi và, ồ, điều đó có nghĩa là đó là một tuyên bố thành viên riêng. Viết mã cũng là về việc phải đọc nó sau này.
Robert Harvey

3
@RobertHarvey Nó cũng có thể hoàn toàn chủ quan; Khi viết mã bằng C ++, tôi luôn bỏ qua mọi thứ không bắt buộc, vì tôi cảm thấy nó làm tôi mất tập trung, cho đến khi tôi nhận ra rằng những người khác đọc mã của tôi có thể đã quen với các quy ước mã hóa dài dòng hơn. Vì vậy, đó là vấn đề của hương vị (trên một dự án cá nhân) và quy ước (khi hợp tác).
marczellm

2
@gnat Tôi không chắc đây là bản sao của câu hỏi đó. Bạn có chắc chắn bạn đã đăng đúng liên kết?
maple_shaft

4
@gnat Thật khó để hỏi tại sao người ta lại tuyên bố rõ ràng từ khóa riêng trong mã của họ là một câu hỏi về phong cách mã hóa. Câu hỏi này cụ thể hơn nhiều. Tôi cảm thấy rằng trong khi một câu trả lời chính tắc có thể bao gồm một câu hỏi khác, thì một câu hỏi cụ thể hơn đôi khi có thể xứng đáng với câu trả lời của chính nó.
maple_shaft

Câu trả lời:


38

Chỉ vì bạn có thể bỏ qua các nguồn cấp dữ liệu và thụt lề và trình biên dịch C # của bạn sẽ vẫn hiểu những gì bạn muốn nói với nó, nó không tự động là một ý tưởng tốt để làm điều đó.

using System; namespace HelloWorld{class 
Hello{static void Main(){Console.WriteLine
("Hello World!");}}}

là ít hơn nhiều có thể đọc được cho người đọc hơn:

using System;
namespace HelloWorld
{
    class Hello 
    {
        static void Main() 
        {
            Console.WriteLine("Hello World!");
        }
    }
}

Và đó là toàn bộ vấn đề ở đây, các chương trình giáo dục được viết cho hai đối tượng:

  • Trình biên dịch hoặc thông dịch viên.
  • Chính bạn và các lập trình viên khác.

Sau này là người cần hiểu và nhanh chóng nắm bắt ý nghĩa của những gì được viết. Bởi vì điều này có một vài thực tiễn tốt đã xuất hiện trong những năm qua và ít nhiều thường được chấp nhận theo tiêu chuẩn. Một trong số đó là đặt các từ khóa phạm vi rõ ràng, một ví dụ khác là đặt thêm dấu ngoặc đơn xung quanh các biểu thức phức tạp, ngay cả trong trường hợp không cần sử dụng cú pháp, như:

(2 + 5) & 4

2
+1 Đặc biệt cho điểm cuối cùng đó. Mặc dù các lập trình viên nói đúng nên biết thứ tự các thao tác cho ngôn ngữ của họ, tôi luôn cố gắng thêm dấu ngoặc đơn nếu có thể bởi vì trong quá khứ tôi đã thấy mình lãng phí vài giây khi cố gắng nghĩ thao tác nào đến trước và liệu một biểu thức có đánh giá được không theo cách tôi nghĩ Đôi khi câu trả lời là "Không, tôi đã nhận nó sai" và những dịp có thể tránh được việc sử dụng hợp lý các dấu ngoặc, đặc biệt là khi bạn xem xét những trường hợp như 5 + 5 * 530, không 50như một số có thể mong đợi ở cái nhìn đầu tiên.
Pharap

1
+1. Có một trục trặc tinh thần nhẹ cho tôi khi tôi không thấy các sửa đổi khả năng hiển thị rõ ràng. Tôi phải suy nghĩ trong giây lát, "Mặc định là công khai hay riêng tư?" đơn giản vì tôi luôn sử dụng các công cụ sửa đổi, và khi ai đó không sử dụng, nó sẽ loại bỏ tôi.
Greg Bair

6
Ý bạn là **private** static void Main()sao? :)
Jesse C. Choper

6

C # không phải là ngôn ngữ lập trình duy nhất cho .NET; các ngôn ngữ khác có thể và có khả năng truy cập mặc định khác nhau trong các ngữ cảnh khác nhau. Việc chỉ định privatesẽ làm cho mọi người đọc mã rõ ràng rằng khả năng truy cập đó được dự định, trong khi bỏ qua thông số kỹ thuật sẽ mở ra câu hỏi liệu thành viên có thể được sử dụng trong hội đồng [như mặc định trong VB.NET] . Rõ ràng có thể đặc biệt hữu ích nếu một người sử dụng nhiều ngôn ngữ với các quy tắc khác nhau.

Liên quan đến việc có nên privatehay protectedkhông được ủng hộ trong trường hợp không có tranh luận đặc biệt có lợi cho bên kia, quyết định nên dựa trên việc có khả năng việc phơi bày một thành viên có thể khiến cho lớp xuất phát có thể làm điều gì đó hữu ích không mặt khác sẽ không thể, hoặc nó sẽ ngăn các phiên bản tương lai của một lớp sửa đổi cấu trúc dữ liệu nội bộ của chúng theo cách hiệu quả hơn. Người ta có thể thấy các ví dụ của cả hai tình huống trong List<T>.

Trong một số trường hợp, nếu một danh sách tổng hợp (ví dụ Pointcấu trúc), có thể hữu ích để cập nhật các mục tại chỗ. Nếu List<T>tiếp xúc cửa hàng sao lưu của nó với các lớp dẫn xuất, người ta có thể dễ dàng định nghĩa EditableList<T>một phương thức:

delegate void ActByRef<T1,T2>(ref T1 p1, ref T2 p2);

void ActOnItem<TParam>(int index, ref TParam param, ActByRef<TParam> proc)
{
  .. test index, then...
  proc(ref _arr[index], ref proc);
}

mà sau đó có thể được gọi bằng cách sử dụng một cái gì đó như:

int adjustmentAmount = ...;
myList.ActOnItem(index, ref adjustmentAmount, 
  (ref Point pt, ref int dx) => pt.X += dx );

Phương pháp như vậy có thể cho phép cập nhật hiệu quả ngay cả với các loại cấu trúc tương đối lớn [vì không cần sao chép]. Việc List<T>không phơi bày nội bộ của nó làm cho không thể rút ra được một lớp có thể thực hiện một toán tử như vậy một cách hiệu quả.

Mặt khác, mặc dù cho đến nay tôi biết Microsoft vẫn chưa khai thác khả năng này, nhưng việc lưu trữ sao lưu là riêng tư sẽ giúp phiên bản tương lai có List<T>thể chia cửa hàng sao lưu thành các phần nhỏ hơn 85K khi sử dụng hầu hết dữ liệu loại, hoặc nhỏ hơn 1000 mặt hàng khi sử dụng double. Việc phân chia như vậy sẽ không thể thực hiện được nếu List<T>tiếp xúc với cửa hàng sao lưu cho các lớp dẫn xuất.


Vì các trường là riêng tư mặc định, tôi không mong đợi đầu ra Ngôn ngữ trung gian chung của trình biên dịch C # int myFieldprivate int myFieldsẽ khác. Vì vậy, tôi không tin rằng không thêm riêng tư để mở cho việc giải thích cho các ngôn ngữ .NET khác.
Roy T.

@RoyT.: Quan điểm của tôi là nếu sử dụng nhiều ngôn ngữ, có thể không rõ ràng rằng một thành viên có chỉ định truy cập bị bỏ qua được dự định có quyền truy cập mặc định trong một ngôn ngữ khác.
supercat

ah tôi hiểu rồi Bạn đã đề cập rất rõ ràng đến các ngôn ngữ .NET khác đến nỗi tôi hiểu nó là chương trình không hiểu, không phải con người.
Roy T.

1
@RoyT.: Tôi đã chỉnh sửa đoạn đầu tiên; Điều đó làm cho nó rõ ràng hơn?
supercat

2

Có, bạn nên sử dụng nó :) privateTừ khóa được sử dụng vì nó thường được chấp nhận thực hành và xóa bỏ mọi nghi ngờ về phạm vi dự định của một thành viên lớp.

Khả năng đọc là rất quan trọng với mã, đặc biệt là khi làm việc trong một nhóm. Nếu bạn muốn xem xét khả năng đọc mã hơn nữa, một cuốn sách tham khảo hay tôi có thể giới thiệu là The Elements of C # Style .


-4

Câu hỏi:

"Bạn có nên sử dụng riêng tư trên các trường và phương thức trong C # không?"

Câu trả lời nhanh:

Vâng, nhưng, nó phụ thuộc vào logic mã của bạn.

Chán dài Câu trả lời mở rộng:

Tôi đề nghị, luôn luôn chỉ định khả năng cho các thành viên.

Tôi nghĩ rằng đó là một cách tiếp cận tốt để tuyên bố các thành viên, theo mặc định, là "riêng tư".

Trong thế giới thực, tôi sử dụng "được bảo vệ", thay vào đó.

Sớm hơn, hoặc muộn hơn, thành viên ẩn đó, có thể được sử dụng bởi một lớp con.

Đôi khi, một câu hỏi hay, có thể được trả lời tốt hơn, bằng cách hỏi câu hỏi ngược lại.

Câu hỏi ngược lại, với câu hỏi của bạn, có thể là một cái gì đó như:

"Tôi có nên sử dụng công cụ sửa đổi truy cập công khai luôn trên các trường & phương thức trong C #"

Trong các ngôn ngữ lập trình khác, bạn có thể "quảng bá" được bảo vệ ra công chúng, tùy thuộc vào thiết kế của bạn.

Tôi sử dụng rất nhiều thư viện phân cấp sâu kiểm soát (trực quan), trong đó, một số thành viên (thuộc tính, methos) được yêu cầu.

Đôi khi, tốt hơn là để chúng công khai, đôi khi không.


5
Sử dụng được bảo vệ như là công cụ xác định đi của bạn có thể là xấu. Nó có khả năng mở ra siêu lớp để thao tác có thể không phù hợp, vì một lớp con có thể có thể làm việc xung quanh các kiểm tra lỗi hoặc các hạn chế được đặt trong siêu lớp. Ngay cả khi đó không phải là trường hợp, nó vẫn gây ô nhiễm các lớp con với các biến trong phạm vi bổ sung là dự phòng (ví dụ: biến được bảo vệ với một bộ truy cập hiện cung cấp hai cách để thay đổi nó trong một lớp con).

2
-1: Không cố gắng giải quyết câu hỏi.
mattnz

1
Công cộng và được bảo vệ là IMHO gần hơn tư nhân và được bảo vệ. Chúng là một phần của giao diện của lớp. Thành viên tư nhân là hộp đen chỉ trạng thái nội bộ.
Petter Nordlander

+1 vì tôi muốn khai báo riêng tư ngay cả khi không cần thiết. Mã tốt là nhiều về khả năng đọc như chức năng.
PhillyNJ

2
-1 Sử dụng bảo vệ như mặc định là lời khuyên khủng khiếp. Bạn luôn có thể tăng khả năng hiển thị của các thành viên sau này nhưng không phải là cách khác mà không vi phạm mã (khi mọi người đang sử dụng mã của bạn).
Oliver Weiler
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.