|
ООП С Sharp - Замечание по поводу ссылочных типов
Прежде чем завершить разговор о классах, нужно предупредить вас об одной потенциальной ловушке, которая может возникнуть в C#, поскольку C# рассматривает все классы как ссылочные типы. Это может иметь некоторые неожиданные эффекты, когда придется сравнивать экземпляры класса на предмет эквивалентности и устанавливать экземпляры классов эквивалентными друг другу.
Например, рассмотрим следующий код:
Authenticator User1;
Authenticator User2 = new Authenticator();
Authenticator User3 = new Authenticator();
User1 = User2;
User2.ChangePassword ("", "Tardis");;
// Это устанавливает password и для User1!
User3.ChangePassword ("", "Tardis");;
if (User2 == User3)
{
// Содержимое этого блока if не будет выполнено, даже несмотря
// на то, что объекты, на которые ссылаются User2 и User3,
// содержат идентичные значения, потому что переменные
// ссылаются на разные объекты
}
if (User2 == User1)
{
// любой код здесь будет выполнен, поскольку User1 и User2
// ссылаются на одну и ту же память
}
В этом коде объявляются три переменных типа Authenticator — User1, User2 и User3. Однако создаются только два объекта класса Authenticator, потому что операция new используется дважды. Затем переменная User1 устанавливается равной User2. В отличие от типов значений, при этом содержимое User2 не копируется. Вместо этого такое присваивание означает, что в User1 устанавливается ссылка на ту же память, что использует User2. В результате этого любое изменение, касающееся User2, также затрагивает и User1, поскольку они не являются отдельными объектами; обе переменные ссылаются на одни и те же данные. Можно также сказать, что они указывают на одни и те же данные, и действительные данные, на которые установлена ссылка, иногда описываются как объект ссылки. Поэтому когда значение password User2 устанавливается равным Tardis, значение password User1 также устанавливается в Tardis. Это серьезно отличается от поведения типов значений. Ситуация становится еще менее интуитивной, когда мы пытаемся сравнивать User2 и User3 в следующей конструкции:
Можно ожидать, что это условие вернет true, так как User2 и User3 имеют одинаковые значения password, потому оба экземпляра содержат идентичные данные. Операция сравнения для ссылочных типов, однако, по умолчанию не сравнивает содержимое данных. Она просто проверяет, ссылаются ли две ссылки на один и тот же адрес памяти. А поскольку это не так, эта проверка вернет false, что означает, что никакой код внутри блока if выполнен не будет. В отличие от этого, сравнение User2 с User1 вернет true, потому что эти переменные указывают на один и тот же адрес памяти. Следует отметить, что это поведение не применимо к строкам, потому что опера- ция == для строк перегружена.
Сравнение двух строк с помощью == всегда сравнивает их содержимое (любое другое поведение строк могло бы ввести в заблуждение).
|