Распространено видеть _var
имя переменной в поле класса. Что означает подчеркивание? Есть ли ссылка на все эти специальные соглашения об именах?
Распространено видеть _var
имя переменной в поле класса. Что означает подчеркивание? Есть ли ссылка на все эти специальные соглашения об именах?
Ответы:
Подчеркивание - это просто соглашение; ничего более. Таким образом, его использование всегда несколько отличается для каждого человека. Вот как я понимаю их для двух рассматриваемых языков:
В C ++ подчеркивание обычно указывает на закрытую переменную-член.
В C # я обычно вижу, что он используется только при определении базовой закрытой переменной-члена для открытого свойства. Другие закрытые переменные-члены не будут иметь подчеркивания. Это использование в значительной степени ушло на второй план с появлением автоматических свойств, хотя.
Перед:
private string _name;
public string Name
{
get { return this._name; }
set { this._name = value; }
}
После:
public string Name { get; set; }
public string Name { get; private set; }
. Правда, он не совсем неизменен, но он есть.
_var
не зарезервировано
Рекомендуется НЕ использовать UNDERSCORES перед любым именем переменной или параметра в C ++
Имена, начинающиеся с подчеркивания или двойного подчеркивания, ЗАБРОНИРОВАНЫ для разработчиков C ++. Имена с подчеркиванием зарезервированы для работы библиотеки.
Если вы читали в стандарте кодирования C ++, вы увидите, что на самой первой странице написано:
«Не переусердствуйте в присвоении имен, но используйте последовательное соглашение об именах: есть только два обязательных элемента: а) никогда не используйте« закулисные имена », те, которые начинаются с подчеркивания или содержат двойное подчеркивание;» (p2, Стандарты кодирования C ++, Херб Саттер и Андрей Александреску)
В частности, рабочий проект ISO устанавливает действующие правила:
Кроме того, некоторые идентификаторы зарезервированы для использования реализациями C ++ и не должны использоваться иначе; Диагностика не требуется. (a) Каждый идентификатор, который содержит двойное подчеркивание __ или начинается с подчеркивания, за которым следует заглавная буква, зарезервирован для реализации для любого использования. (b) Каждый идентификатор, который начинается со знака подчеркивания, зарезервирован для реализации для использования в качестве имени в глобальном пространстве имен.
Лучше не начинать символ с символа подчеркивания, если вы случайно попали в одно из указанных выше ограничений.
Вы сами можете понять, почему такое использование подчеркивания может иметь катастрофические последствия при разработке программного обеспечения:
Попробуйте скомпилировать простую программу helloWorld.cpp, например:
g++ -E helloWorld.cpp
Вы увидите все, что происходит в фоновом режиме. Вот фрагмент:
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;
}
Вы можете увидеть, сколько имен начинаются с двойного подчеркивания!
Также, если вы посмотрите на виртуальные функции-члены, вы увидите, что * _vptr - это указатель, сгенерированный для виртуальной таблицы, который автоматически создается, когда вы используете одну или несколько виртуальных функций-членов в своем классе! Но это другая история ...
Если вы используете подчеркивание, вы можете столкнуться с конфликтными проблемами и не будете знать, что их вызывает, пока не станет слишком поздно.
На самом деле _var
соглашение происходит от VB, а не C # или C ++ (m _, ... это другое дело).
Это привело к преодолению нечувствительности к регистру VB при объявлении свойств.
Например, такой код не возможен в VB, потому что он считает user
и User
тем же идентификатором
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
Таким образом, чтобы преодолеть это, некоторые использовали соглашение, чтобы добавить '_' в приватное поле, чтобы получить вот так
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
Поскольку многие соглашения предназначены для .Net и для сохранения некоторого единообразия между соглашениями C # и VB.NET, они используют один и тот же.
Я нашел ссылку на то, что я говорил: http://10rem.net/articles/net-naming-conventions-and-programming-standards---best-practices
Чехол для верблюдов с ведущим символом подчеркивания. В VB.NET всегда указывайте «Защищенный» или «Частный», не используйте «Тусклый». Использование «m_» не рекомендуется, так же как и использование имени переменной, которое отличается от свойства только регистром, особенно с защищенными переменными, поскольку это нарушает соответствие, и сделает вашу жизнь болезненной, если вы будете программировать на VB.NET, так как вы придется называть ваших членов чем-то отличным от свойств аксессора / мутатора. Из всех перечисленных здесь подчеркивание является единственным спорным. Лично я предпочитаю это вместо прямого символа верблюда для моих личных переменных, чтобы мне не приходилось квалифицировать имена переменных с помощью «this». чтобы отличить от параметров в конструкторах или в других местах, где у меня, вероятно, будет конфликт имен. С учетом нечувствительности к регистру в VB.NET это еще более важно, поскольку ваши свойства аксессора обычно имеют то же имя, что и ваши закрытые переменные-члены, за исключением подчеркивания. Что касается M_, это действительно только эстетика. Я (и многие другие) нахожу безобразным, так как в имени переменной есть пробел. Это почти оскорбительно. Я использовал его в VB6 все время, но это только потому, что переменные не могли иметь подчеркивания в начале. Я не мог быть счастливее видеть, как это уходит. Microsoft рекомендует против m_ (и прямой _), хотя они и сделали в своем коде. Кроме того, префикс с прямой "м" прямо. Конечно, поскольку они кодируют в основном на C #, у них могут быть закрытые члены, которые отличаются только в случае от свойств. VB люди должны сделать что-то еще. Вместо того, чтобы пытаться придумывать языковые особые случаи, я рекомендую подчеркивание для всех языков, которые его поддерживают. Если я хочу, чтобы мой класс был полностью CLS-совместимым, я мог бы опустить префикс для любых переменных-членов, защищенных в C #. На практике, однако, я никогда не беспокоюсь об этом, так как я держу все потенциально защищенные переменные-члены в секрете и вместо этого предоставляю защищенные методы доступа и мутаторы. Почему: в двух словах, это соглашение простое (один символ), легко читаемое (ваш взгляд не отвлекается на другие ведущие символы) и успешно избегает конфликтов имен с переменными уровня процедуры и свойствами уровня класса. Свойства уровня класса , Я рекомендую нижнее подчеркивание для всех языков, которые его поддерживают. Если я хочу, чтобы мой класс был полностью CLS-совместимым, я мог бы опустить префикс для любых переменных-членов, защищенных в C #. На практике, однако, я никогда не беспокоюсь об этом, так как я держу все потенциально защищенные переменные-члены в секрете и вместо этого предоставляю защищенные методы доступа и мутаторы. Почему: в двух словах, это соглашение простое (один символ), легко читаемое (ваш взгляд не отвлекается на другие ведущие символы) и успешно избегает конфликтов имен с переменными уровня процедуры и свойствами уровня класса. Свойства уровня класса , Я рекомендую нижнее подчеркивание для всех языков, которые его поддерживают. Если я хочу, чтобы мой класс был полностью CLS-совместимым, я мог бы опустить префикс для любых переменных-членов, защищенных в C #. На практике, однако, я никогда не беспокоюсь об этом, так как я держу все потенциально защищенные переменные-члены в секрете и вместо этого предоставляю защищенные методы доступа и мутаторы. Почему: в двух словах, это соглашение простое (один символ), легко читаемое (ваш взгляд не отвлекается на другие ведущие символы) и успешно избегает конфликтов имен с переменными уровня процедуры и свойствами уровня класса. Свойства уровня класса , Я никогда не беспокоюсь об этом, так как я держу все потенциально защищенные переменные-члены в секрете и вместо этого поставляю защищенные методы доступа и мутаторы. Почему: в двух словах, это соглашение простое (один символ), легко читаемое (ваш взгляд не отвлекается на другие ведущие символы) и успешно избегает конфликтов имен с переменными уровня процедуры и свойствами уровня класса. Свойства уровня класса , Я никогда не беспокоюсь об этом, так как я держу все потенциально защищенные переменные-члены в секрете и вместо этого поставляю защищенные методы доступа и мутаторы. Почему: в двух словах, это соглашение простое (один символ), легко читаемое (ваш взгляд не отвлекается на другие ведущие символы) и успешно избегает конфликтов имен с переменными уровня процедуры и свойствами уровня класса. Свойства уровня класса ,
Первый комментатор (R Samuel Klatchko) ссылался: каковы правила использования подчеркивания в идентификаторе C ++? который отвечает на вопрос о подчеркивании в C ++. В общем, вы не должны использовать начальное подчеркивание, так как оно зарезервировано для разработчика вашего компилятора. Код, с которым вы сталкиваетесь, _var
вероятно, является либо устаревшим кодом, либо кодом, написанным кем-то, кто вырос, используя старую систему именования, которая не зацикливалась на ведущих подчеркиваниях.
Как говорится в других ответах, он использовался в C ++ для определения переменных членов класса. Тем не менее, он не имеет особого значения для декораторов или синтаксиса. Так что, если вы хотите использовать его, он скомпилируется.
Я оставлю обсуждение C # другим.
_var не имеет смысла и служит только для того, чтобы упростить распознавание того, что переменная является закрытой переменной-членом.
В C ++ использование соглашения _var является плохой формой, поскольку существуют правила, регулирующие использование подчеркивания перед идентификатором. _var зарезервирован как глобальный идентификатор, а _Var (подчеркивание + заглавная буква) зарезервирован в любое время. Вот почему в C ++ вы увидите людей, которые вместо этого используют соглашение var_.
Вы можете создать свои собственные правила кодирования. Просто напишите четкую документацию для остальной части команды.
Использование _field помогает Intelilsense фильтровать все переменные класса, просто набирая _.
Я обычно следую Руководящим указаниям Брэда Адамса , но он рекомендует не использовать подчеркивание.
Именование стандарт Microsoft для C # говорит переменные и параметры должны использовать нижнюю форму верблюд случая IE: paramName
. Стандарт также требует поля , чтобы следовать той же форме , но это может привести к неясному коду так много команд требуют подчеркивания префикса для улучшения ясности IE: _fieldName
.
В C # Руководства по проектированию Microsoft Framework предлагают не использовать символ подчеркивания для открытых членов. Для частных пользователей подчеркивания в порядке. Фактически, Джеффри Рихтер (часто цитируемый в руководящих принципах) использует, например, m_ и s_ для частных статических членов.
Лично я использую только _, чтобы пометить своих частных пользователей. «m_» и «s_» граничат с венгерской нотацией, которая не только не одобряется в .NET, но может быть довольно многословной, и я нахожу, что классы со многими членами трудно выполнить быструю проверку в алфавитном порядке (представьте 10 переменных, все начинающиеся с m_) ,
Я использую именование _var для переменных-членов моих классов. Есть две основные причины, по которым я это делаю:
1) Это помогает мне отслеживать переменные класса и локальные функции, когда я читаю свой код позже.
2) Это помогает в Intellisense (или другой системе дополнения кода), когда я ищу переменную класса. Знание первого символа полезно для фильтрации списка доступных переменных и методов.
Что касается языков C и C ++, то нет особого значения для подчеркивания в имени (начало, середина или конец). Это просто допустимый символ имени переменной. «Соглашения» происходят из практики кодирования в сообществе программистов.
Как уже указывалось различными примерами выше, _ в начале может означать закрытые или защищенные члены класса в C ++.
Позвольте мне привести историю, которая может быть интересной. В UNIX, если у вас есть функция библиотеки ядра C и серверная часть ядра, где вы хотите также представить функцию ядра в пространстве пользователя, _ застревает перед заглушкой функции, которая вызывает функцию ядра напрямую, не делая ничего другого. Наиболее известный и знакомый пример этого - exit () vs _exit () в ядрах типа BSD и SysV: там exit () выполняет работу с пользовательским пространством перед вызовом службы выхода ядра, тогда как _exit просто сопоставляется со службой выхода ядра.
Таким образом, _ использовался для «локальных» вещей, в данном случае локальный был машинно-локальным. Обычно _functions () не были переносимыми. В этом вы не должны ожидать одинакового поведения на разных платформах.
Теперь что касается _ в именах переменных, таких как
int _foo;
Психологически, _ - это странная вещь, которую нужно вводить в начале. Поэтому, если вы хотите создать имя переменной, которое будет иметь меньшую вероятность столкновения с чем-то другим, ОСОБЕННО при работе с заменами препроцессора, вы должны рассмотреть использование _.
Мой основной совет - всегда следовать правилам вашего сообщества программистов, чтобы вы могли сотрудничать более эффективно.
Многим людям нравится иметь частные поля с префиксом подчеркивания. Это просто соглашение об именах.
Официальные соглашения об именах в C # предписывают простые строчные имена (без подчеркивания) для частных полей.
Я не знаю стандартных соглашений для C ++, хотя подчеркивания очень широко используются.
Это просто соглашение, которое некоторые программисты используют, чтобы прояснить, когда вы манипулируете членом класса или какой-либо другой переменной (параметры, локальные для функции и т. Д.). Другое соглашение, которое также широко используется для переменных-членов, заключается в добавлении префикса имени к «m_».
В любом случае, это всего лишь соглашения, и вы не найдете единого источника для всех них. Это вопрос стиля, и у каждой команды программистов, проектов или компаний есть свои (или даже нет).
Существует вполне законная причина использовать его в C #: если код должен быть также расширяемым из VB.NET. (В противном случае я бы не стал.)
Поскольку VB.NET нечувствителен к регистру, field
в этом коде нет простого способа получить доступ к защищенному члену:
public class CSharpClass
{
protected int field;
public int Field { get { return field; } }
}
Например, это получит доступ к получателю свойства, а не к полю:
Public Class VBClass
Inherits CSharpClass
Function Test() As Integer
Return Field
End Function
End Class
Черт, я даже не могу писать field
строчными буквами - VS 2010 просто продолжает исправлять это.
Чтобы сделать его легко доступным для производных классов в VB.NET, необходимо придумать другое соглашение об именах. Префикс подчеркивания является, вероятно, наименее навязчивым и наиболее «исторически приемлемым» из них.
Старый вопрос, новый ответ (C #).
Другое использование символов подчеркивания для C # - это DI-ядро ASP NET Core (внедрение зависимостей). Закрытые readonly
переменные класса, которые были присвоены внедренному интерфейсу во время построения, должны начинаться с подчеркивания. Я предполагаю, что это спор о том, использовать ли подчеркивание для каждого частного члена класса (хотя сама Microsoft следует за ним), но это однозначно.
private readonly ILogger<MyDependency> _logger;
public MyDependency(ILogger<MyDependency> logger)
{
_logger = logger;
}
Соглашение об именах, подобное этому, полезно, когда вы читаете код, особенно код, который вам не принадлежит. Сильное соглашение об именах помогает указать, где определен конкретный член, какой он член и т. Д. Большинство групп разработчиков применяют простое соглашение об именах и просто ставят префиксы полей для членов с подчеркиванием ( _fieldName
). В прошлом я использовал следующее соглашение об именах для C # (основанное на соглашениях Microsoft для кода платформы .NET, которые можно увидеть с помощью Reflector):
Поле экземпляра: m_fieldName
Статическое поле: s_fieldName
Public / Protected / Internal Участник: PascalCasedName ()
Закрытый член: camelCasedName ()
Это помогает людям понять структуру, использование, доступность и местоположение участников при быстром чтении незнакомого кода.