Сравнение двух одномерных массивов C#

504
09 декабря 2016, 08:48

День добрый, ситуация следующая:

  • копируем массив, в составе которого N строк StringBuilder
  • в изначально массиве, в каждой строке производим замену ОО на ++
  • проверяем скопированный массив с изначального массива, с измененным массивом.

Вопрос:

  • даже если замена не производится, т.е. условий для замены нету, при сравнении итоговых массивов возвращается false

    Почему? Что такого делает Replace кроме как поиска и замены?

    StringBuilder[] raws1 = new StringBuilder[n];
    Array.Copy(raws, raws1, 0);
    for (int i = 0; i < n; i++)
    {
        raws[i] = raws[i].Replace("OO", "++");
    }
    if (Equals(raws1,raws))
    {
        Console.WriteLine("NO");
    }
    else
    {
        Console.WriteLine("YES");
        for (int i = 0; i < n; i++)
        {
            Console.WriteLine("{0}", raws[i]);
        }
    }
    
Answer 1

Как уже написал @free_ze, метод Array.Equals не имеет никакого отношения к сравнению данных массива. Этот метод сравнивает, являются ли указанные аргументы ссылками на один и тот же массив.

Чтобы сравнить элементы массивов используйте хотя бы Enumerable.SequenceEqual:

bool isEqual = Enumerable.SequenceEqual(target1, target2);

Однако, обратите винмание, что в вашем коде есть ещё одна проблема. Когда вы копируете ссылки на StringBuilder, а потом меняете значение содержимого StringBuilder при помощи метода Replace, то меняются данные объекта, на который сслается и первый массив и копия.

Правильнее сказать, что вы не создаёте копию набора StringBuilder, вы создаёте копию ссылок на них.

Не путайте StringBuilder.Replace и string.replace. Это совершенно разные вещи. StringBuilder.Replace меняет содержимое себя и возвращает ссылку на себя же, вне зависимости от того, нашлось что-то для замены или нет. string.replace создаёт новую строку и возвращает ссылку на неё, если нашлось что поменять, а если не нашлось, то возвращает ссылку на себя.

Если бы вы работали с массивами ссылок на System.String, то у ваш код заработал бы как ожидалось.

Если работать надо именно с классом StringBuilder то при создании копии надо использовать что-то вроде:

for(int index = 0; index < raws.Length; index++)
{
    raws1[index] = new StringBuilder(raws[index].ToString());
}

Обратите внимание, что при такой тактике, вы будете подвержены ещё одной потенциальной проблеме. А именно, метод StringBuilder.Equals сравнивает не только строку, которая в нём хранится, но так же свойства Capacity, и MaxCapacity, которые могут меняться в процессе манипуляций со строками внутри StringBuilder.

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

Answer 2

Array.Equals наследуется от Object, т.е. сравнивает ссылки на объекты массивов.

Answer 3

Дабы избежать работы с ссылками, пришлось уйти от StrinBuilder'a и сделать все через строки. Тем самым, сравнение происходит корректно. Спасибо @ZverevEugene и @free_ze.

     `for (int i = 0; i < n; i++)
        {
           str1[i] = raws[i].Replace("OO", "++");
        }
      bool isEqual=Enumerable.SequenceEqual(str1, raws); `
READ ALSO
Многопоточность, блокировка доступа

Многопоточность, блокировка доступа

Есть приведенный ниже код, суть в том, что функции Add(), Read(), Modify(), Remove(), вызываются извне и в хаотичном порядке, с разным периодом во времени

233
Нужен пример ssh client на C#, с использованием granados

Нужен пример ssh client на C#, с использованием granados

Добрый вечерВстала задача написать SSH client на C#, и после долгих поисков по просторам интернета и чтения разных статей, постов и вопросов-ответов...

339
Файл не докачивается полностью

Файл не докачивается полностью

Когда пытаюсь скачать файл с сервера, файл начинает качаться в корректной папке, но почему то не хочет продолжать качатьсяПочему? Вот код:

224
WaitHandle.WaitAll в Closing (C# WPF)

WaitHandle.WaitAll в Closing (C# WPF)

Есть следующий код:

267