Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Comparing two collections with IEquatable while using only LINQ

This question is for educational purposes only and I can solve it easily by using for loop that returns false on first mismatch.

I am implementing IEquatable<CustomerFeedbackViewModel> on CustomerFeedbackViewModel which has a collection of QuestionViewModel that I need to compare element by element.

public class CustomerFeedbackViewModel 
{
    public List<QuestionViewModel> Questions { get; set; }

    public string PageName { get; set; }

    public string SessionId { get; set; }
}

when implementing Equals instead of using for loop I mentioned above I wanted to use TrueForAll method it would look something like below.

public bool Equals(CustomerFeedbackViewModel other)
    {
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;
        return Questions.TrueForAll((o,i) => o.Equals(other.Questions.ElementAt(i))) && string.Equals(PageName, other.PageName) && string.Equals(SessionId, other.SessionId);
    }

Ofc TrueForAll does not have index and above will never fly.

How could I go around implementing comparison of two lists without using for loop but instead using linq 'oneliner'?

like image 980
Matas Vaitkevicius Avatar asked Feb 02 '16 09:02

Matas Vaitkevicius


1 Answers

Instead of comparing each question at all indexes you should use Enumerable.SequenceEqual:

return string.Equals(PageName, other.PageName) 
    && string.Equals(SessionId, other.SessionId) 
    && Questions.SequenceEqual(other.Questions);

If you don't override Equals + GethashCode in QuestionViewModel you can provide a custom IEqualityComparer<QuestionViewModel> and pass that to the SequenceEqual overload or implement IEquatable<QuestionViewModel>.

like image 98
Tim Schmelter Avatar answered Sep 21 '22 21:09

Tim Schmelter