How to use C # LINQ Union to get User List Union1 with List2

I use the Enumerable.Union<TSource> method to get the combination of Custom List1 with Custom List2. But for some reason this does not work, as it should be in my case. I receive all items and a duplicate once.

I followed the MSDN link to do this work, but still I cannot achieve the same.

The following is a custom class code: -

 public class CustomFormat : IEqualityComparer<CustomFormat> { private string mask; public string Mask { get { return mask; } set { mask = value; } } private int type;//0 for Default 1 for userdefined public int Type { get { return type; } set { type = value; } } public CustomFormat(string c_maskin, int c_type) { mask = c_maskin; type = c_type; } public bool Equals(CustomFormat x, CustomFormat y) { if (ReferenceEquals(x, y)) return true; //Check whether the products' properties are equal. return x != null && y != null && x.Mask.Equals(y.Mask) && x.Type.Equals(y.Type); } public int GetHashCode(CustomFormat obj) { //Get hash code for the Name field if it is not null. int hashProductName = obj.Mask == null ? 0 : obj.Mask.GetHashCode(); //Get hash code for the Code field. int hashProductCode = obj.Type.GetHashCode(); //Calculate the hash code for the product. return hashProductName ^ hashProductCode; } } 

I call this the following: -

 List<CustomFormat> l1 = new List<CustomFormat>(); l1.Add(new CustomFormat("#",1)); l1.Add(new CustomFormat("##",1)); l1.Add(new CustomFormat("###",1)); l1.Add(new CustomFormat("####",1)); List<CustomFormat> l2 = new List<CustomFormat>(); l2.Add(new CustomFormat("#",1)); l2.Add(new CustomFormat("##",1)); l2.Add(new CustomFormat("###",1)); l2.Add(new CustomFormat("####",1)); l2.Add(new CustomFormat("## ###.0",1)); l1 = l1.Union(l2).ToList(); foreach(var l3 in l1) { Console.WriteLine(l3.Mask + " " + l3.Type); } 

Please suggest a suitable way to achieve the same!

+7
c # linq extension-methods union
source share
2 answers

The odd thing here is that your class implements IEqualityComparer<CustomClass> instead of IEquatable<CustomClass> . You can pass another instance of CustomClass that will be used as a comparator, but it would be more idiomatic to just make CustomClass implement IEquatable<CustomClass> , and also override Equals(object) .

The difference between IEquatable<T> and IEqualityComparer<T> is that IEquatable<T> says: β€œI know how to compare myself to another instance of T ”, while IEqualityComparer<T> says: β€œI know how to compare two instance of T ". The latter is usually provided separately - just as Union can provide through another parameter. It is very rare for a type to implement IEqualityComparer<T> for its own type - while IEquatable<T> should largely be used only to compare values ​​of the same type.

It implements an implementation using automatically implemented properties for simplicity and more idiomatic parameter names. I would probably change the hash code implementation myself and use expression elements, but that's another matter.

 public class CustomFormat : IEquatable<CustomFormat> { public string Mask { get; set; } public int Type { get; set; } public CustomFormat(string mask, int type) { Mask = mask; Type = type; } public bool Equals(CustomFormat other) { if (ReferenceEquals(this, other)) { return true; } return other != null && other.Mask == Mask && other.Type == Type; } public override bool Equals(object obj) { return Equals(obj as CustomFormat); } public override int GetHashCode() { // Get hash code for the Name field if it is not null. int hashProductName = Mask == null ? 0 : Mask.GetHashCode(); //Get hash code for the Code field. int hashProductCode = Type.GetHashCode(); //Calculate the hash code for the product. return hashProductName ^ hashProductCode; } } 

Now this does not help (as noted in the comments), the documentation for Enumerable.Union is incorrect. It currently says:

The default comparison tool Default used to compare values ​​of types that implement the common IEqualityComparer<T> interface.

He should say something like:

By default, the Default equality is used to compare values ​​when a specific IEqualityComparer<T> not provided. If T implements IEquatable<T> , then the default mapping will be used. Otherwise, it will use the implementation of Equals(object) .

+8
source share

You need to pass an instance of the IEqualityComparer method to the Union method. The method has overload for comparison in your compame.

The simplest and ugliest solution is

 var comparer = new CustomFormat(null,0); l1 = l1.Union(l2, comparer).ToList(); 

You made some mistakes in your implementation. You should not use the IEqualityComparer method for your type ( CustomFormat ), but in a separate class like CustomFormatComparer .

In your type ( CustomFormat ) you must implement IEquatable .

+3
source share

All Articles