user3165438
user3165438

Reputation: 2661

Union lists by content

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

Answers (2)

Sriram Sakthivel
Sriram Sakthivel

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

Pat Burke
Pat Burke

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:

LINQ Distinct

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

Related Questions