letie
letie

Reputation: 894

How to replace IF statements for dictionary? (C#, Linq)

I have this equality comparer of a SampleObject:

    public bool Equals(SampleObject x, SampleObject y)
    {
        if (x == null)
        {
            return y == null;
        }

        if (y == null)
        {
            return false;
        }

        if (!string.Equals(x.SomeId, y.SomeId))
        {
            return false;
        }

        if (x.EventsList == null)
        {
            return y.EventsList == null;
        }

        if (y.EventsList == null)
        {
            return false;
        }

        return x.EventsList.OrderBy(e => e)
            .SequenceEqual(y.EventsList.OrderBy(e => e));
    }

What I would like to know is if there is a way to replace all those IF clauses for a dictionary?

Upvotes: 1

Views: 884

Answers (3)

SomeBody
SomeBody

Reputation: 8743

It is not possible with a dictionary, but with a list. A dictionary has no order, hence you can't guarantee that your checks are performed in the right order. I used a list of tuples, where the first item is the condition, and the second item is the return value. Your code will be the following:

public bool Equals(SampleObject x, SampleObject y)
{
var checks = new List<(Func<bool>,Func<bool>)>
{
    (() => x == null, () => y == null),
    (() => y == null, () => false),
    (() => !string.Equals(x.SomeId, y.SomeId), () => false),
    (() => x.EventsList == null, () => y.EventsList == null),
    (() => y.EventsList == null, () => false)
};
foreach(var entry in checks)
{
     if(entry.Item1.Invoke())
     {
       return entry.Item2.Invoke();
     }
}
return x.EventsList.OrderBy(e => e)
            .SequenceEqual(y.EventsList.OrderBy(e => e));
}

But I strongly recommend to stay with your original version, because from my point of view the readability strongly decreases with this approach. Sometimes a classic sequence of if statements is much more appropriate then any fancy LINQ or whatever stuff.

Upvotes: 2

Olivier Jacot-Descombes
Olivier Jacot-Descombes

Reputation: 112682

I don't think a dictionary is of any help here. You can replace all the if-statements by a simple expression:

return
    x == null && y == null ||
    x != null && y != null &&
    String.Equals(x.SomeId, y.SomeId) &&
    (x.EventsList == null && y.EventsList == null ||
     x.EventsList != null && y.EventsList != null &&
     x.EventsList.OrderBy(e => e)
        .SequenceEqual(y.EventsList.OrderBy(e => e));

Note that because of C#'s short-circuit evaluation, the expression has to be evaluated only partially in most cases.

Upvotes: 1

Dmitrii Bychenko
Dmitrii Bychenko

Reputation: 186813

Well, I doubt if Dictionary is of any help here, but you can slightly simplify the routine into

public bool Equals(SampleObject x, SampleObject y) {
  if (ReferenceEquals(x, y))
    return true;
  else if (x == null || y == null)
    return false;

  // From now on, both x and y are not null

  //TODO: to avoid such constructions, do not let collections be null, but empty 
  if (x.EventList == null || y.EventList == null)
    return x.EventList == y.EventList;

  // From now on, both x.EventList and y.EventList are not null

  return string.Equals(x.SomeId, y.SomeId) &&
         x.EventList.OrderBy(e => e).SequenceEquals(y.EventList.OrderBy(e => e));
}

Upvotes: 2

Related Questions