I need to compare two List<object>
but during comparison for properties having "string" value I don't want case sensitive comparison.
I have a class:
class User
{
public int Id { get;set; }
public string name { get;set; }
}
I have 2 lists List<User> olduser
and List<User> newuser
. I need to compare both lists but while comparing I should ignore case sensitivity of "name" field and get values in olduser
not part of values in newuser
.
List<User> obsoleteUsers = olduser.Except(newuser).ToList();
I need to add a condition that while comparing two lists, please ignore the case for "name" field.
You can use a custom IEqualityComparer<T>
:
class UserNameComparer : IEqualityComparer<User>
{
public UserNameComparer(StringComparer comparer)
{
if (comparer == null) throw new ArgumentNullException(nameof(comparer));
this.Comparer = comparer;
}
public StringComparer Comparer { get; }
public bool Equals(User x, User y)
{
if (x == null || y == null) return true;
return Comparer.Equals(x.name, y.name);
}
public int GetHashCode(User obj)
{
return Comparer.GetHashCode(obj?.name);
}
}
You use it in Except
(or other LINQ methods):
List<User> obsoleteUsers = olduser
.Except(newuser, new UserNameComparer(StringComparer.InvariantCultureIgnoreCase))
.ToList();
On this way you can implement multiple comparers for different requirements without changing the original class and the way it identifies duplicates(for example by the ID
-property).
Note that Except
(and other set based methods like Distinct
) use GetHashCode
to fast-check if an object equals another. That's why your class should override Equals
and GetHashCode
(always together) to support being used in a set based collection(like HashSet<T>
or Dictionary<TKey, TValue>
). Otherwise you will use the version from System.Object
that just compares references and not properties.
If you want to compare for equality with your own rules, let's implement Equals
and GetHashCode
methods:
class User : IEquatable<User> {
// Dangerous practice: Id (and name) usually should be readonly:
// we can put instance into, say, dictionary and then change Id loosing the instance
public int Id { get; set; }
public string name { get; set; }
public bool Equals(User other) {
if (null == other)
return false;
return
Id == other.Id &&
string.Equals(name, other.name, StringComparison.OrdinalIgnoreCase);
}
public override bool Equals(object obj) => Equals(obj as User);
public override int GetHashCode() => Id;
}
Then you can put Except
as usual
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With