Я должен использовать “это” для вызова свойств класса, участников или методов?

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

this.MyProperty = this.GetSomeValue();

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

14
задан Benny Jobigan 5 February 2010 в 12:54
поделиться

15 ответов

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

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

например

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

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

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

Вам, очевидно, всегда понадобится ключевое слово this при передаче ссылок, например:

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

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

3
ответ дан 1 December 2019 в 07:51
поделиться

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

this.field = field;

становится более читабельным. Я бы тоже вставил методы! Раскраска этого тоже не повредит.

0
ответ дан 1 December 2019 в 07:51
поделиться

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

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
  }
}
0
ответ дан 1 December 2019 в 07:51
поделиться

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

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

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

0
ответ дан 1 December 2019 в 07:51
поделиться

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

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

0
ответ дан 1 December 2019 в 07:51
поделиться

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

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

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

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

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

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

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

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

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

1
ответ дан 1 December 2019 в 07:51
поделиться

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

3
ответ дан 1 December 2019 в 07:51
поделиться

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

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

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

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

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

13
ответ дан 1 December 2019 в 07:51
поделиться

Я развлекаюсь, пытаясь реализовать бот на основе нейронной сети для настольной игры Дипломатия , взаимодействуя через протоколы DAIDE . Оказывается, это очень сложно, поэтому я обратился к XCS, чтобы упростить проблему.

-121--3502293-

Сначала позвольте мне обсудить несколько терминов. Если вы просто хотите получить ответ на свой вопрос, перейдите к разделу "Ответ на ваш вопрос".

Определения

Идентификатор объекта : при создании объекта его можно присвоить переменной. Затем ее можно также назначить другой переменной. И другой.

>>> button = Button()
>>> cancel = button
>>> close = button
>>> dismiss = button
>>> print(cancel is close)
True

В этом случае отмена , закрытие и отмена всех ссылок на один и тот же объект в памяти. Создан только один объект Button , и все три переменные ссылаются на этот объект. Мы говорим, что отменить , закрыть и отклонить все относятся к идентичным объектам; то есть они относятся к одному отдельному объекту.

Равенство объектов : При сравнении двух объектов обычно все равно, что они относятся к точному одному и тому же объекту в памяти. При равенстве объектов можно определить собственные правила сравнения двух объектов. Когда вы пишете , если a = b: , вы по существу говорите , если a.__eq__ (b): . Это позволяет определить метод _ _ eq _ _ для a для использования собственной логики сравнения.

Обоснование сравнений равенства

Обоснование: Два объекта имеют одинаковые данные, но не идентичны. (Они не являются одним и тем же объектом в памяти.) Пример: Строки

>>> greeting = "It's a beautiful day in the neighbourhood."
>>> a = unicode(greeting)
>>> b = unicode(greeting)
>>> a is b
False
>>> a == b
True

Примечание: Здесь используются строки Юникода, поскольку Python достаточно умен, чтобы повторно использовать обычные строки без создания новых в памяти.

Здесь у меня две строки Юникода, a и b . Они имеют одно и то же содержимое, но не являются одним и тем же объектом в памяти. Однако, когда мы сравниваем их, мы хотим, чтобы они сравнивали равные. Здесь происходит то, что объект Юникод реализовал метод _ _ eq _ _ .

class unicode(object):
    # ...

    def __eq__(self, other):
        if len(self) != len(other):
            return False

        for i, j in zip(self, other):
            if i != j:
                return False

        return True

Примечание: _ _ eq _ _ на юникоде определенно реализуется более эффективно, чем это.

Обоснование: два объекта имеют разные данные, но считаются одним и тем же объектом, если некоторые ключевые данные совпадают. Пример: Большинство типов данных модели

>>> import datetime
>>> a = Monitor()
>>> a.make = "Dell"
>>> a.model = "E770s"
>>> a.owner = "Bob Jones"
>>> a.warranty_expiration = datetime.date(2030, 12, 31)
>>> b = Monitor()
>>> b.make = "Dell"
>>> b.model = "E770s"
>>> b.owner = "Sam Johnson"
>>> b.warranty_expiration = datetime.date(2005, 8, 22)
>>> a is b
False
>>> a == b
True

Здесь имеется два монитора Dell: a и b . У них одинаковая марка и модель. Однако они не имеют одинаковых данных и не являются одним и тем же объектом в памяти. Однако, когда мы сравниваем их, мы хотим, чтобы они сравнивали равные. Здесь происходит то, что объект Monitor реализует метод _ _ eq _ _ .

class Monitor(object):
    # ...

    def __eq__(self, other):
        return self.make == other.make and self.model == other.model

Отвечая на вопрос

При сравнении с Нет всегда используйте не . Ни один не является синглтоном в Python - в памяти есть только один его экземпляр.

При сравнении идентификатора это может быть выполнено очень быстро.Python проверяет, имеет ли объект, на который вы ссылаетесь, тот же адрес памяти, что и глобальный объект None - очень, очень быстрое сравнение двух чисел.

Сравнивая равенство , Python должен проверить, имеет ли объект метод _ _ eq _ _ . Если нет, он проверяет каждый суперкласс в поисках метода _ _ eq _ _ . Если найдёт, то Пайтон позвонит. Это особенно плохо, если метод _ _ eq _ _ медленный и не возвращается сразу, когда он замечает, что другим объектом является None .

Вы не внедрили _ _ eq _ _ ? Тогда Python, вероятно, найдет метод _ _ eq _ _ для объекта и будет использовать этот метод, который в любом случае просто проверяет идентичность объекта.

При сравнении большинства других вещей в Python вы будете использовать ! = .

-121--606032-

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

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

0
ответ дан 1 December 2019 в 07:51
поделиться

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

Возьмем, к примеру, такой класс:

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;
    }
}

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

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

0
ответ дан 1 December 2019 в 07:51
поделиться

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

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

Конечно, иногда «это» неизбежно, например, в

void setX(int x){ this.x = x; }
2
ответ дан 1 December 2019 в 07:51
поделиться

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

StyleCop правило SA1101: PrefixLocalCallsWithThis говорит:

Причина

Вызов экземпляра члена локального или базового класса не префиксован с помощью 'this.', внутри C# файла кода.

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

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

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

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

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

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

3
ответ дан 1 December 2019 в 07:51
поделиться

Что касается C ++, при использовании шаблонов иногда необходимо использовать 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
     } 
 }; 
2
ответ дан 1 December 2019 в 07:51
поделиться

В Objective-c

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

и

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

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

1
ответ дан 1 December 2019 в 07:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: