Reputation: 894
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
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
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
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