There is a class

public class DB { public string vopros { get; set; } public string otvet { get; set; } public string url { get; set; } } 

There are two lists

 List<DB> list1 = new List<DB>(); List<DB> list2 = new List<DB>(); 

How to compare these two list ? so that for example in list3 were those elements that are in the first and not in the second?

Going through the cycle I think is not so good. Maybe there is a better solution?

5 answers 5

If you just need to compare, that is, find out whether the lists are the same or not, use the SequenceEquals method.

 list1.SequenceEquals(list2) 

This method also compares the order of elements .

If you need to find out whether the sets of elements coincide without taking into account the order, it is most effective to construct a set from the first sequence, and check the equality as follows:

 new HashSet<DB>(list1).SetEquals(list2) 

If you need to compare not instances, but values, then you either define a universal comparison method (implement IEquatable<DB> ), or pass your implementation to IEqualityComparer<DB> as follows:

 list1.SequenceEquals(list2, comparer) 

or respectively

 new HashSet<DB>(list1, comparer).SetEquals(list2) 
     using System.Linq; //.... var list3 = list1.Except(list2).ToList(); 

    If the elements need to be compared by the value of the fields, then you will have to do one of the following:

    • change class to struct
    • override in DB methods Equals and GetHashCode
    • create a heir class from IEqualityComparer<DB> and pass an instance of this class as a second parameter in Except

      In general, at the moment, it seems to me, the correct solution would be to use the method

      Enumerable.SequenceEqual <TSource> (c) MSDN

      And the code will look something like this:

      bool isEqual = list1.SequenceEqual(list2);

         foreach (var item in list1) { if (list2.Any(c => c.vopros == item.vopros)) { list3.Add(item); } } 

          To correctly compare two lists of objects of type Т you need to implement IEqualityComparer<T> for this type. I write the code "on the knee", so I apologize for any syntactic errors.

           public class DbComparer: IEqualityComparer<DB> { pablic static DbComparer Comparer {get;} = new DbComparer(); private DbComparer{} public bool Equels(DB one, DB two) { //описываем логику сравнения объектов заданного типа return string.Compare(one.vopros, two.vopros, StringComparison.CurrentCulture) == 0 && string.Compare(one.otvet, two.otvet, StringComparison.CurrentCulture) == 0 && string.Compare(one.url, two.url, StringComparison.CurrentCulture) == 0; } pablic int GetHashCode(DB obj) { //реализация для .NET Core. для .NET Framework на память не помню return System.HashCode.Combine(obj.vopros, obj.otvet, obj.url ) } } 

          Example of use:

           var hashOne = new HashSet<DB>(list1, DbComparer.Comparer); var hashTwo = new HashSet<DB>(list2, DbComparer.Comparer); hashOne.SymmetricExceptWith(hashTwo); //SymmetricExceptWith оставит в hashOne только уникальные элементы if (hashOne.Count > 0) { //Если списки отличаются do something } 

          For small lists, it works quickly, but for large ones it does not test.