Сравнить String и Object в С#
Смотрите этот код:
object x = "mehdi emrani";
string y = "mehdi emrani";
Console.WriteLine(y == x);
который возвращает true
.
Но этот код:
object x = "mehdi emrani";
string y = "mehdi ";
y += "emrani";
Console.WriteLine(y == x);
возвращает false
.
Поэтому, когда я сравниваю String и Object в первом коде, я получаю true
.
Но когда я сравниваю их во втором коде, я получаю false
.
Обе строки одинаковы, но почему, когда я добавляю к строке, мой результат возвращает false
?
Ответы
Ответ 1
В каждом случае второй операнд ==
равен x
, который имеет тип object
. Это означает, что вы используете обычный оператор равенства.
Теперь в первом случае вы используете две строковые константы с одним и тем же содержимым. Компилятор С# будет использовать один объект для этих двух ссылок. Во втором случае x
и y
относятся к отдельным строковым объектам с тем же содержимым. Две ссылки будут разными, поэтому ==
вернет false.
Вы можете исправить сравнение:
-
Вместо этого используйте Equals
- переопределяемый string
(в отличие от оператора ==
, который только перегружен:
Console.WriteLine(y.Equals(x)); // or x.Equals(y), or Equals(y, x)
Использование статического метода Equals(object, object)
может быть полезно, если любой из аргументов может быть нулевым; это означает, что вам не нужно беспокоиться о NullReferenceException
.
-
Сделайте обе переменные типа string
, после чего во время компиляции будет выбрана перегрузка ==
внутри string
, и эта перегрузка сравнивает содержимое строк, а не только ссылки
Стоит отметить, что это не просто вопрос о строковых литералах, которые сам замечает компилятор С# - это о константах постоянной времени компиляции. Так, например:
object x = "mehdi emrani";
string y = "mehdi " + "emrani";
Console.WriteLine(y == x); // True
Здесь y
инициализируется с использованием двух строковых литералов, которые не совпадают с теми, которые использовались для инициализации x
, но конкатенация строк выполняется компилятором, который реализует ту же самую строку, которую он уже использовал для x
.
Ответ 2
Когда вы инициализировали
object x = "mehdi emrani"; //pointer(x)
Он инициализировал его в памяти и назначил ссылку на x. После этого, когда вы инициализировали
string y = "mehdi emrani"; //pointer(x)
![ref]()
Компилятор обнаруживает, что это значение уже находится в памяти, поэтому оно назначает ту же ссылку на y.
Теперь ==
оператор равенства, который фактически сравнивает адреса вместо значения, находит тот же адрес для обеих переменных, который возвращает true:
x==y //actually compares pointer(x)==pointer(x) which is true
Во втором случае, когда вы инициализировали x и y, которым назначены разные адреса.
object x = "mehdi emrani"; //Pointer(x)
string y = "mehdi "; //not found in memory
y += "emrani"; //Pointer(y)
Теперь сравнение набирает разные адреса, результаты которых ложны:
x == y //is actually Pointer(x) == Pointer(y) which is false
Итак, чтобы преодолеть это, вам нужно использовать .Equals(), который вместо ссылки сравнивает значение и тип объекта.
Console.WriteLine(y.Equals(x)); //compares "mehdi emrani" == "mehdi emrani" results true
Ответ 3
Скорее всего, ссылки сравниваются (стандартная Equals
реализация для объекта). В первом примере С# оптимизирует постоянные строки, и поэтому y и x фактически указывают на один и тот же объект, поэтому их ссылка равна. В другом случае y создается динамически, поэтому ссылка отличается.
Ответ 4
В фоновом режиме новая строка создается каждый раз, когда вы изменяете существующую, потому что строки неизменяемы, что означает, что они не могут измениться.
Для объяснения см. следующее: Почему .NET String является неизменной?
Ответ 5
В первом случае .NET выполняет оптимизацию строковых констант и выделяет только один экземпляр String. Оба x и y указывают на один и тот же объект (обе ссылки равны).
Но во втором случае x и y указывают на разные экземпляры String. Добавление "ermani" к y создает третий строковый объект.
Оператор "==" в принципе возвращает true, если операнды с обеих сторон относятся к одному и тому же объекту. В первом случае x и y относятся к одному и тому же объекту, а в секундах x и y относятся к другим объектам.
Ответ 6
Вы пробовали:
Console.WriteLine(y == x.ToString());