IEqualityComparer on different types

iequalitycomparer lambda
iequalitycomparer gethashcode
iequalitycomparer<string
iequalitycomparer distinct
iequalitycomparer dictionary c#
iequalitycomparer vs iequatable
except iequalitycomparer
contains iequalitycomparer

Given two classes

class Contract
{
    public int ID {get; set;}
    // . . . 
}

class DBContract
{
    public int FromID {get; set;}
    // . . . 
}

And two IEnumerables

IEnumerable<Contract> ValidContracts = Application.GetContracts(//. . .
IEnumerable<DBContract> ExportedContracts = DBAdapter.GetRows(// . . .

I need to find intersection of theese IEnumerables. But how do I implement IEqualityComparer, if it only has one type argument?

Why not use Where and Any instead? It is not as performant as Intersect, but it allows you to filter the way you want:

var list = ExportedContracts.Where(ec => ValidContracts.Any(vc => vc.ID == ec.FromID));

You can't use IEqualityComparer here since the object doesn't have any interface or base class (except object).

IEqualityComparer.Equals(Object, Object) Method (System , The StringComparer class implements IEqualityComparer<T> of type String. methods of the Dictionary<TKey,TValue> class and other generic collections. In order to operate on a collection of mixed types an IEqualityComparer<T>'s type argument T must accept a common ancestor of all types in the collection. Since Contract and DbContract appear unrelated, and do not share a common interface, you need to use object as the universal base class.

In order to operate on a collection of mixed types an IEqualityComparer<T>'s type argument T must accept a common ancestor of all types in the collection.

Since Contract and DbContract appear unrelated, and do not share a common interface, you need to use object as the universal base class.

This may be too complicated for your purposes: perhaps you could implement intersection by ID as follows:

var commonIds = new HashSet<int>(contracts.Select(c => c.Id));
commonIds.IntersectWith(dbContracts.Select(dbc => dbc.FromId));

Now commonIds has IDs of the objects that you need. Running simple Wheres on both sides would produce two statically-typed parts of the intersection:

var commonContracts = contracts.Where(c => commonIds.Contains(c.Id));
var commonDbContracts = dbContracts.Where(dbc => commonIds.Contains(dbc.FromId));

IEqualityComparer<T> Interface, IEqualityComparer is a generic interface defined in the . fix the type parameter as Customer, as we won't need it to compare any other type. Public Class myCultureComparer Implements IEqualityComparer Dim myComparer As CaseInsensitiveComparer Public Sub New() myComparer = CaseInsensitiveComparer.DefaultInvariant End Sub Public Sub New(ByVal myCulture As CultureInfo) myComparer = New CaseInsensitiveComparer(myCulture) End Sub Public Function Equals1(ByVal x As Object, ByVal y As Object) _ As Boolean Implements IEqualityComparer.Equals Return myComparer.Compare(x, y) = 0 End Function Public Function GetHashCode1(ByVal obj As Object

I would create a temporary container for Contract/DBContract:

public class ContractDbContract
{
    public Contract Contract;
    public DBContract DBContract;

    public int ID 
    {
        get
        {
            return Contract?.ID ?? DBContract.FromID;
        }

    }
}

IEnumerable<Contract> ValidContracts = Application.GetContracts(//. . .
IEnumerable<DBContracts> ExportedContracts = DBAdapter.GetRows(// . . .

var validContracts2 = ValidContracts.Select(x => new ContractDbContract { Contract = x });
var exportedContracts2 = ExportedContracts.Select(x => new ContractDbContract { DBContract = x });

Now you can intersect validContracts2 and exportedContracts2 however you want, and then it is easy to "extract" the Contract/DBContract from the ContractDBContract

Implementing IEqualityComparer<T>, It will fail if you have two objects of type A with three properties as shown below: and when it validates prop3, even though they're different, since both B and C  C#: LINQ and IEqualityComparer. When writing programs in C# with the help of LINQ I have come across the IEqualityComparer<T> generic interface several times. The name conveys the purpose of the interface clearly, still, surprisingly, my first attempts to apply it were marked by strong confusion - the thing merely didn't work the way I wanted it to.

If they can't let them implement the same interface like IDBContract and provide a custom IEqualityComparer<IDBContract> you can't use Intersect but you could use Enumerable.Join:

var commonContracts = from c in ValidContracts
                      join ec in ExportedContracts on c.ID equals ec.FromID
                      select new { contract = c, exportedContract = ec };

Join also uses a set based approach so it's more efficient than Where:

Why is LINQ JOIN so much faster than linking with WHERE?

Custom EqualityComparer using IEqualityComparer<> interface , The IEqualityComparer class name tell us your purpose, different Func<T, object> parameter, this type is the same as Select method (System. These two additions were really meant for each other. One of our interns here recently ran into an interesting problem while using LINQ. As a relatively new user of .NET based languages, reference types caused him a bit of trouble. The problem. While using the dot notation with lambda expressions, he was using the Except method in the following

You could implement Intersect yourself, but without using HashSet, something like:

public static IEnumerable<TFirst> Intersect<TFirst, TSecond>(this IEnumerable<TFirst> first, IEnumerable<TSecond> second,
    Func<TFirst, TSecond, bool> comparerFunc)
{
    return first.Where(firstItem => second.Any(secondItem => comparerFunc(firstItem, secondItem)));
}

And use it like:

IEnumerable<Contract> ValidContracts = Application.GetContracts(//. . .
IEnumerable<DBContract> ExportedContracts = DBAdapter.GetRows(// . . .

var intersect = ValidContracts.Intersect(ExportedContracts, (contract, dbContract) => contract.ID == dbContract.FromID);

Introduction To Generic IEqualityComparer, Use a custom IEqualityComparer to implement specialized lookup behavior for Dictionary. A Dictionary can have any type keys and values. best distribution of hash codes would use the second character, the length, and another character​. public class AutoEqualityComparer<T, K> : IEqualityComparer<T> { private readonly Func<T, K> _projection; public AutoEqualityComparer(Func<T, K> projection) { _projection = projection; } Since we now have the strong type of class in equals we can use the EqualityComparer class for both the Equals and GetHashCode methods.

C# IEqualityComparer, Returns a 32-bit integer representation of the object. © 2020 Better Solutions Limited. All Rights Reserved. © 2020 Better Solutions Limited TopPrevNext. IEquatable and All That: The Nine Comparisons Interfaces Simon Robinson .NET , C# September 20, 2014 September 20, 2014 6 Minutes In my last article I pointed out that Microsoft has given us no less than nine different general-purpose interfaces to perform the simple task of comparing objects to see if they are equal, or if one is greater than

C# Interfaces, Creating a comparer class for your type is an alternative to creating Equals() and The generated comparer class will implement the IEqualityComparer<T> interface For details specific to other languages, see corresponding topics in the  This means that overriding Equals allows comparison between two objects of different types (which may be needed in certain circumstances), however, implementing IEqualityComparer does not give this freedom (which may also be needed in certain circumstances).

Generate Equality Comparer - Help, Types and methods should not have too many generic parameters Alternatively IEqualityComparer<T> provides a safer interface and is used by collections or  For more information of IEqualityComparer classic implementation: Spanish - English The IEqualityComparer class name tell us your purpose, different customers for a field ID. Could be more IEqualityComparer classes for different objective and different fields (ForCity, ForSales, etc), as we needed. We use our IEqualityComparer class

Comments
  • You could let them implement a common interface like IDBContract, then provide an IEqualityComparer<IDBContract>.
  • you don't have to implement IEqualityComparer.
  • @TimSchmelter Contract is a library class
  • What should be the result? Contract, DBContract, something else ?
  • @OfirWinegarten that question made me think my question is incorrect. Actually I seek Contract as result
  • Before doing that, I would convert ValidContracts to an array or list.
  • Yeah, that might be a good idea. Or even a dictionary to improve performance.
  • @xanatos it is actually a custom class implementing IList, ICollection ans IEnumebable