Я видел некоторые руководства или блоги, в которых говорится использование this
получить доступ к собственным участникам класса плохо. Однако я также видел некоторые места, где профессионалы получают доступ с this
. Я склонен предпочитать явно использовать this
, так как это, кажется, проясняет, что вещью, к которой я получаю доступ, является часть класса.
this.MyProperty = this.GetSomeValue();
Есть ли некоторое преимущество или недостаток к использованию this
? Это - просто стилистическое предпочтение?
Пройдя путь от использования этого
в течение многих лет, и обнаружив, что не так много людей (по крайней мере, по моему опыту) используют его, я в конце концов сменил его. Преимущества, которые я вижу в коде без этого:
_myVar
для приватных переменных, которым не нужен this
, так как они всегда являются переменными-членами. например
someclass.Method(1);
SomeClass.StaticMethod(1);
Я вижу, что если вы не используете соглашение об именовании с подчеркиванием и имеете большой метод с весомым телом, это может привести к некоторой путанице.
Статические методы или свойства могут иногда сбивать с толку, но очень редко.
Вам, очевидно, всегда понадобится ключевое слово this
при передаче ссылок, например:
someclass.Method(this);
var someclass = new SomeClass(this);
(Я пишу на C#, но мой ответ относится к Java)
Это действительно полезно в конструкторе
, где код типа
this.field = field;
становится более читабельным. Я бы тоже вставил методы! Раскраска этого
тоже не повредит.
Использование этого кода делает коды более чистыми и удобочитаемыми. Также у вас нет другого выбора, кроме как использовать в ситуации, когда имя параметра совпадает с именем переменной-члена. Как вы их различите?
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
}
}
Он в основном используется для конструкторов и функций инициализации (и я предпочитаю этот стиль различным подчеркиваниям):
MyClass(hisValue) { this->hisValue = hisValue; }
Использование этого стиля повсюду - это просто синтаксическое раздувание, напоминающее венгерскую нотацию. Если вы сделаете функции достаточно короткими, локальные переменные и параметры функций сразу же узнаются читателем кода. Если объявление находится вне экрана, тогда можно предположить, что оно является членом класса, поэтому нотация «this» не добавляет никакой полезной информации.
Я согласен с Дэйвом. Это дольше.
Это просто вопрос стиля, другого эффекта нет.
Это хмурится, почти все время в общем употреблении. Я никогда не использую "это" так.
Люди делают это, потому что они получают интеллект в редакторе, набирая "это", а затем "точка". Вы также видите это во многих местах, когда автоматические генераторы кода делают кодирование.
Теперь, что касается вопроса к , почему использование "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 больше многословия без добавления семантики - это плохо. Мои два цента. Процитируй все, что хочешь.
Это не значит, что "это" не имеет смысла. Отнюдь нет. Если вы используете его для разрешения разницы между вызовом базового члена и члена в текущем объекте, то он имеет свое место. Оно имеет свое место и в генераторах кода. Но, как меня научил виски, чрезмерное использование всего приводит к боли.
Иногда это необходимо, например в конструкторе (в C # или Java), если вы назначаете поле из параметра с тем же именем.
Я всегда использую это.
, потому что, на мой взгляд, это делает код более читаемым. Это сразу дает понять, что
base.
) или замещающий член ( this.
) this.Monster.Legs.Run ();
vs Monster.Legs.Run ();
). Если это добавляет ясности коду, используйте его, если нет. Есть несколько мест, где это действительно добавляет ясности - например, в C ++:
struct Point {
int x, y;
Point & operator=( const Point & p ) {
this->x = p.x;
this->y = p.y;
return *this;
}
};
В таких случаях, когда у вас есть два объекта одного типа для ссылки, я считаю, что использование this
может прояснить вещи (хотя обратите внимание, что в C ++ указанная выше реализация оператора присваивания не требуется).
Я развлекаюсь, пытаясь реализовать бот на основе нейронной сети для настольной игры Дипломатия , взаимодействуя через протоколы 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 вы будете использовать ! =
.
Я бы предложил всегда использовать это
, если код не будет вести себя иначе, если вы не сделали это. Он, по крайней мере, действует как синтаксический сахар для программиста/читателя, чтобы указать, что RHS идет из текущего класса.
Кроме того, в некоторых языках (Perl является одним), если оставить ссылку на объект, то наследственная наследственность не используется при разрешении RHS. например, если methodName определен в родительском объекте, то $ this- > methodName ()
будет работать, но methodName ()
завершится ошибкой, поскольку поиск выполняется только для текущего пакета.
Я всегда использую этот по простой причине:
(Пример на 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;
}
}
Что теперь происходит? И насколько легко можно предотвратить это, всегда используя это?
Конечно, пример нереалистичен, но это легко происходит в более сложных классах и методах и вызывает трудности с отслеживанием ошибок.
Общее правило должно быть таким: используйте «это», чтобы избежать двусмысленности, не используйте это, если очевидно, о чем вы говорите.
Например, при программировании на Java this.getSomeValue ()
не требуется, поскольку все вызовы функций являются вызовами методов для «this». С другой стороны, this.myProperty
может быть полезен, если в вашем методе много локальных переменных или если есть статические переменные-члены, и вы хотите четко указать, что вы обращаетесь к переменной экземпляра.
Конечно, иногда «это» неизбежно, например, в
void setX(int x){ this.x = x; }
Я использую эту , потому что она кажется мне более читабельной. И...
StyleCop правило SA1101: PrefixLocalCallsWithThis говорит:
Причина
Вызов экземпляра члена локального или базового класса не префиксован с помощью 'this.', внутри C# файла кода.
Описание правила
Нарушение этого правила происходит всякий раз, когда код содержит вызов к экземпляру-члену локального класса или базового класса, который не имеет префикса 'this. Исключение из данного правила происходит, когда существует локальное переопределение члена базового класса, и код намерен обратиться непосредственно к члену базового класса, минуя локальное переопределение. В этом случае вызов может быть префиксован с помощью 'base.', а не 'this.'.
По умолчанию StyleCop запрещает использовать подчеркивания или m_ для обозначения полей локального класса, в пользу префикса 'this.'. Преимущество использования 'this.' в том, что оно одинаково применимо ко всем типам элементов, включая методы, свойства и т.д., а не только к полям, делая все вызовы членов класса мгновенно узнаваемыми, независимо от того, какой редактор используется для просмотра кода. Еще одним преимуществом является то, что он создает быстрое, узнаваемое различие между членами экземпляра и статическими членами, которые не являются префиксными.
Конечным преимуществом использования префикса 'this.' является то, что его ввод заставляет Visual Studio показывать всплывающее окно IntelliSense, что делает выбор вызываемого члена класса быстрым и легким для разработчика.
Как исправить нарушение
Для исправления нарушения этого правила, вставьте префикс 'this.' перед вызовом члена класса.
Что касается 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
}
};
В Objective-c
...
prop = value; // just an assignment
...
и
...
self.prop = value; // !!! equivalent to method call [self setProp:value]
...
сильно различаются - вы должны знать что и зачем ты делаешь.