Сравнить 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());