#c# #linq #list
#c# #linq #Список
Вопрос:
В принципе, у меня есть структура, которая содержит несколько полей. Я собираюсь создать два списка, содержащих экземпляры этой структуры, и мне нужно иметь возможность проверить, идентичны ли оба списка (т. Е. Одинаковое количество структур и одинаковые значения для всех полей).
Я изучал оператор SequenceEqual, но это зависит от элементов в списке, имеющих одну и ту же ссылку — они не будут, они оба поступают из разных источников.
Я мог бы просто упорядочить списки по полю, перебрать каждый элемент в списке, затем перебрать каждое поле / свойство в списке и посмотреть, совпадает ли оно в другом списке — но это кажется немного чрезмерно сложным. Есть ли более простой способ?
Ответ №1:
SequenceEqual
Оператор сравнивает с помощью средства сравнения, а не по ссылке на последовательности.
Из MSDN: «Определяет, равны ли две последовательности, сравнивая элементы с использованием средства сравнения равенства по умолчанию для их типа».
Используйте SequenceEqual
и реализуйте IEqualityComparer
, и все должно быть в порядке.
var areSame = list1.SequenceEqual(list2, new MyStructComparer());
class MyStructComparer : IEqualityComparer<MyStruct> {
public bool Equals(MyStruct x, MyStruct y) {
if (Object.ReferenceEquals(x, y))
return true;
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
return false;
return x.A == y.A amp;amp; x.B == y.B;
}
public int GetHashCode(MyStruct myStruct)
{
if (Object.ReferenceEquals(myStruct, null))
return 0;
int hashMyStructA = myStruct.A == null ? 0 : myStruct.A.GetHashCode();
int hashMyStructB = myStruct.B == null ? 0 : myStruct.B.GetHashCode();
return hashMyStructA ^ hashMyStructB;
}
}
Комментарии:
1. Это означает, что ему все еще нужно предоставить свой собственный
Equals()
метод в структуре. Ему могло сойти с рук usignfirst.All(i => second.Any(x => x.Id.equals(i.Id)));
2. Это неверно, он мог бы передать
IEqualityComparer
методуSequenceEqual
, который мог бы обрабатывать сравнение. Структура может оставаться в счастливом неведении.
Ответ №2:
Вы можете переопределить Equals()
и сравнить все свойства там и вернуть true, если все они равны.
public struct MyStruct
{
public int A;
public int B;
public override bool Equals(object obj)
{
MyStruct other = (MyStruct) obj;
return A == other.A amp;amp; B == other.B;
}
}
Для равенства списков я бы написал метод расширения:
public static class MyStructExtension
{
public static bool ListsEqual(this IList<MyStruct> a, IList<MyStruct> b)
{
if(a==b)
return true;
if (a == null || b == null)
return false;
if (a.Count != b.Count)
return false;
for (int i = 0; i < a.Count; i )
{
if (!a[i].Equals(b[i]))
return false;
}
return true;
}
}