Должен ли я использовать "this" для вызова свойств класса, членов или методов?

Я видел несколько руководств или блогов, которые говорят, что использование this для доступа к собственным членам класса является плохим. Тем не менее, я также видел некоторые места, где профессионалы получают доступ с помощью this. Я предпочитаю явно использовать this, поскольку, похоже, ясно, что предмет, к которому я обращаюсь, является частью класса.

this.MyProperty = this.GetSomeValue();

Есть ли какое-то преимущество или недостаток использования this? Это просто стилистические предпочтения?

Ответы

Ответ 1

Из-за использования this в течение многих лет, чтобы найти не много людей (по крайней мере, по моему опыту), использовать его, я в конечном итоге изменился. Преимущества, которые я вижу, имеют такой код:

  • Я использую символы подчеркивания: _myVar для частных переменных, для которых не требуется this, поскольку они всегда являются переменными-членами.
  • Для вызовов методов очень очевидно, что это часть класса. Вы бы добавили имя типа, если это не так.
  • (С#) Частные переменные и параметры всегда верблюд.
  • Если ваш класс настолько велик, что вы сбиваете с толку, вы все равно сталкиваетесь с сплоченностью и разделением проблем.
  • (С#) Типы цветовых кодов Visual Studio, поэтому вы знаете, используете ли вы свойство или тип:

например.

someclass.Method(1);
SomeClass.StaticMethod(1);

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

Статические методы или свойства могут иногда путать вещи, но очень редко.

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

someclass.Method(this);
var someclass = new SomeClass(this);

(пишу С#, но мой ответ относится к Java)

Ответ 2

Если это добавит ясности кода, используйте его, если это не так. Есть несколько мест, которые он добавляет ясности - например, в С++:

struct Point {
   int x, y;
   Point & operator=( const Point & p ) {
      this->x = p.x;
      this->y = p.y;
      return *this;
   }
};

В таких случаях, когда у вас есть два объекта одного типа для ссылки, я нахожу, что использование this может прояснить ситуацию (хотя обратите внимание, что в С++ указанная реализация оператора присваивания не требуется).

Ответ 3

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

  • Он является членом этого экземпляра.
  • Уточняется, если вызывается базовый класс (base.) или переопределяющий элемент (this.)
  • Это не статический член.
  • Это не вызов члена другого статического класса (this.Monster.Legs.Run(); vs Monster.Legs.Run();).

Ответ 4

Иногда это необходимо, например. в конструкторе (на С# или Java), если вы назначаете поле из параметра с тем же именем.

Ответ 5

Я использую это, потому что мне кажется более читаемым. И...

правило StyleCop SA1101: префиксLocalCallsWithThis говорит:

Причина

Вызов члена экземпляра локального класса или базового класса не префикс "this." в файле кода С#.

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

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

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

Последнее преимущество использования этого. префикс заключается в том, что набрав это. приведет к тому, что Visual Studio отобразит всплывающее окно IntelliSense, чтобы разработчик мог быстро и просто выбрать участника класса.

Как устранить нарушения

Чтобы зафиксировать нарушение этого правила, вставьте "this". prefix перед вызовом члену класса.

Ответ 6

Что касается С++, при использовании шаблонов иногда необходимо использовать this, чтобы помочь компилятору с разрешением имен:

 template <typename T> 
 class Base { 
   public: 
     void exit(); 
 };

 template <typename T> 
 class Derived : Base<T> { 
   public: 
     void foo() { 
         exit();   // calls external exit() or error
                   // so you should use this->exit() if that was your intent
     } 
 }; 

Ответ 7

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

Например, при запрограммировании в Java this.getSomeValue() не требуется, поскольку все вызовы функций являются вызовами методов на "this". С другой стороны, this.myProperty может быть полезна, если в вашем методе есть много локальных переменных или если есть статические переменные-члены, и вы хотите четко указать, что вы обращаетесь к переменной экземпляра.

Конечно, иногда "this" неизбежно, как в

void setX(int x){ this.x = x; }

Ответ 8

Он нахмурился, почти все время в общем использовании. Я никогда не использую "this".

Люди делают это, потому что они получают Intellisense в своем редакторе, набрав "this", а затем "точку". Вы также видите это во многих местах, когда автоматические генераторы кода делают кодирование.

Теперь о том, почему использование "this" во всем вашем коде - плохая идея. Во-первых, его можно использовать как костыль, чтобы скрыть отсутствие хорошего соглашения об именах. Например, я считаю этот блок кода "ужасом кодирования":

class Fudge {
   public decimal PoundsOfChocolate {get; set;}
   Fudge (decimal PoundsOfChocoloate) {
       this.PoundsOfChocolate = PoundsOfChocolate;
   }
}

Тьфу. Лучше использовать согласованное соглашение об именах:

class Fudge {
   public decimal PoundsOfChocolate {get; set;}
   Fudge (decimal poundsOfChocoloate) {
       PoundsOfChocolate = poundsOfChocolate;
   }
}

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

Кроме того, если вы перекроете свой код с помощью "this" ключевых слов, это становится более трудным для чтения, так как есть более повторяющийся текст. И это просто более подробно, без добавления семантики. ИМО более многословие без добавленной семантики - это плохо. Мои два цента. Downvote все, что вы хотите.

Это не означает, что "this" не имеет действительных применений. Отнюдь не. Если вы используете его для разрешения разницы между вызовом базового элемента и членом в текущем объекте, то он имеет свое место. Он также имеет место в генераторах кода. Но, как научи меня виски, чрезмерное использование чего-либо приводит к боли.

Ответ 9

В objective-c

...
prop = value; // just an assignment
...

и

...
self.prop = value; // !!! equivalent to method call [self setProp:value]
...

сильно отличаются - вы должны знать, что и почему вы делаете.

Ответ 10

Я согласен с Дейвом. Это длиннее.

Это просто вопрос стиля, другого эффекта нет.

Ответ 11

В основном он используется для конструкторов и функций инициализации (и я предпочитаю этот стиль различным символам подчеркивания):

MyClass(hisValue) { this->hisValue = hisValue; }

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

Ответ 12

Я всегда использую это по простой причине:
(Пример в С#, но не имеет значения)

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

class Foo {
    private int count = 0;
    public List<Int32> foos = new List<Int32>();

    public int DoCounting() {
       foreach (Int32 foo in foos) {
           if (foo > 50) ++count;
       }
       return count;
    }
}

Теперь другой кодер вашей компании должен быстро добавить функцию, т.е. считать другой цикл. Он не смотрит на ваш код, а просто добавляет его из-за критического запроса времени (или потому, что он 11:59 и он хочет сделать перерыв):

class Foo {
    private int count = 0;
    public List<Int32> foos = new List<Int32>();
    public List<Int32> bars = new List<Int32>();

    public int DoCounting() {
       int count = bars.Count;
       for (int i = 0; i < count; ++i) {
           bars[i]++;
       }

       foreach (Int32 foo in foos) {
           if (foo > 50) ++count;
       }
       return count;
    }
}

Теперь, что происходит? И как легко это можно предотвратить, всегда используя это?

Ofc пример нереалистичен, но это происходит легко в более сложных классах и методах и затрудняет отслеживание ошибок.

Ответ 13

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

class Test {
  int a;

  void doA(int a) {
    this.a = a; //if you do a=a its gonna be a bug really hard to catch
  }
}

Ответ 14

Я предлагаю всегда использовать this, если код не будет вести себя иначе, если вы этого не сделали. Он, по крайней мере, действует как синтаксический сахар для программиста/читателя, чтобы указать, что RHS исходит из текущего класса.

Кроме того, на некоторых языках (Perl является одним), если вы опускаете ссылку на объект, тогда иерархия наследования не используется при разрешении RHS. например если methodName определено в родительском, то $this->methodName() будет работать, но methodName() завершится с ошибкой, потому что выполняется поиск только текущего пакета.

Ответ 15

Это действительно полезно в constructor, где код типа

this.field = field;

становится более читаемым. Я бы тоже поставил методы! Окрашивание this тоже не повредит.