Reputation: 2661
I have 2 lists:
list1<a>
list2<b>
I would like to merge these 2 lists without duplicates according to a property exist in a and b.
To do so I have to override the methods Equals and GetHashCode.
public override bool Equals(object otherInstance)
{
MyClass instance = otherInstance as MyClass ;
return (instance != null) ? GetGuid.Equals(instance .GetGuid) : false;
}
public override int GetHashCode()
{
return GetGuid.GetHashCode();
}
However, I cannot inherit class A and class B from a common base class, since they already extend other classes and multiple inheritance is invalid using C#.
Any ideas?
Upvotes: 0
Views: 118
Reputation: 73442
There are number of ways you can get this done. I'll take a shortcut. This should work if you're using .Net 4.0 and above, If not please drop a comment I'll update my answer.
List<Class1> list1 = new List<Class1>();
list1.Add(new Class1());
List<Class2> list2 = new List<Class2>();
list2.Add(new Class2());
var unionList = list1.Cast<object>()
.Union(list2.Cast<object>(), new DynamicComparer())
.ToList();
internal class DynamicComparer : IEqualityComparer<object>
{
public new bool Equals(object x, object y)
{
dynamic dx = x;
dynamic dy = y;
return dx.Guid == dy.Guid;
}
public int GetHashCode(object obj)
{
dynamic dobj = obj;
return dobj.Guid.GetHashCode();
}
}
internal class Class1
{
public Guid Guid { get; set; }
}
internal class Class2
{
public Guid Guid { get; set; }
}
Since I don't know how you implemented GetHashCode
and Equals
I just given a example. This should give you a idea of how to start.
How does it works: We're using IEqualityComparer<T>
interface to get the job done which is used to implement custom comparison rules to find object equiality. but the problem is we don't have a common interface or base class for Class1
and Class2
only way to represent it as common is via System.Object
so we implement IEqualityComparer<object>
.
Then implementation of Equals
is pretty simple it just converts the parameters to dynamic which leverages dynamic feature of .Net4.0. then simply compare the properties or fields dynamically(no compile time failure) in this case we compare Guid
property and that's all.
Worth noting that this may fail if the property doesn't exist in runtime rather than compile time.
Hope this helps.
Upvotes: 3
Reputation: 590
You have a couple good options here. Although C# doesn't support multiple inheritance, it does support some pretty handy interfaces here. You could use IComparable or IEquatable to hand-roll your own solution, or use the LINQ Distinct method.
Another option is to use LINQ Distinct and pass an IEqualityComparer.
Have the A and B implement a common interface which contains Prop. Then:
class MyClassComparer<T> : IEqualityComparer<MyClass>
{
public bool Equals(object otherInstance)
{
MyClass instance = otherInstance as MyClass ;
return (instance != null) ? GetGuid.Equals(instance .GetGuid) : false;
}
public int GetHashCode()
{
return GetGuid.GetHashCode();
}
}
}
listA.AddRange(listB); //Need to be List<ICommonInterface> Common Interface
var distinctList = listA.Distinct(new MyClassComparer<T>());
Upvotes: 1