Я создал программу, в которой у меня есть очередь массивов int:
Queue< int[] > Test = new Queue< int[] >();
Учитывая массив, я хочу проверить, находится ли массив внутри очереди.
В настоящее время я использую пространства имен: System, System.Collections и System.Collections.Generic.
Я попробовал что-то вроде этого:
Queue<int[]> Test = new Queue<int[]>();
Test.Enqueue(new int[] { 20, 20 });
Console.WriteLine( Test.Contains(new int[] { 20, 20 }) ); // Is the array {20,20} inside the queue?
В этом коде мне кажется, что консоль выдаст "true", потому что я добавил массив {20, 20} в очередь, и теперь я проверяю использование метода Contains.
Но когда я запускаю код - консоль выводит false.
У меня есть два вопроса: почему это происходит? И как я могу это исправить?
Поскольку массивы являются ссылочными типами, сравнение будет основываться на ссылках. Даже если содержимое одного и того же, у ваших массивов есть разные ссылки. Вот почему вы ошибаетесь.
Чтобы исправить это, вы можете реализовать пользовательский сопоставитель или использовать методы LINQ
например
bool arrayExists = Test.Any(x => x.SequenceEqual(new[] { 20, 20 }));
Contains()
использует тип сравнения по умолчанию. Для массивов сравнивается ссылка массива, а не содержимое. Вам нужно будет создать собственный сопоставитель сравнений.
Что-то вроде этого:
class ArrayComparer : IEqualityComparer<int[]>
{
public bool Equals(int[] x, int[] y)
{
return x.SequenceEqual(y);
}
public int GetHashCode(int[] obj)
{
int h = 0;
foreach (int item in obj)
{
h = (h << 5) + 3 + h ^ item.GetHashCode();
}
return h;
}
}
Test.Contains(new int[] { 20, 20 }, new ArrayComparer())
По умолчанию массивы сравниваются по ссылке, а не по содержимому. Один из способов его устранения - хранить списки вместо массивов, которые будут сравнивать содержимое. Вы можете преобразовать свои массивы в списки перед добавлением в очередь и обратно, после того, как вытащить их, если это важно.