I am trying to merge two lists using list.Union
in LinqPad
but I can\'t get it to work and wanted to check my understanding is correct.
Giv
You can create a class implementing
IEqualityComparer<Test>
Is this class define Equals and GetHashCode After it you can pass this comparer to you Union method Just like that:
public class MyComparer:IEqualityComparer<Test>{
//Equals and GetHashCode
}
var mergedList = list.Union(list2, new MyComparer()).ToList();
Just want to leave this here for anyone that still couldn't get it. I found this article super helpful about the compare class that inherits from IEqualityComparer http://alicebobandmallory.com/articles/2012/10/18/merge-collections-without-duplicates-in-c
You can try something like that if not happy with default comparer (which is, in turn, utilizes GetHashCode method as @IlyaIvanov had mentioned):
// get all items that "other than in first list", so Where() and Any() are our filtering expressions
var delta = list2.Where(x2 => !list.Any(x1 => (x1.Id == x2.Id) && (x1.field1 == x2.field1)));
// now let merge two enumerables that have nothing "equal" between them
var merged = list.Union(delta).ToList();
In your case you simply define some method, that LINQ knows nothing about. It's like creating method bool HeyEquateMeWith(Test other)
and expect, that LINQ will call it when doing set operations.
You need to define your class as following (override Object
's Equals
and GetHashCode
methods):
public class Test
{
public int Id { get; set;}
public int field1 { get; set; }
public override bool Equals(object other) //note parameter is of type object
{
Test t = other as Test;
return (t != null) ? Id.Equals(t.Id) : false;
}
public override int GetHashCode()
{
return Id.GetHashCode();
}
}
Now Union
will call your overridden Equals
and GetHashCode
methods. Also you should ALWAYS override GetHashCode
when you override Equals
method.