Подчеркивать или не подчеркивать, вот в чем вопрос - PullRequest
119 голосов
/ 16 января 2009

Есть ли проблемы с отсутствием префикса частных полей с подчеркиванием в C #, если двоичная версия будет использоваться другими языками фреймворка? Например, поскольку C # чувствителен к регистру, вы можете вызвать поле "foo" и открытое свойство "Foo", и оно отлично работает.

Будет ли это любым эффектом для языка без учета регистра, такого как VB.NET, возникнут ли какие-либо проблемы с CLS-совместимостью (или другие), если имена различаются только регистром?

Ответы [ 13 ]

234 голосов
/ 30 июля 2013

ВАЖНОЕ ОБНОВЛЕНИЕ (12 апреля 2016 г.):

Нам стало известно, что внутренний стандарт .NET CoreFX team настаивает на использовании знака подчеркивания , не давая понять, почему. Однако если мы внимательно посмотрим на правило № 3, то станет очевидным, что существует система префиксов _, t_, s_, которая позволяет предположить, почему _ был выбран в первую очередь.

  1. Мы используем _camelCase для внутренних и частных полей и используем только для чтения, где это возможно. Префикс полей экземпляра с _, статических полей с s_ и потоковых статических полей с t_. При использовании в статических полях readonly должен идти после static (т.е. static readonly, а не readonly static).
  2. Мы избегаем this., за исключением случаев, когда это абсолютно необходимо.

Так что, если вы просто как команда .NET CoreFX, работающая над неким критически важным для производительности многопоточным кодом системного уровня, то НАСТОЯТЕЛЬНО ПРЕДЛАГАЕМ, что вы:

  • придерживаются своих стандартов кодирования и
  • используйте знак подчеркивания и
  • больше не читать этот ответ

В противном случае, пожалуйста, продолжайте читать ...

ОРИГИНАЛЬНЫЙ ОТВЕТ:

Давайте сначала договоримся о том, о чем мы говорим. Вопрос в том, как получить доступ к членам экземпляра из нестатических методов и конструкторов класса / подклассов, если модификаторы видимости позволяют это делать.

Подчеркивание-нотация

  • предлагает использовать префикс "_" в именах приватных полей
  • также говорится, что вы никогда не должны использовать «это», если это не является абсолютно необходимым

This-нотация

  • предполагает, что вы просто всегда используете «это». получить доступ к любому члену экземпляра

Почему эта нотация существует?

Потому что так ты

  • отличает параметр от поля, когда они имеют одно и то же имя
  • убедитесь, что вы работаете в контексте текущего экземпляра

Пример

public class Demo
{
   private String name;
   public Demo(String name) {
       this.name = name;
   }
}

Почему существует знак подчеркивания?

Некоторым людям не нравится вводить «это», но им все еще нужен способ различать поле и параметр, поэтому они согласились использовать «_» перед полем

Пример

public class Demo
{
   private String _name;
   public Demo(String name) {
      _name = name;
   }
}

Кто-то может подумать, что это вопрос личного вкуса, и оба способа одинаково хороши / плохи. Однако есть некоторые аспекты, где эта нотация превосходит нотацию подчеркивания:

Ясность

  • имена с подчеркиванием в беспорядке
  • this-нотация сохраняет имена без изменений

Когнитивная нагрузка

  • примечание подчеркивания является непоследовательным, оно заставляет вас обращаться с полями особым образом, но вы не можете использовать его с другими членами, каждый раз, когда вам нужно спросить себя, нужно ли вам свойство или поле

  • эта нотация непротиворечива, вам не нужно думать, вы просто всегда используете "this" для обозначения любого члена

ОБНОВЛЕНИЕ: как было указано, следующее не является преимуществом

Техническое обслуживание

  • примечание подчеркивания требует, чтобы вы следили за _ во время рефакторинга, скажем, превращение поля в свойство (удалить _) или наоборот (добавьте _)

  • у этой нотации такой проблемы нет

Автозаполнение

Когда вам нужно увидеть список членов экземпляра:

  • Подчеркивание не очень вам помогает, потому что когда вы набираете «_», всплывающее окно автозаполнения показывает вам закрытые поля и все типы, доступные из связанных сборок, смешанных с остальными членами экземпляра
  • this-нотация дает вам четкий ответ, набрав «this», все, что вы видите, это список членов и ничего больше

Неоднозначность

Иногда вам приходится иметь дело с кодом без помощи Intellisense. Например, когда вы делаете обзоры кода или просматриваете исходный код онлайн.

  • примечание подчеркивания неоднозначно: когда вы видите Something.SomethingElse, вы не можете сказать, является ли Something классом, а SomethingElse является его статическим свойством ... или, возможно, Something является текущим свойством экземпляра, у которого есть собственное свойство SomethingElse

  • эта нотация понятна: когда вы видите Something.SomethingElse, это может означать только класс со статическим свойством, а когда вы видите this.Something.SomethingElse, вы знаете, что Something является членом, а SomethingElse является его свойством

Методы расширения

Вы не можете использовать методы расширений на самом экземпляре, не используя "this".

  • примечание подчеркивания требует, чтобы вы не использовали "this", однако с методами расширения вы должны
  • эта нотация избавляет вас от колебаний, вы всегда используете "это", точка.

Поддержка Visual Studio

  • Нотация подчеркивания не имеет встроенной поддержки в Visual Studio
  • эта нотация поддерживается Visual Studio естественным образом:

    1. http://www.screenr.com/zDCH
    2. "Это." Квалификация : Предпочитать, чтобы все нестатические поля, используемые в нестатических методах, начинались с this. в C #

Официальные рекомендации

Существует множество официальных руководств, в которых четко сказано "не используйте подчеркивания", особенно в C #

67 голосов
/ 16 января 2009

Взято из файла справки Microsoft StyleCop:

TypeName: FieldNamesMustNotBeginWithUnderscore

CheckId: SA1309

Причина: Имя поля в C # начинается с подчеркивания.

Описание правила:

Нарушение этого правила происходит, когда имя поля начинается с подчеркивания.

По умолчанию StyleCop запрещает использование подчеркивания, m_ и т. Д. Для пометки полей локального класса в пользу префикса «this.». Преимущество использования «this.» Заключается в том, что оно в равной степени применяется ко всем типам элементов, включая методы, свойства и т. Д., А не только к полям, благодаря чему все вызовы членов класса могут быть мгновенно распознаны независимо от того, какой редактор используется для просмотра кода. , Другое преимущество состоит в том, что он создает быстрое, узнаваемое различие между элементами экземпляра и статическими элементами, которые не будут иметь префикса.

Если имя поля или переменной предназначено для соответствия имени элемента, связанного с Win32 или COM, и, следовательно, должно начинаться с подчеркивания, поместите поле или переменную в специальный класс NativeMethods. Класс NativeMethods - это любой класс, который содержит имя, оканчивающееся на NativeMethods, и предназначен в качестве заполнителя для оболочек Win32 или COM. StyleCop будет игнорировать это нарушение, если элемент помещен в класс NativeMethods.

Другое описание правила указывает на то, что в дополнение к вышесказанному предпочтительной практикой является запуск личных полей строчными буквами, а открытых - прописными буквами.

Edit: Как следствие, страница проекта StyleCop находится здесь: http://code.msdn.microsoft.com/sourceanalysis. Прочитав файл справки, вы поймете, почему они предлагают различные стилистические правила.

45 голосов
/ 16 января 2009

Будет иметь эффект .

Часть рекомендаций по написанию CLS-совместимых библиотек НЕ должна иметь две открытые / защищенные сущности, которые отличаются только регистром, например, вы должны НЕ иметь

public void foo() {...}

и

public void Foo() {...}

то, что вы описываете, не является проблемой, потому что закрытый элемент недоступен для пользователя библиотеки

23 голосов
/ 16 января 2009

Поскольку речь идет о закрытом поле, оно не влияет на пользователя вашего класса.

Но я рекомендую использовать подчеркивание для частного поля, потому что это может сделать код легче для понимания, например:

private int foo;
public void SetFoo(int foo)
{
  // you have to prefix the private field with "this."
  this.foo = foo;

  // imagine there's lots of code here,
  // so you can't see the method signature



  // when reading the following code, you can't be sure what foo is
  // is it a private field, or a method-argument (or a local variable)??
  if (foo == x)
  {
    ..
  }
}

В нашей команде мы всегда используем префикс подчеркивания для закрытых полей. Таким образом, читая некоторый код, я могу очень легко идентифицировать частные поля и отличать их от локальных и аргументов. В каком-то смысле подчеркивание можно рассматривать как сокращенную версию слова «это».

14 голосов
/ 16 января 2009

После работы в среде, которая имела очень специфические и очень бессмысленные правила стиля, с тех пор я продолжил создавать свой собственный стиль. Это один тип, который я многократно переворачивал. Я наконец решил, что закрытые поля всегда будут _field, локальные переменные никогда не будут иметь _ и будут строчными, имена переменных для элементов управления будут свободно следовать венгерской нотации, а параметры обычно будут camelCase.

Мне не нравится ключевое слово this., на мой взгляд, оно добавляет слишком много кода. Я люблю удалить избыточное это Решарпера. ключевое слово.

Обновление за 6 лет: Я анализировал внутреннее устройство Dictionary<TKey,T> для конкретного использования параллельного доступа и неправильно прочитал приватное поле как локальную переменную. Закрытые поля определенно не должны соответствовать именам локальных переменных. Если бы было подчеркивание, это было бы невероятно очевидно.

12 голосов
/ 16 января 2009

Мне нравится подчеркивание, потому что тогда я могу использовать строчные буквы в качестве параметров метода, например:

public class Person
{
    string _firstName;

    public MyClass(string firstName)
    {
        _firstName = firstName;
    }

    public string FirstName
    {
        get { return _firstName; }
    }
}
7 голосов
/ 16 января 2009

Мне все еще очень нравится использовать подчеркивание перед закрытыми полями по причине, упомянутой Мартином, а также потому, что закрытые поля будут затем сортироваться вместе в IntelliSense. И это несмотря на всю злобность венгерских префиксных обозначений в целом.

Тем не менее, в последнее время я нахожу, что использование префикса подчеркивания для частных пользователей вызывает неодобрение, хотя я не совсем уверен, почему. Возможно, кто-то еще знает? Это просто префиксный принцип? Или было что-то связанное с искажением имен общих типов, которые подчеркивались в них в скомпилированных сборках, или что-то в этом роде?

5 голосов
/ 21 июля 2011

Рекомендация Style Cop или нет, копание в .NET Framework показывает большое использование "_" для переменных-членов. Что бы ни рекомендовали создатели Style Cop, это не то, чем пользуется большинство сотрудников MS. :) Так что я буду придерживаться подчеркивания. Поскольку я лично делаю намного меньше ошибок, используя подчеркивание, чем это (пример: использование varName = varName вместо this.varName = varName, оно действительно застряло во мне)

3 голосов
/ 16 января 2009

Я думаю, что в целом поля уровня класса являются ошибкой в ​​дизайне языка. Я бы предпочел, чтобы свойства C # имели свою локальную область видимости:

public int Foo
{
   private int foo;
   get
   {
      return foo;
   }
   set
   {
      foo = value;
   }
}

Это позволило бы полностью прекратить использование полей.

Единственный раз, когда я делаю префикс частного поля с подчеркиванием, это когда свойство требует отдельного вспомогательного поля. Это также единственный раз, когда я использую частные поля. (И поскольку я никогда не использую защищенные, внутренние или открытые поля, это единственный раз, когда я использую поля period.) Насколько мне известно, если переменная должна иметь область видимости класса, это свойство класса.

2 голосов
/ 16 января 2009

Обозначение _fieldName для частных полей , поэтому его легко разбить . Используя «это». запись невозможно нарушить. Как бы вы нарушили нотацию _? Наблюдать:

private void MyMethod()
{
  int _myInt = 1; 
  return; 
}

Ну вот, я просто нарушил ваше соглашение об именах, но оно компилируется. Я бы предпочел, чтобы соглашение об именах было а) не венгерским и б) явным. Я за то, чтобы покончить с венгерскими именами, и это вполне оправдывает себя. Вместо типа объекта перед именем переменной у вас есть уровень доступа.

Сравните это с Ruby, где имя переменной @my_number связывает имя с областью действия и является неразрывным.

edit: Этот ответ стал отрицательным. Мне все равно, это остается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...