Người ta thường thấy một _var
tên biến trong trường lớp. Dấu gạch dưới có nghĩa là gì? Có một tài liệu tham khảo cho tất cả các quy ước đặt tên đặc biệt?
Người ta thường thấy một _var
tên biến trong trường lớp. Dấu gạch dưới có nghĩa là gì? Có một tài liệu tham khảo cho tất cả các quy ước đặt tên đặc biệt?
Câu trả lời:
Gạch dưới chỉ đơn giản là một quy ước; chỉ có bấy nhiêu thôi. Như vậy, công dụng của nó luôn có phần khác nhau đối với mỗi người. Đây là cách tôi hiểu chúng cho hai ngôn ngữ trong câu hỏi:
Trong C ++, dấu gạch dưới thường chỉ ra biến thành viên riêng.
Trong C #, tôi thường thấy nó chỉ được sử dụng khi xác định biến thành viên riêng bên dưới cho một thuộc tính công cộng. Các biến thành viên tư nhân khác sẽ không có dấu gạch dưới. Việc sử dụng này phần lớn đã đi vào lối mòn với sự ra đời của các thuộc tính tự động.
Trước:
private string _name;
public string Name
{
get { return this._name; }
set { this._name = value; }
}
Sau:
public string Name { get; set; }
public string Name { get; private set; }
. Đúng, nó không hoàn toàn bất biến, nhưng nó ở đó.
_var
không được bảo lưu.
Cách tốt nhất là KHÔNG sử dụng UNDERSCORES trước bất kỳ tên biến hoặc tên tham số nào trong C ++
Các tên bắt đầu bằng dấu gạch dưới hoặc dấu gạch dưới kép được ĐẶT CH for cho người triển khai C ++. Tên có dấu gạch dưới được dành riêng cho thư viện để làm việc.
Nếu bạn đã đọc ở Tiêu chuẩn mã hóa C ++, bạn sẽ thấy điều đó trong trang đầu tiên có ghi:
"Đừng đặt tên quá mức, nhưng hãy sử dụng quy ước đặt tên nhất quán: Chỉ có hai tên bắt buộc: a) không bao giờ sử dụng" tên ngầm ", bắt đầu bằng dấu gạch dưới hoặc có dấu gạch dưới kép;" (p2, Tiêu chuẩn mã hóa C ++, Herb Sutter và Andrei Alexandrescu)
Cụ thể hơn, dự thảo làm việc của ISO nêu các quy tắc thực tế:
Ngoài ra, một số định danh được dành riêng để sử dụng cho việc triển khai C ++ và không được sử dụng theo cách khác; không cần chẩn đoán. (a) Mỗi mã định danh có dấu gạch dưới kép __ hoặc bắt đầu bằng dấu gạch dưới theo sau là chữ cái viết hoa được dành riêng cho việc thực hiện cho bất kỳ việc sử dụng nào. (b) Mỗi mã định danh bắt đầu bằng dấu gạch dưới được dành riêng cho việc triển khai để sử dụng làm tên trong không gian tên toàn cầu.
Cách tốt nhất là tránh bắt đầu một biểu tượng có dấu gạch dưới trong trường hợp bạn vô tình đi lang thang vào một trong những hạn chế trên.
Bạn có thể tự mình nhìn thấy lý do tại sao việc sử dụng dấu gạch dưới như vậy có thể là thảm họa khi phát triển phần mềm:
Hãy thử biên dịch một chương trình helloWorld.cpp đơn giản như thế này:
g++ -E helloWorld.cpp
Bạn sẽ thấy tất cả những gì xảy ra trong nền. Đây là một đoạn:
ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
try
{
__streambuf_type* __sb = this->rdbuf();
if (__sb)
{
if (__sb->pubsync() == -1)
__err |= ios_base::badbit;
else
__ret = 0;
}
Bạn có thể thấy có bao nhiêu tên bắt đầu bằng dấu gạch dưới kép!
Ngoài ra nếu bạn nhìn vào các hàm thành viên ảo, bạn sẽ thấy rằng * _vptr là con trỏ được tạo cho bảng ảo sẽ tự động được tạo khi bạn sử dụng một hoặc nhiều hàm thành viên ảo trong lớp! Nhưng nó là một câu chuyện khác...
Nếu bạn sử dụng dấu gạch dưới, bạn có thể gặp phải các vấn đề xung đột và bạn S NO KHÔNG CÓ Ý TƯỞNG điều gì gây ra nó, cho đến khi quá muộn.
Trên thực tế, _var
quy ước xuất phát từ VB chứ không phải C # hay C ++ (m _, ... là một điều khác).
Điều này đã khắc phục trường hợp không nhạy cảm của VB khi khai báo Thuộc tính.
Ví dụ: mã như vậy không thể có trong VB vì nó xem xét user
và User
là cùng một mã định danh
Private user As String
Public Property User As String
Get
Return user
End Get
Set(ByVal Value As String)
user = value
End Set
End Property
Vì vậy, để khắc phục điều này, một số người đã sử dụng một quy ước để thêm '_' vào trường riêng như thế này
Private _user As String
Public Property User As String
Get
Return _user
End Get
Set(ByVal Value As String)
_user = value
End Set
End Property
Vì nhiều quy ước dành cho .Net và để giữ sự đồng nhất giữa quy ước C # et VB.NET, nên chúng đang sử dụng cùng một quy ước.
Tôi tìm thấy tài liệu tham khảo cho những gì tôi đang nói: http://10rem.net/articles/net-naming-conventions-and-programming-st Chuẩns---best-practices
Trường hợp lạc đà với gạch dưới hàng đầu. Trong VB.NET, luôn chỉ ra "Được bảo vệ" hoặc "Riêng tư", không sử dụng "Dim". Việc sử dụng "m_" không được khuyến khích, cũng như việc sử dụng tên biến khác với thuộc tính chỉ bởi trường hợp, đặc biệt là với các biến được bảo vệ vì vi phạm tuân thủ và sẽ khiến cuộc sống của bạn trở nên khó khăn nếu bạn lập trình trong VB.NET, như bạn sẽ phải đặt tên cho các thành viên của bạn một cái gì đó khác với các thuộc tính accessor / mutator. Trong tất cả các mục ở đây, phần gạch dưới hàng đầu thực sự là thứ gây tranh cãi duy nhất. Cá nhân tôi thích nó hơn trường hợp lạc đà không gạch dưới thẳng cho các biến riêng tư của tôi để tôi không phải đủ điều kiện tên biến với "này". để phân biệt với các tham số trong hàm tạo hoặc ở nơi khác mà tôi có thể sẽ có xung đột đặt tên. Với trường hợp không nhạy cảm của VB.NET, điều này thậm chí còn quan trọng hơn vì các thuộc tính truy cập của bạn thường sẽ có cùng tên với các biến thành viên riêng của bạn ngoại trừ dấu gạch dưới. Theo như m_ đi, nó thực sự chỉ là về tính thẩm mỹ. Tôi (và nhiều người khác) thấy m_ xấu xí, vì có vẻ như có một lỗ hổng trong tên biến. Nó gần như gây khó chịu. Tôi đã từng sử dụng nó trong VB6 mọi lúc, nhưng đó chỉ là do các biến không thể có dấu gạch dưới hàng đầu. Tôi không thể hạnh phúc hơn khi thấy nó biến mất. Microsoft khuyến nghị chống lại m_ (và _ thẳng) mặc dù họ đã làm cả hai trong mã của họ. Ngoài ra, tiền tố với một "m" thẳng là ngay lập tức. Tất nhiên, vì họ mã hóa chủ yếu bằng C #, họ có thể có các thành viên riêng chỉ khác nhau trong trường hợp từ các thuộc tính. VB folks phải làm một cái gì đó khác. Thay vì thử và đưa ra các trường hợp đặc biệt theo ngôn ngữ, tôi khuyên bạn nên gạch dưới hàng đầu cho tất cả các ngôn ngữ sẽ hỗ trợ nó. Nếu tôi muốn lớp của mình tuân thủ hoàn toàn CLS, tôi có thể bỏ tiền tố trên bất kỳ biến thành viên được bảo vệ C # nào. Tuy nhiên, trên thực tế, tôi không bao giờ lo lắng về điều này vì tôi giữ tất cả các biến thành viên có khả năng được bảo vệ ở chế độ riêng tư và thay vào đó cung cấp các bộ truy cập và bộ biến đổi được bảo vệ. Tại sao: Tóm lại, quy ước này đơn giản (một ký tự), dễ đọc (mắt bạn không bị phân tâm bởi các ký tự hàng đầu khác) và tránh thành công các xung đột đặt tên với các biến cấp độ thủ tục và thuộc tính cấp độ lớp. . Tôi khuyên bạn nên gạch dưới hàng đầu cho tất cả các ngôn ngữ sẽ hỗ trợ nó. Nếu tôi muốn lớp của mình tuân thủ hoàn toàn CLS, tôi có thể bỏ tiền tố trên bất kỳ biến thành viên được bảo vệ C # nào. Tuy nhiên, trên thực tế, tôi không bao giờ lo lắng về điều này vì tôi giữ tất cả các biến thành viên có khả năng được bảo vệ ở chế độ riêng tư và thay vào đó cung cấp các bộ truy cập và bộ biến đổi được bảo vệ. Tại sao: Tóm lại, quy ước này đơn giản (một ký tự), dễ đọc (mắt bạn không bị phân tâm bởi các ký tự hàng đầu khác) và tránh thành công các xung đột đặt tên với các biến cấp độ thủ tục và thuộc tính cấp độ lớp. . Tôi khuyên bạn nên gạch dưới hàng đầu cho tất cả các ngôn ngữ sẽ hỗ trợ nó. Nếu tôi muốn lớp của mình tuân thủ hoàn toàn CLS, tôi có thể bỏ tiền tố trên bất kỳ biến thành viên được bảo vệ C # nào. Tuy nhiên, trên thực tế, tôi không bao giờ lo lắng về điều này vì tôi giữ tất cả các biến thành viên có khả năng được bảo vệ ở chế độ riêng tư và thay vào đó cung cấp các bộ truy cập và bộ biến đổi được bảo vệ. Tại sao: Tóm lại, quy ước này đơn giản (một ký tự), dễ đọc (mắt bạn không bị phân tâm bởi các ký tự hàng đầu khác) và tránh thành công các xung đột đặt tên với các biến cấp độ thủ tục và thuộc tính cấp độ lớp. . Tôi không bao giờ lo lắng về điều này vì tôi giữ tất cả các biến thành viên có khả năng được bảo vệ riêng tư và thay vào đó cung cấp các bộ truy cập và bộ biến đổi được bảo vệ. Tại sao: Tóm lại, quy ước này đơn giản (một ký tự), dễ đọc (mắt bạn không bị phân tâm bởi các ký tự hàng đầu khác) và tránh thành công các xung đột đặt tên với các biến cấp độ thủ tục và thuộc tính cấp độ lớp. . Tôi không bao giờ lo lắng về điều này vì tôi giữ tất cả các biến thành viên có khả năng được bảo vệ riêng tư và thay vào đó cung cấp các bộ truy cập và bộ biến đổi được bảo vệ. Tại sao: Tóm lại, quy ước này đơn giản (một ký tự), dễ đọc (mắt bạn không bị phân tâm bởi các ký tự hàng đầu khác) và tránh thành công các xung đột đặt tên với các biến cấp độ thủ tục và thuộc tính cấp độ lớp. .
Nhà bình luận đầu tiên (R Samuel Klatchko) đã tham khảo: các quy tắc về việc sử dụng dấu gạch dưới trong định danh C ++ là gì? trong đó trả lời câu hỏi về dấu gạch dưới trong C ++. Nói chung, bạn không được phép sử dụng dấu gạch dưới hàng đầu, vì nó được dành riêng cho người triển khai trình biên dịch của bạn. Mã bạn đang thấy với_var
lẽ là mã kế thừa hoặc mã được viết bởi một người lớn lên bằng cách sử dụng hệ thống đặt tên cũ không cau mày trên các dấu gạch dưới hàng đầu.
Như các trạng thái câu trả lời khác, nó được sử dụng trong C ++ để xác định các biến thành viên của lớp. Tuy nhiên, nó không có ý nghĩa đặc biệt về trang trí hay cú pháp. Vì vậy, nếu bạn muốn sử dụng nó, nó sẽ biên dịch.
Tôi sẽ để lại cuộc thảo luận C # cho người khác.
_var không có ý nghĩa và chỉ phục vụ mục đích giúp dễ dàng phân biệt biến đó là biến thành viên riêng.
Trong C ++, sử dụng quy ước _var là hình thức xấu, bởi vì có các quy tắc chi phối việc sử dụng dấu gạch dưới trước một mã định danh. _var được bảo lưu như một định danh toàn cầu, trong khi _Var (dấu gạch dưới + chữ in hoa) được bảo lưu bất cứ lúc nào. Đây là lý do tại sao trong C ++, bạn sẽ thấy mọi người sử dụng quy ước var_ thay thế.
Bạn có thể tạo hướng dẫn mã hóa của riêng bạn. Chỉ cần viết một tài liệu rõ ràng cho phần còn lại của đội.
Sử dụng _field giúp Intelilsense lọc tất cả các biến lớp chỉ cần gõ _.
Tôi thường làm theo Nguyên tắc Brad Adams , nhưng nó khuyên không nên sử dụng dấu gạch dưới.
Tiêu chuẩn đặt tên của Microsoft cho C # cho biết các biến và tham số nên sử dụng mẫu trường hợp lạc đà thấp hơn IE : paramName
. Tiêu chuẩn cũng yêu cầu các trường tuân theo cùng một hình thức nhưng điều này có thể dẫn đến mã không rõ ràng nên nhiều nhóm gọi tiền tố gạch dưới để cải thiện IE rõ ràng :_fieldName
.
Với C #, Nguyên tắc thiết kế khung của Microsoft đề nghị không sử dụng ký tự gạch dưới cho các thành viên công cộng . Đối với các thành viên tư nhân , dấu gạch dưới là OK để sử dụng. Trên thực tế, Jeffrey Richter (thường được trích dẫn trong hướng dẫn) sử dụng ví dụ m_ và "s_" cho các thành viên tĩnh riêng.
Cá nhân, tôi chỉ sử dụng _ để đánh dấu các thành viên riêng của mình. "m_" và "s_" verge trên ký hiệu Hungary không chỉ nhăn mặt trong .NET, mà còn khá dài dòng và tôi thấy các lớp có nhiều thành viên khó thực hiện quét mắt nhanh theo bảng chữ cái (hãy tưởng tượng 10 biến tất cả bắt đầu bằng m_) .
Tôi sử dụng cách đặt tên _var cho các biến thành viên của các lớp. Có 2 lý do chính tôi làm:
1) Nó giúp tôi theo dõi các biến lớp và biến hàm cục bộ khi tôi đọc mã của mình sau này.
2) Nó giúp trong Intellisense (hoặc hệ thống hoàn thành mã khác) khi tôi đang tìm kiếm một biến lớp. Chỉ cần biết ký tự đầu tiên là hữu ích trong việc lọc qua danh sách các biến và phương thức có sẵn.
Đối với các ngôn ngữ C và C ++ có liên quan, không có ý nghĩa đặc biệt đối với dấu gạch dưới trong tên (đầu, giữa hoặc cuối). Nó chỉ là một ký tự tên biến hợp lệ. Các "quy ước" đến từ các hoạt động mã hóa trong một cộng đồng mã hóa.
Như đã được chỉ ra bởi các ví dụ khác nhau ở trên, _ lúc đầu có thể có nghĩa là các thành viên riêng tư hoặc được bảo vệ của một lớp trong C ++.
Hãy để tôi đưa ra một số lịch sử có thể là những câu đố vui. Trong UNIX nếu bạn có chức năng thư viện C lõi và back-end kernel, nơi bạn muốn hiển thị chức năng kernel cho không gian người dùng cũng như _ bị kẹt trước hàm stub gọi hàm kernel trực tiếp mà không làm gì khác. Ví dụ nổi tiếng và quen thuộc nhất của điều này là exit () vs _exit () trong các loại nhân BSD và SysV: Ở đó, exit () thực hiện công cụ không gian người dùng trước khi gọi dịch vụ thoát của kernel, trong khi _exit chỉ ánh xạ tới dịch vụ thoát của kernel.
Vì vậy, _ đã được sử dụng cho các công cụ "cục bộ" trong trường hợp này là cục bộ cục bộ. Thông thường _fifts () không di động. Trong đó bạn không nên mong đợi hành vi tương tự trên các nền tảng khác nhau.
Bây giờ như đối với _ trong tên biến, chẳng hạn như
int _foo;
Về mặt tâm lý, một _ là một điều kỳ lạ phải gõ vào đầu. Vì vậy, nếu bạn muốn tạo một tên biến có ít khả năng xảy ra xung đột với thứ khác, HÃY ĐẢM BẢO khi xử lý các thay thế tiền xử lý mà bạn muốn xem xét sử dụng _.
Lời khuyên cơ bản của tôi sẽ là luôn tuân theo quy ước của cộng đồng mã hóa của bạn, để bạn có thể cộng tác hiệu quả hơn.
Nhiều người thích có các trường riêng có tiền tố gạch dưới. Nó chỉ là một quy ước đặt tên.
Các quy ước đặt tên chính thức của C # quy định tên viết thường đơn giản (không gạch dưới) cho các trường riêng.
Tôi không biết các quy ước tiêu chuẩn cho C ++, mặc dù dấu gạch dưới được sử dụng rất rộng rãi.
Đây chỉ là một quy ước mà một số lập trình viên sử dụng để làm rõ khi bạn thao tác một thành viên của lớp hoặc một loại biến khác (tham số, cục bộ cho hàm, v.v.). Một quy ước khác cũng được sử dụng rộng rãi cho các biến thành viên là tiền tố tên với 'm_'.
Dù sao, đây chỉ là những quy ước và bạn sẽ không tìm thấy một nguồn duy nhất cho tất cả chúng. Chúng là một vấn đề về phong cách và mỗi nhóm lập trình, dự án hoặc công ty có cái riêng (hoặc thậm chí không có cái nào).
Có một lý do hoàn toàn hợp pháp để sử dụng nó trong C #: nếu mã cũng phải được mở rộng từ VB.NET. (Nếu không, tôi sẽ không.)
Vì VB.NET không phân biệt chữ hoa chữ thường, nên không có cách đơn giản nào để truy cập field
thành viên được bảo vệ trong mã này:
public class CSharpClass
{
protected int field;
public int Field { get { return field; } }
}
Ví dụ: điều này sẽ truy cập vào getter thuộc tính, không phải trường:
Public Class VBClass
Inherits CSharpClass
Function Test() As Integer
Return Field
End Function
End Class
Heck, tôi thậm chí không thể viết field
bằng chữ thường - VS 2010 cứ sửa nó.
Để làm cho nó dễ dàng truy cập vào các lớp dẫn xuất trong VB.NET, người ta phải đưa ra một quy ước đặt tên khác. Tiền tố một dấu gạch dưới có lẽ là ít xâm phạm nhất và "được chấp nhận nhất trong lịch sử" của chúng.
Câu hỏi cũ, câu trả lời mới (C #).
Một cách sử dụng khác của dấu gạch dưới cho C # là với DI (tiêm phụ thuộc) của ASP NET Core. Các readonly
biến riêng của một lớp được gán cho giao diện được chèn trong quá trình xây dựng nên bắt đầu bằng dấu gạch dưới. Tôi đoán đó là một cuộc tranh luận về việc có nên sử dụng dấu gạch dưới cho mỗi thành viên riêng của một lớp hay không (mặc dù chính Microsoft tuân theo nó) nhưng điều này là chắc chắn.
private readonly ILogger<MyDependency> _logger;
public MyDependency(ILogger<MyDependency> logger)
{
_logger = logger;
}
Một quy ước đặt tên như thế này rất hữu ích khi bạn đang đọc mã, đặc biệt là mã không phải của riêng bạn. Một quy ước đặt tên mạnh giúp chỉ ra nơi một thành viên cụ thể được xác định, loại thành viên đó, v.v. Hầu hết các nhóm phát triển áp dụng quy ước đặt tên đơn giản và chỉ đơn giản là tiền tố các trường thành viên có dấu gạch dưới ( _fieldName
). Trước đây, tôi đã sử dụng quy ước đặt tên sau cho C # (dựa trên các quy ước của microsofts cho mã khung .NET, có thể được nhìn thấy bằng Reflector):
Trường sơ thẩm: m_fieldName
Trường tĩnh: s_fieldName
Công khai / Được bảo vệ / Thành viên nội bộ: PascalCasingName ()
Thành viên riêng: camelCasingName ()
Điều này giúp mọi người hiểu cấu trúc, cách sử dụng, khả năng truy cập và vị trí của các thành viên khi đọc mã không quen thuộc rất nhanh.