Często spotyka się _var
nazwę zmiennej w polu klasy. Co oznacza podkreślenie? Czy istnieje odniesienie do wszystkich tych specjalnych konwencji nazewnictwa?
Często spotyka się _var
nazwę zmiennej w polu klasy. Co oznacza podkreślenie? Czy istnieje odniesienie do wszystkich tych specjalnych konwencji nazewnictwa?
Odpowiedzi:
Podkreślenie to po prostu konwencja; nic więcej. W związku z tym jego użycie jest zawsze nieco inne dla każdej osoby. Oto, jak rozumiem je w tych dwóch językach:
W C ++ podkreślenie zwykle oznacza prywatną zmienną składową.
W C # zwykle widzę, że jest używany tylko podczas definiowania podstawowej zmiennej składowej prywatnej dla właściwości publicznej. Inne zmienne składowe prywatne nie miałyby podkreślenia. To użycie w dużej mierze odeszło jednak na bok wraz z pojawieniem się automatycznych właściwości.
Przed:
private string _name;
public string Name
{
get { return this._name; }
set { this._name = value; }
}
Po:
public string Name { get; set; }
public string Name { get; private set; }
. To prawda, że nie jest całkowicie niezmienny, ale istnieje.
_var
nie jest zastrzeżone.
Najlepszą praktyką jest NIEUŻYWANIE PODNOŚNIKÓW przed jakąkolwiek nazwą zmiennej lub nazwą parametru w C ++
Nazwy zaczynające się od podkreślenia lub podwójnego podkreślenia są ZAREZERWOWANE dla osób wdrażających C ++. Nazwy z podkreśleniem są zarezerwowane dla biblioteki.
Jeśli przeczytałeś C ++ Coding Standard, zobaczysz, że na pierwszej stronie jest napisane:
„Nie przesadzaj z nazewnictwem, ale stosuj spójną konwencję nazewnictwa: są tylko dwie rzeczy do zrobienia: a) nigdy nie używaj„ podstępnych nazw ”, zaczynających się od podkreślenia lub zawierających podwójne podkreślenie; (p2, Standardy kodowania C ++, Herb Sutter i Andrei Alexandrescu)
Dokładniej, projekt roboczy ISO określa rzeczywiste zasady:
Ponadto niektóre identyfikatory są zarezerwowane do użytku przez implementacje C ++ i nie powinny być używane w inny sposób; nie jest wymagana żadna diagnostyka. (a) Każdy identyfikator, który zawiera podwójne podkreślenie __ lub zaczyna się od podkreślenia, po którym następuje duża litera, jest zarezerwowany dla implementacji do dowolnego użytku. (b) Każdy identyfikator, który zaczyna się od podkreślenia, jest zarezerwowany dla implementacji do użycia jako nazwa w globalnej przestrzeni nazw.
Najlepszą praktyką jest unikanie rozpoczynania symbolu od podkreślenia, na wypadek gdybyś przypadkowo znalazł się w jednym z powyższych ograniczeń.
Sam możesz się przekonać, dlaczego takie użycie podkreśleń może być katastrofalne w przypadku tworzenia oprogramowania:
Spróbuj skompilować prosty program helloWorld.cpp w następujący sposób:
g++ -E helloWorld.cpp
Zobaczysz wszystko, co dzieje się w tle. Oto fragment:
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;
}
Możesz zobaczyć, ile nazw zaczyna się od podwójnego podkreślenia!
Ponadto, jeśli spojrzysz na wirtualne funkcje składowe, zobaczysz, że * _vptr jest wskaźnikiem wygenerowanym dla wirtualnej tabeli, który jest automatycznie tworzony, gdy używasz jednej lub więcej wirtualnych funkcji składowych w swojej klasie! Ale to już inna historia ...
Jeśli użyjesz podkreśleń, możesz mieć problemy z konfliktem i NIE MASZ POMYSŁU, co go powoduje, dopóki nie będzie za późno.
Właściwie _var
konwencja pochodzi z VB, a nie z C # czy C ++ (m _, ... to inna sprawa).
Pozwoliło to przezwyciężyć niewrażliwość VB na wielkość liter podczas deklarowania właściwości.
Na przykład, taki kod nie jest możliwe w VB, ponieważ uważa, user
i User
jako taki sam identyfikator
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
Aby temu zaradzić, niektórzy używali konwencji dodawania „_” do pola prywatnego, aby uzyskać taki efekt
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
Ponieważ wiele konwencji dotyczy .Net i aby zachować pewną jednolitość między konwencjami C # i VB.NET, używają one tej samej.
Znalazłem odniesienie do tego, co mówiłem: http://10rem.net/articles/net-naming-conventions-and-programming-standards---best-practices
Etui Camel z wiodącym podkreśleniem. W VB.NET zawsze zaznaczaj „Chroniony” lub „Prywatny”, nie używaj „Dim”. Używanie "m_" jest odradzane, podobnie jak używanie nazwy zmiennej, która różni się od właściwości tylko wielkością liter, szczególnie w przypadku zmiennych chronionych, ponieważ narusza to zgodność i sprawi, że twoje życie będzie bólem, jeśli będziesz programować w VB.NET, ponieważ musiałby nadać członkom inną nazwę niż właściwości akcesora / mutatora. Ze wszystkich przedstawionych tutaj elementów, wiodące podkreślenie jest tak naprawdę jedynym kontrowersyjnym. Osobiście wolę to od prostych, pozbawionych podkreślenia wielbłądów dla moich zmiennych prywatnych, więc nie muszę kwalifikować nazw zmiennych za pomocą „this”. odróżnić od parametrów w konstruktorach lub w innych miejscach, gdzie prawdopodobnie wystąpi kolizja nazw. Przy niewrażliwości na wielkość liter w VB.NET jest to jeszcze ważniejsze, ponieważ właściwości akcesorium zwykle mają taką samą nazwę, jak prywatne zmienne składowe, z wyjątkiem podkreślenia. Jeśli chodzi o m_, to tak naprawdę chodzi tylko o estetykę. Ja (i wielu innych) uważam, że m_ jest brzydki, ponieważ wygląda na to, że w nazwie zmiennej jest dziura. To prawie obraźliwe. Używałem go cały czas w VB6, ale to tylko dlatego, że zmienne nie mogły mieć wiodącego podkreślenia. Nie mogłem być szczęśliwszy, widząc, jak to odchodzi. Firma Microsoft odradza m_ (i prostą _), mimo że zrobili to w swoim kodzie. Również prefiks z prostym „m” jest od razu skuteczny. Oczywiście, ponieważ kodują głównie w C #, mogą mieć prywatnych członków różniących się tylko wielkością liter od właściwości. Ludzie VB muszą zrobić coś innego. Zamiast próbować wymyślać przypadki specjalne dla poszczególnych języków, polecam wiodące podkreślenie dla wszystkich języków, które będą go obsługiwać. Jeśli chcę, aby moja klasa była w pełni zgodna z CLS, mógłbym pominąć prefiks na dowolnej chronionej C # zmiennej składowej. W praktyce jednak nigdy się tym nie martwię, ponieważ zachowuję wszystkie potencjalnie chronione zmienne składowe jako prywatne, a zamiast tego dostarczam chronione metody dostępu i mutatory. Dlaczego: w skrócie, ta konwencja jest prosta (jeden znak), łatwa do odczytania (twoje oko nie jest rozpraszane przez inne wiodące znaki) i skutecznie pozwala uniknąć kolizji nazw ze zmiennymi na poziomie procedury i właściwościami na poziomie klasy. Właściwości na poziomie klasy . Polecam wiodące podkreślenie dla wszystkich języków, które będą go wspierać. Jeśli chcę, aby moja klasa była w pełni zgodna z CLS, mógłbym pominąć prefiks na dowolnej chronionej C # zmiennej składowej. W praktyce jednak nigdy się tym nie martwię, ponieważ zachowuję wszystkie potencjalnie chronione zmienne składowe jako prywatne, a zamiast tego dostarczam chronione metody dostępu i mutatory. Dlaczego: w skrócie, ta konwencja jest prosta (jeden znak), łatwa do odczytania (twoje oko nie jest rozpraszane przez inne wiodące znaki) i skutecznie pozwala uniknąć kolizji nazw ze zmiennymi na poziomie procedury i właściwościami na poziomie klasy. Właściwości na poziomie klasy . Polecam wiodące podkreślenie dla wszystkich języków, które będą go wspierać. Jeśli chcę, aby moja klasa była w pełni zgodna z CLS, mógłbym pominąć prefiks na dowolnej chronionej C # zmiennej składowej. W praktyce jednak nigdy się tym nie przejmuję, ponieważ zachowuję wszystkie potencjalnie chronione zmienne składowe jako prywatne i zamiast tego dostarczam chronione metody dostępu i mutatory. Dlaczego: w skrócie, ta konwencja jest prosta (jeden znak), łatwa do odczytania (twoje oko nie jest rozpraszane przez inne wiodące znaki) i skutecznie pozwala uniknąć kolizji nazw ze zmiennymi na poziomie procedury i właściwościami na poziomie klasy. Właściwości na poziomie klasy . Nigdy się tym nie martwię, ponieważ zachowuję wszystkie potencjalnie chronione zmienne składowe jako prywatne, a zamiast tego dostarczam chronione akcesory i mutatory. Dlaczego: w skrócie, ta konwencja jest prosta (jeden znak), łatwa do odczytania (twoje oko nie jest rozpraszane przez inne wiodące znaki) i skutecznie pozwala uniknąć kolizji nazw ze zmiennymi na poziomie procedury i właściwościami na poziomie klasy. Właściwości na poziomie klasy . Nigdy się tym nie martwię, ponieważ zachowuję wszystkie potencjalnie chronione zmienne składowe jako prywatne, a zamiast tego dostarczam chronione akcesory i mutatory. Dlaczego: w skrócie, ta konwencja jest prosta (jeden znak), łatwa do odczytania (twoje oko nie jest rozpraszane przez inne wiodące znaki) i skutecznie pozwala uniknąć kolizji nazw ze zmiennymi na poziomie procedury i właściwościami na poziomie klasy. Właściwości na poziomie klasy .
Pierwszy komentator (R Samuel Klatchko) wspomniał: Jakie są zasady dotyczące używania podkreślenia w identyfikatorze C ++? który odpowiada na pytanie o podkreślenie w C ++. Ogólnie rzecz biorąc, nie powinieneś używać początkowego podkreślenia, ponieważ jest on zarezerwowany dla implementującego twój kompilator. Kod, z którym widzisz, _var
jest prawdopodobnie kodem starszym lub kodem napisanym przez kogoś, kto dorastał przy użyciu starego systemu nazewnictwa, który nie marszczył brwi na widok wiodących znaków podkreślenia.
Jak podają inne odpowiedzi, był używany w C ++ do identyfikowania zmiennych składowych klasy. Jednak nie ma to specjalnego znaczenia, jeśli chodzi o dekoratory lub składnię. Więc jeśli chcesz go użyć, skompiluje się.
Zostawię dyskusję C # innym.
_var nie ma znaczenia i służy jedynie do ułatwienia rozróżnienia, że zmienna jest prywatną zmienną składową.
W C ++ używanie konwencji _var jest złą formą, ponieważ istnieją reguły regulujące użycie znaku podkreślenia przed identyfikatorem. _var jest zarezerwowany jako identyfikator globalny, podczas gdy _Var (podkreślenie + duża litera) jest zarezerwowany w dowolnym momencie. Dlatego w C ++ zobaczysz ludzi używających konwencji var_.
Możesz stworzyć własne wytyczne dotyczące kodowania. Po prostu napisz jasną dokumentację dla reszty zespołu.
Użycie _field pomaga Intelilsense w filtrowaniu wszystkich zmiennych klas po prostu wpisując _.
Zwykle postępuję zgodnie z wytycznymi Brada Adamsa , ale odradzam używanie podkreślenia.
Nazewnictwie standardem Microsoft C # mówi zmienne i parametry powinny stosować małe liter wielbłąd tj paramName
. Norma wymaga również pola podążać taką samą formę, ale może to prowadzić do kodu niejasnej tak wiele zespołów wezwać do prefiksu podkreślenia, aby poprawić jasność tj _fieldName
.
W przypadku języka C # wytyczne dotyczące projektu Microsoft Framework sugerują, aby nie używać znaku podkreślenia dla członków publicznych . W przypadku członków prywatnych podkreślenia są dopuszczalne. W rzeczywistości Jeffrey Richter (często cytowany w wytycznych) używa na przykład m_ i „s_” dla prywatnych statycznych członków.
Osobiście używam tylko _ do oznaczania moich prywatnych członków. „m_” i „s_” graniczą z notacją węgierską, która jest nie tylko mile widziana w .NET, ale może być dość rozwlekła i uważam, że klasy z wieloma członkami są trudne do wykonania szybkiego skanowania oczu alfabetycznie (wyobraź sobie 10 zmiennych, wszystkie zaczynające się od m_) .
Używam nazewnictwa _var dla zmiennych składowych moich klas. Są dwa główne powody, dla których robię:
1) Pomaga mi śledzić zmienne klasowe i lokalne zmienne funkcyjne podczas późniejszego czytania kodu.
2) Pomaga w Intellisense (lub innym systemie uzupełniania kodu), gdy szukam zmiennej klasy. Znajomość pierwszego znaku jest pomocna w przefiltrowaniu listy dostępnych zmiennych i metod.
Jeśli chodzi o języki C i C ++, podkreślenie w nazwie nie ma specjalnego znaczenia (początek, środek lub koniec). To tylko prawidłowy znak nazwy zmiennej. „Konwencje” pochodzą z praktyk kodowania w ramach społeczności programistów.
Jak już wskazano w różnych przykładach powyżej, _ na początku może oznaczać prywatnych lub chronionych członków klasy w C ++.
Podam tylko historię, która może być zabawną ciekawostką. W systemie UNIX, jeśli masz podstawową funkcję biblioteki C i zaplecze jądra, w którym chcesz udostępnić funkcję jądra w przestrzeni użytkownika, znak _ utknie przed funkcją pośredniczącą funkcji, która bezpośrednio wywołuje funkcję jądra, nie robiąc nic innego. Najbardziej znanym i znanym przykładem tego jest exit () vs _exit () w jądrach typu BSD i SysV: Tutaj exit () wykonuje operacje w przestrzeni użytkownika przed wywołaniem usługi wyjścia jądra, podczas gdy _exit po prostu mapuje na usługę wyjścia jądra.
Tak więc _ zostało użyte dla rzeczy „lokalnych”, w tym przypadku lokalnie lokalna dla maszyny. Zazwyczaj funkcja _functions () nie była przenośna. W związku z tym nie należy oczekiwać takiego samego zachowania na różnych platformach.
Teraz co do _ w nazwach zmiennych, takich jak
int _foo;
Z psychologicznego punktu widzenia _ jest dziwną rzeczą, którą trzeba wpisywać na początku. Więc jeśli chcesz utworzyć nazwę zmiennej, która miałaby mniejsze szanse na kolizję z czymś innym, SZCZEGÓLNIE w przypadku zastępowania preprocesorów, które chcesz, rozważ użycie _.
Moja podstawowa rada jest taka, aby zawsze postępować zgodnie z konwencją Twojej społeczności programistów, aby móc efektywniej współpracować.
Wiele osób lubi mieć prywatne pola poprzedzone podkreśleniem. To tylko konwencja nazewnictwa.
„Oficjalne” konwencje nazewnictwa języka C # nakazują proste nazwy małymi literami (bez podkreślenia) dla pól prywatnych.
Nie znam standardowych konwencji C ++, chociaż podkreślenia są bardzo szeroko stosowane.
Jest to po prostu konwencja, której niektórzy programiści używają, aby wyjaśnić, kiedy manipulujesz składnikiem klasy lub jakimś innym rodzajem zmiennej (parametrami, lokalnymi dla funkcji itp.). Inną konwencją, która jest również szeroko stosowana w przypadku zmiennych składowych, jest poprzedzanie nazwy przedrostkiem „m_”.
Zresztą to tylko konwencje i nie znajdziesz dla nich jednego źródła. Są kwestią stylu, a każdy zespół programistyczny, projekt czy firma ma swój własny (a nawet go nie ma).
Jest w pełni uzasadniony powód, aby używać go w C #: jeśli kod musi być również rozszerzalny z VB.NET. (W przeciwnym razie nie zrobiłbym tego.)
Ponieważ VB.NET nie rozróżnia wielkości liter, nie ma prostego sposobu na uzyskanie dostępu do chronionego field
elementu członkowskiego w tym kodzie:
public class CSharpClass
{
protected int field;
public int Field { get { return field; } }
}
Np. Uzyska dostęp do metody pobierania właściwości, a nie pola:
Public Class VBClass
Inherits CSharpClass
Function Test() As Integer
Return Field
End Function
End Class
Heck, nie mogę nawet pisać field
małymi literami - VS 2010 po prostu ciągle to poprawia.
Aby uczynić go łatwo dostępnym dla klas pochodnych w VB.NET, trzeba wymyślić inną konwencję nazewnictwa. Przedrostek podkreślenia jest prawdopodobnie najmniej uciążliwym i najbardziej „historycznie akceptowanym” z nich.
Stare pytanie, nowa odpowiedź (C #).
Innym zastosowaniem podkreślenia dla C # jest użycie DI (iniekcja zależności) ASP NET Core. Prywatne readonly
zmienne klasy, która została przypisana do wstrzykniętego interfejsu podczas budowy, powinny zaczynać się od podkreślenia. Wydaje mi się, że jest to debata, czy użyć podkreślenia dla każdego prywatnego członka klasy (chociaż sam Microsoft podąża za tym), ale ten jest pewien.
private readonly ILogger<MyDependency> _logger;
public MyDependency(ILogger<MyDependency> logger)
{
_logger = logger;
}
Taka konwencja nazewnictwa jest przydatna podczas czytania kodu, zwłaszcza kodu, który nie jest Twoim własnym. Silna konwencja nazewnictwa pomaga wskazać, gdzie jest zdefiniowany dany członek, jakiego rodzaju jest to członek, itp. Większość zespołów programistów przyjmuje prostą konwencję nazewnictwa i po prostu umieszcza przed polami elementu podkreślenie ( _fieldName
). W przeszłości stosowałem następującą konwencję nazewnictwa dla języka C # (która jest oparta na konwencji Microsoftu dla kodu platformy .NET, którą można zobaczyć w programie Reflector):
Pole instancji: m_fieldName
Pole statyczne: s_fieldName
Public / Protected / Internal Member: PascalCasedName ()
Private Member: camelCasedName ()
Pomaga to ludziom bardzo szybko zrozumieć strukturę, użycie, dostępność i lokalizację członków podczas czytania nieznanego kodu.