So I am utilizing CollectionBase as an inherited class for custom collections. I am utilizing CollectionBase through an abstract class so that I don't repeated knowledge (following the DRY principle). The abstract class is defined as a generic class also. Here is how I am implementing my class:
public abstract class GenericCollectionBase<T,C> : CollectionBase
{
//Indexders, virtual methods for Add, Contains, IndexOf, etc
}
I utilize this so I don't have to implement these base methods in 10+ classes.
My question is am I taking this too far when I override the Equals method like this:
public override bool Equals(object obj)
{
if (obj is C)
{
GenericCollectionBase<T, C> collB =
obj as GenericCollectionBase<T, C>;
if (this.Count == collB.Count)
{
for (int i = 0; i < this.Count; ++i)
{
if (!this[i].Equals(collB[i]))
return false;
}
return true;
}
}
return false;
}
Am I trying to accomplish too much with my abstract, or doing this the correct way?
EDIT: This is written for .Net 2.0 and do not have access to 3.5 to utilize things like LINQ
I don't believe you are trying to accomplish too much. If an abstract class was meant to not have any implementation at all, or other methods which define functionality, then they would be interfaces.
The only thing I would change is to use EqualityComparer<T> instead of equals for the comparison of this[i] and collB[i].
Well, first, this is weird :
if (obj is C)
{
GenericCollectionBase<T, C> collB = obj as GenericCollectionBase<T, C>;
I'll assume you meant that :
GenericCollectionBase<T, C> collB = obj as GenericCollectionBase<T, C>;
if (collB != null)
{
...
I think you're over-thinking this, except if you really, really need two different collections with the same content to be considered as equal. I'd put this logic in another method to be called explicitly or in an equality comparer.
Making an extension method against IDictionary would be far more useful. There's also methods like Intersect from LINQ that may be useful.
I don't know if you're trying to accomplish too much, but I think you're trying to accomplish the wrong thing. There are cases where you might want that type of equality for collections, but it should be opt-in and obvious from the name of the type. I've created a ListValue<> with the type of equality you're using, but then it's always been immutable as well.
Also, if you're going to do this type of equality check, an initial test using object.ReferenceEquals can save you from having to iterate over a large collection when your comparing an object to itself.
Related
I would like to compare an object with antoher to know if they are equal or not. So it seems the way to do that is implementing the IEquatable interface in my class.
But I am not sure about how this affect to the behaviour of my class. Now, in my code, I use to compare two object by reference in this way:
if(myObject1 == myObject2)
{
// code when both objects are the same.
// Set values in some properties and do some actions according that.
}
else
{
// code when both objects are no the same.
// Set values in some properties and do some actions according that.
}
But in some special cases, mainly in testing, I would like to compare 2 objects and considerate equal if all the properties are equal, but in this case I don't know if it will affect to my main code, in which I am compare by reference.
Another option could be implement a method that compare in this way, but I don't know if it is a good idea or it is better to implement the IEquatable interface.
Thanks.
There are several different things going on here.
The first is that IEquatable<T> is not directly related to the == operator. If you implement IEquatable<T>, but you don't override the == operator, then == will continue to do what it currently does: compare your objects by reference.
IEquatable<T> gives you an Equals(T) method, and that's it. By itself, it doesn't affect Equals(object) (which you also need to implement), or == and !=.
So let's assume that you do overload the == operator, to call our Equals method:
public static bool operator ==(Foo left, Foo right) => Equals(left, right);
public static bool operator !=(Foo left, Foo right) => !Equals(left, right);
This has only changed the == operator between two Foo instances. You can still write:
if ((object)myObject1 == (object)myObject2))
and that will fall back to using object's == method, which compares by reference.
Another way to do this is:
if (ReferenceEquals(myObject1, myObject2))
which just does the same thing.
Also note that it's rare to implement IEquatable<T> for classes: there's really no point. Classes already have an Equals(object) method and a GetHashCode() method which you need to override, and adding an Equals(T) method doesn't give you much.
IEquatable<T> is however useful for structs: they also have an Equals(object) method you need to override, but if you actually call it then you're going to end up boxing, since it accepts object. If you implement IEquatable<T> here then you also get an Equals(T) method, which you can call without boxing anything.
All of that said, I would write your code as it's intended to work in your application, and do any testing-specific stuff in your test project. This means that if your objects should be compared by reference in your code, I wouldn't add anything new to the object itself.
In your test project, you can write your own method to check whether two instances of your object have the same properties (either as a custom bool AreFoosEqual(Foo f1, Foo f2), or as a full-blown IEqualityComparer<Foo> instance). You can then make this do exactly what your tests need, without worrying about breaking your application.
You can also write your test method as a series of assertions, which tells you which property is incorrect, and what the difference is. This can give you richer test output:
public static void AssertFoosEquals(Foo f1, Foo f2)
{
Assert.AreEqual(f1.Foo, f2.Foo, "Foo property mismatch");
Assert.AreEqual(f1.Bar, f2.Bar, "Bar property mismtach");
}
If you want to compare same objects but in different ways, I suggest using a comparer which implements IEqualityComparer<T>:
public class MyClassTestComparer : IEqualityComparer<MyClass> {
public bool Equals(MyClass x, MyClass y) {
if (ReferenceEquals(x, y))
return true;
else if (null == x || null == y)
return false;
return x.Propery1 == y.Property1 &&
x.Propery2 == y.Property2 &&
x.ProperyN == y.PropertyN;
}
public int GetHashCode(MyClass obj) {
return obj == null
? 0
: obj.Propery1.GetHashCode() ^ obj.Propery2.GetHashCode();
}
}
then you can choose the right comparer
public static IEqualityComparer<MyClass> MyClassComparer {
if (we_should_use_test_comparer)
return new MyClassTestComparer();
else
return EqualityComparer<MyClass>.Default;
}
Finally if will be
if (MyClassComparer.Equals(myObject1, myObject2)) {
// Equals: by reference or by properties (in test)
}
When you make a unit test ->
Like:
public void TestSomething()
{
var expectedValue1 = "SomeExpectedValue";
var actualValue = instance.Method();
Assert.Equal(expectedValue1, actualValue);
}
Then you "simply" assert the properties you want to look at, if you return an object and not a value:
public void TestSomething()
{
var expectedValue1 = "SomeExpectedValue";
TestableObject subject = instance.Method();
Assert.Equal(expectedValue1, subject.Somevalue);
}
If you want a more generic setup, you can write a reflection using generic flow, that looks at all properties on an object and attempts to match them to the another provided object.
Or you could download a nuget package of tools that already allow you to do this.
I would not override any functionality, simply for the purpose of testing. That way lies spaghetti code.
Ideally your code should be 100% verifiable by unit tests, without having specific code sections that augment or assist your testing methods. (Unless said code is restricted to the test project itself, and is not contained within any of the actual code being tested.
I've implemented IEqualityComparer and IEquatable (both just to be sure), but when I call the Distinct() method on a collection it does not call the methods that come with it. Here is the code that I execute when calling Distinct().
ObservableCollection<GigViewModel> distinctGigs = new ObservableCollection<GigViewModel>(Gigs.Distinct<GigViewModel>());
return distinctGigs;
I want to return an ObservableCollection that doesn't contain any double objects that are in the 'Gigs' ObservableCollection.
I implement the interfaces like this on the GigViewModel class:
public class GigViewModel : INotifyPropertyChanged, IEqualityComparer<GigViewModel>, IEquatable<GigViewModel>
{
....
}
And override the methods that come with the interfaces like so:
public bool Equals(GigViewModel x, GigViewModel y)
{
if (x.Artiest.Naam == y.Artiest.Naam)
{
return true;
}
else
{
return false;
}
}
public int GetHashCode(GigViewModel obj)
{
return obj.Artiest.Naam.GetHashCode();
}
public bool Equals(GigViewModel other)
{
if (other.Artiest.Naam == this.Artiest.Naam)
{
return true;
}
else
{
return false;
}
}
Thanks for all the help I'm getting. So I've created a seperate class that implements IEqualityComparer and passed it's instance into the disctinct method. But the methods are still not being triggered.
EqualityComparer:
class GigViewModelComparer : IEqualityComparer<GigViewModel>
{
public bool Equals(GigViewModel x, GigViewModel y)
{
if (x.Artiest.Naam == y.Artiest.Naam)
{
return true;
}
else
{
return false;
}
}
public int GetHashCode(GigViewModel obj)
{
return obj.Artiest.Naam.GetHashCode();
}
}
The Distinct() call:
GigViewModelComparer comp = new GigViewModelComparer();
ObservableCollection<GigViewModel> distinctGigs = new ObservableCollection<GigViewModel>(Gigs.Distinct(comp));
return distinctGigs;
EDIT2:
The GetHashCode() method DOES get called! After implementing the new class. But the collection still contains duplicates. I have a list of 'Gigs' that contain an 'Artiest' (or Artist) object. This Artist has a Naam property which is a String (Name).
So you had the object that itself is being compared implement both IEquatable as well as IEqualityComparer. That generally doesn't make sense. IEquatable is a way of saying an object can compare itself to something else. IEqualityComparer is a way of saying it can compare two different things you give it to each other. You generally want to do one or the other, not both.
If you want to implement IEquatable then the object not only needs to have an Equals method of the appropriate signature, but it needs to override GetHashCode to have a sensible implementation for the given definition of equality. You didn't do that. You created GetHashCode method that takes an object as a parameter, but that's the overload used for IEqualityComparer. You need to override the parameter-less version when using IEquatable (the one defined in Object).
If you want to create a class that implements IEqualityComparer you need to pass the comparer to the Distinct method. Since you've defined the object as its own comparer you'd need to pass in some instance of this object as the second parameter. Of course, this doesn't really make a whole lot of sense this way; so it would be better, if you go this route, to pull out the two methods that go with IEqualityComparer into a new type, and create an instance of that type to the Distinct method. If you actually passed an object with those definitions in as a comparer, it'd work just fine.
Following MSDN's advice, you'd be best off creating a separate class for your equality comparisons:
We recommend that you derive from the EqualityComparer class
instead of implementing the IEqualityComparer interface, because
the EqualityComparer class tests for equality using the
IEquatable.Equals method instead of the Object.Equals method. This
is consistent with the Contains, IndexOf, LastIndexOf, and Remove
methods of the Dictionary class and other generic
collections.
So, create a class, GigViewModelComparer, that derives from EqualityComparer and put your Equals and GetHashCode methods there.
Then, pass in an instance of that new comparer class in your call to Gigs.Distinct(new GigViewModelComparer()) and it should work. Follow along in the example in the MSDN link I provided above.
I've never seen somebody implement IEqualityComparer in the same class as the type of objects the collection in question contains, that is probably at least part of your problem.
Is there something like anonymous inner classes (used in Java) in C#?
I explain what I would use it for by example: I'm declaring and initializing field of type IDictionary<Person, Account> and I need to write custom IEqualityComparer<Person>. That is because I want two Persons to be treated as equal by the IDictionary when they have equal names and IDs (not only IDs as it is by default). I will not need this IEqualityComparer<Person> anywhere else in the code.
So I do I have to declare new class that implements IEqualityComparer<Person> to do this ? In Java I would use anonymous class, something like this(this is mixed C#-Java syntax, just to show what functionality I'm looking for):
IDictionry<Person, Account> myDict = new Dictionary<Person, Account>(
new IEqualityComparer<Person>(){
public bool Equals(Person a, Person b){
return a.Id == b.Id && a.Name == b.Name;
}
public int GetHashCode(Person p){
return p.Id.GetHashCode() * p.Name.GetHashCode();
}
});
Is something like this in C# ? I'm too lazy to write new class every time I need something like this.
Note: This is syntax question. I know how to write it, but I want to know if it's possible to make the code shorter.
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
EDIT: How do you yourself code similar cases ? Do you create new class to implement the interface or what do you do ? Maybe you have some trick that I might like.
EDIT What about future support for anonymous classes like those in Java ? Have you heard something about it ?
EDIT: Well I see I'll have to provide my actual code - not just an example. That's because I don't know if it's going to work with Jon's Skeet's solution.
The actual reason why I don't just implement Equals(object) and GetHashCode in the class itself is, that it's class(entity) generated by E-R framework from model diagram. If I implemented it in class itself my code would be deleted from the class(entity) every time I update the model from database (using "update from database" feature). The class is actually called Font not Person. It has this properities:
Id: int
FamilyName:string
Size:int
Bold:bool
Italic:bool
Underlined:bool
Striked:bool
Foreground:Color
Where Color is another class (entity) generated from database.
This are properties of Color:
Id:int
Alpha:byte
Red:byte
Green:byte
Blue:byte
So I cannot modify Font, neither Color (if I don't want to rewrite those changes over and over again every time I change database) What I want is to have this Dictionary:
private IDictionary<Font, Something> cache = new Dictionary<Font, Something>(new SomeEqualityComparer());
And the comparer SomeEqualityComparer should ensure that two Fonts would be considered equal if and only if all the properties listed above(except Id) are equal. In the case of last property Foreground two Colors are considered equal when all their properties(except Id) are equal.
Now if I use solution that Jon Skeet has kindly recommended me, I'm not sure if that can be ensured.
If I used something like:
private IDictionary<Font, Something> cache = new Dictionary<Font, Something>(ProjectionEqualityComparer<Font>.Create
(f => new { f.FontName, f.Size, f.Bold, f.Italic, f.Underlined, f.Striked, f.Foreground});
I'd guess that anonymous types call Equals(object) on all properties when their Equals(object) is called. However as I cannot override Color's Equals(object) it would not compare Colors as I want (using all properties except Id) so also the equality of Fonts would be tested incorrectly. Am I right ?
I have a ProjectionEqualityComparer class you could use in MiscUtil. You'd use code like this:
IEqualityComparer<Person> comparer = ProjectionEqualityComparer<Person>.Create
(p => new { p.Name, p.Id });
Thhat uses the fact that anonymous types have appropriate equality notions built in - when the ProjectionEqualityComparer is asked to compare two people for equality, it will project each to the anonymous type, and compare those instances. Likewise when it's asked for a hashcode, it will perform the projection and ask that for its hash code.
EDIT: To tackle your colour problem, you're right: if Color doesn't override Equals/GetHashCode in the way that you want, you can't use it directly. However, you can do this instead:
private IDictionary<Font, Something> cache = new Dictionary<Font, Something>
(ProjectionEqualityComparer<Font>.Create(f => new {
f.FontName, f.Size, f.Bold, f.Italic, f.Underlined, f.Striked,
f.Foreground.Alpha, f.Foreground.Red, f.Foreground.Green,
f.Foreground.Blue});
If you're able to modify the Color type in terms of properties, it would be simpler if you could give it an ARGB property generated from the others, so you could write:
private IDictionary<Font, Something> cache = new Dictionary<Font, Something>
(ProjectionEqualityComparer<Font>.Create(f => new {
f.FontName, f.Size, f.Bold, f.Italic, f.Underlined, f.Striked,
f.Foreground.ARGB });
That's pretty ugly, but it should work...
In your last edit you mention that the reason that you don't implement Equals and GetHashCode is because the code for your classes is auto-generated and you don't want to have to re-implement that code each time you regenerate the code.
That's one of the scenarios for which partial classes were introduced in C#
A lot of code generation tools will generate classes with the partial keyword to allow you to take advantage of that feature. Check if the classes that are being generated for your code are partial.
In a separate file (or files) that won't be overwritten when you regenerate the code, within the same assembly, you could have something like the following:
partial class Font
{
public override bool Equals(object obj)
{
// ...
}
public override int GetHashCode()
{
// ...
}
}
partial class Color
{
public override bool Equals(object obj)
{
// ...
}
public override int GetHashCode()
{
// ...
}
}
No there isn't. There are anonymous types e.g.
var MyType = new { id=1, name="john", dept = "sales" };
but they are very limited, and only contain read only properties and no methods.
The literal answer is that no, C# doesn't have anonymous inner classes, because Java added those to get around its lack of first-class functions, which C# does have. More specifically, to solve your problem, you can just implement IEquatable<Person> on your Person class, and then IDictionary will use that automatically. That's the most common solution to this problem and works as long as your OK with the process for comparing Persons being baked into that class.
If you want the comparison/equality logic to not be tied directly to Person, most collections in .NET allow you to pass in a Comparison<T> object (which is a delegate, not an interface), letting you do nice in-place sorting logic. For example, to sort a list of people by name, you could do:
List<Person> people = ...
people.Sort((x, y) => x.Name.CompareTo(x.y));
Unfortunately, Dictionary doesn't have something similar to an equality function. In .NET 4.0, the stock answer seems to be to override EqualityComparer<T>:
public class PersonComparer : EqualityComparer<Person>
{
public override bool Equals(Person a, Person b)
{
return a.Id == b.Id && a.Name == b.Name;
}
}
Having to define a new class each time you need to compare, though, is a chore. What I'd do is make a generic one that takes a function:
public class Equality<T> : EqualityComparer<T>
{
public Equality(Func<T, T, bool> comparer)
{
this.comparer = comparer;
}
public override bool Equals(T a, T b)
{
return comparer(a, b);
}
private Func<T, T, bool> comparer;
}
Add a little helper class:
public static class Equality
{
public static Equality<T> Create<T>(Func<T, T, bool> comparer)
{
return new Equality<T>(comparer);
}
}
And then your solution becomes:
IDictionary<Person, Account> myDict = new Dictionary<Person, Account>(
Equality.Create((a, b) => a.Id == b.Id && a.Name == b.Name);
Even shorter than it would be in Java.
The closest you're going to get is anonymous types like you'd see in a LINQ expression. A short example from the link:
var v = new { Amount = 108, Message = "Hello" };
Definitely not what you're looking for. I haven't heard of future support for anonymous classes in C# either.
You could define the implementation of the interface in one place, 1 class, map the interface to your desired implementation class in your favorite IOC framework and not have to think about instantiating a 1-time-use anonymous implementation at all.
No, as of the time this question was originally written (C# 3.0), there is not.
When I want to constraint the type T to be comparable, should I use:
where T : IComparable
or
where T : IComparable<T>
I can't get my head around if #2 makes sense. Anyone can explain what the difference would be?
You may want both constraints, as in:
where T : IComparable, IComparable<T>
This would make your type compatible with more users of the IComparable interfaces. The generic version of IComparable, IComparable<T> will help to avoid boxing when T is a value type and allows for more strongly typed implementations of the interface methods. Supporting both ensures that no matter which interface some other object asks for, your object can comply and therefore inter-operate nicely.
For example, Array.Sort and ArrayList.Sort use IComparable, not IComparable<T>.
The main difference between IComparable and IComparable<> is that the first is pre-generics so allows you to call the compare method with any object, whereas the second enforces that it shares the same type:
IComparable - CompareTo(object other);
IComparable<T> - CompareTo(T other);
I would go with the second option provided that you don't intend to use any old .net 1.0 libraries where the types may not implement the modern, generic solution. You'll gain a performance boost since you'll avoid boxing and the comparisons won't need to check the types match and you'll also get the warm feeling that comes from doing things in the most cutting edge way...
To address Jeff's very good and pertinent point I would argue that it is good practice to place as few constraints on a generic as is required to perform the task. Since you are in complete control of the code inside the generic you know whether you are using any methods that require a basic IComparable type. So, taking his comment into consideration I personally would follow these rules:
If you are not expecting the generic to use any types that only implement IComparable (i.e. legacy 1.0 code) and you are not calling any methods from inside the generic that rely on an IComparable parameter then use the IComparable<> constraint only.
If you are using types that only implement IComparable then use that constraint only
If you are using methods that require an IComparable parameter, but not using types that only implement IComparable then using both constraints as in Jeff's answer will boost performance when you use methods that accept the generic type.
To expand on the third rule - let's assume that the class you are writing is as follows:
public class StrangeExample<T> where ... //to be decided
{
public void SortArray(T[] input)
{
Array.Sort(input);
}
public bool AreEqual(T a, T b)
{
return a.CompareTo(b) == 0;
}
}
And we need to decide what constraints to place on it. The SortArray method calls Array.Sort which requires the array that is passed in to contains objects that implement IComparable. Therefore we must have an IComparable constraint:
public class StrangeExample<T> where T : IComparable
Now the class will compile and work correctly as an array of T is valid for Array.Sort and there is a valid .CompareTo method defined in the interface. However, if you are sure that you will not want to use your class with a type that does not also implement the IComparable<> interface you can extend your constraint to:
public class StrangeExample<T> where T : IComparable, IComparable<T>
This means that when AreEqual is called it will use the faster, generic CompareTo method and you will see a performance benefit at the expense of not being able to use it with old, .NET 1.0 types.
On the other hand if you didn't have the AreEqual method then there is no advantage to the IComparable<> constraint so you may as well drop it - you are only using IComparable implementations anyway.
Those are two different interfaces. Before .NET 2.0 there were no generics, so there was just IComparable. With .NET 2.0 came generics and it became possible to make IComparable<T>. They do exactly the same. Basically IComparable is obsolete, although most libraries out there recognize both.
To make your code really compatible, implement both, but make one call the other, so you don't have to write the same code twice.
The IComparable<T> allows the comparator to be strongly typed.
You can have
public int CompareTo(MyType other)
{
// logic
}
as oppose to
public int CompareTo(object other)
{
if (other is MyType)
// logic
}
Take for instance the next example witch implements both interfaces:
public class MyType : IComparable<MyType>, IComparable
{
public MyType(string name, int id)
{ Name = name; Id = id; }
public string Name { get; set; }
public int Id { get; set; }
public int CompareTo(MyType other)
{
if (null == other)
throw new ArgumentNullException("other");
return (Id - other.Id > 0 ? 1 : 0);
}
public int CompareTo(object other)
{
if (null == other)
throw new ArgumentNullException("other");
if (other is MyType)
return (Id - (other as MyType).Id > 0 ? 1 : 0);
else
throw new InvalidOperationException("Bad type");
}
}
MyType t1 = new MyType("a", 1);
MyType t2 = new MyType("b", 2);
object someObj = new object();
// calls the strongly typed method: CompareTo(MyType other)
t1.CompareTo(t2);
// calls the *weakly* typed method: CompareTo(object other)
t1.CompareTo(someObj);
If MyType was only implemented with IComparable<MyType>, the second compareTo(someObj) is a compile time error. This is one advantage of strongly typed generics.
On the other hand, there are methods in the framework that require the non generic IComparable like Array.Sort. In these cases, you should consider implementing both interfaces like in this example.
I would use the second constraint as that will allow you to reference strongly-typed members of the interface. If you go with your first option then you will have to cast to use the interface type.
I'm looking for real world best practices, how other people might have implemented solutions with complex domains.
Any time you consider using an IEqualityComparer<T>, pause to think if the class could be made to implement IEquatable<T> instead. If a Product should always be compared by ID, just define it to be equated as such so you can use the default comparer.
That said, there are still a few of reasons you might want a custom comparer:
If there are multiple ways instances of a class could be considered equal. The best example of this is a string, for which the framework provides six different comparers in StringComparer.
If the class is defined in such a way that you can't define it as IEquatable<T>. This would include classes defined by others and classes generated by the compiler (specifically anonymous types, which use a property-wise comparison by default).
If you do decide you need a comparer, you can certainly use a generalized comparer (see DMenT's answer), but if you need to reuse that logic you should encapsulate it in a dedicated class. You could even declare it by inheriting from the generic base:
class ProductByIdComparer : GenericEqualityComparer<ShopByProduct>
{
public ProductByIdComparer()
: base((x, y) => x.ProductId == y.ProductId, z => z.ProductId)
{ }
}
As far as use, you should take advantage of comparers when possible. For example, rather than calling ToLower() on every string used as a dictionary key (logic for which will be strewn across your app), you should declare the dictionary to use a case-insensitive StringComparer. The same goes for the LINQ operators that accept a comparer. But again, always consider if the equatable behavior that should be intrinsic to the class rather than defined externally.
I did the following, I'm not sure if it is real-world best practice, but it worked fine for me. :)
public class GenericEqualityComparer<T> : IEqualityComparer<T>
{
private Func<T, T, Boolean> _comparer;
private Func<T, int> _hashCodeEvaluator;
public GenericEqualityComparer(Func<T, T, Boolean> comparer)
{
_comparer = comparer;
}
public GenericEqualityComparer(Func<T, T, Boolean> comparer, Func<T, int> hashCodeEvaluator)
{
_comparer = comparer;
_hashCodeEvaluator = hashCodeEvaluator;
}
#region IEqualityComparer<T> Members
public bool Equals(T x, T y)
{
return _comparer(x, y);
}
public int GetHashCode(T obj)
{
if(obj == null) {
throw new ArgumentNullException("obj");
}
if(_hashCodeEvaluator == null) {
return 0;
}
return _hashCodeEvaluator(obj);
}
#endregion
}
Then you can use it in your collections.
var comparer = new GenericEqualityComparer<ShopByProduct>((x, y) => x.ProductId == y.ProductId);
var current = SelectAll().Where(p => p.ShopByGroup == group).ToList();
var toDelete = current.Except(products, comparer);
var toAdd = products.Except(current, comparer);
If you need to support custom GetHashCode() functionality, use the alternative constructor to provide a lambda to do the alternative calculation:
var comparer = new GenericEqualityComparer<ShopByProduct>(
(x, y) => { return x.ProductId == y.ProductId; },
(x) => { return x.Product.GetHashCode()}
);
I hope this helps. =)
See this post for (better) alternatives: Wrap a delegate in an IEqualityComparer
Scroll down to the part on KeyEqualityComparer and especially the part on the importance of GetHashCode. There is a whole discussion on why obj.GetHashCode(); (as suggested by DMenT's post) is wrong and should just return 0 instead.
This is what MSDN has to say about IEqualityComparer (non-generic):
This interface allows the implementation of customized equality comparison for collections. That is, you can create your own definition of equality, and specify that this definition be used with a collection type that accepts the IEqualityComparer interface. In the .NET Framework, constructors of the Hashtable, NameValueCollection, and OrderedDictionary collection types accept this interface.
This interface supports only equality comparisons. Customization of comparisons for sorting and ordering is provided by the IComparer interface.
It looks like the generic version of this interface performs the same function but is used for Dictionary<(Of <(TKey, TValue>)>) collections.
As far as best practices around using this interface for your own purposes. I would say that the best practice would be to use it when you are deriving or implementing a class that has similar functionality to the above mentioned .NET framework collections and where you want to add the same capability to your own collections. This will ensure that you are consistent with how the .NET framework uses the interface.
In other words support the use of this interface if you are developing a custom collection and you want to allow your consumers to control equality which is used in a number of LINQ and collection related methods (eg. Sort).
I would say that the best use would be when you need to plug in different equality rules for a certain algorithm. Much in the same way that a sorting algorithm might accept an IComparer<T>, a finding algorithm might accept an IEqualityComparer<T>
The list uses this interface alot, so you can say a.Substract(b) or other of these nice functions.
Just remember: If you're objects don't return the same Hashcode, the Equals is not called.