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.
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 have followed the suggestions from this post to try and get Distinct() working in my code but I am still having issues. Here are the two objects I am working with:
public class InvoiceItem : IEqualityComparer<InvoiceItem>
{
public InvoiceItem(string userName, string invoiceNumber, string invoiceAmount)
{
this.UserName = userName;
this.InvoiceNumber= invoiceNumber;
this.InvoiceAmount= invoiceAmount;
}
public string UserName { get; set; }
public string InvoiceNumber { get; set; }
public double InvoiceAmount { get; set; }
public bool Equals(InvoiceItem left, InvoiceItem right)
{
if ((object)left.InvoiceNumber == null && (object)right.InvoiceNumber == null) { return true; }
if ((object)left.InvoiceNumber == null || (object)right.InvoiceNumber == null) { return false; }
return left.InvoiceNumber == right.InvoiceNumber;
}
public int GetHashCode(InvoiceItem item)
{
return item.InvoiceNumber == null ? 0 : item.InvoiceNumber.GetHashCode();
}
}
public class InvoiceItems : List<InvoiceItem>{ }
My goal is to populate an InvoiceItems object (we will call it aBunchOfInvoiceItems) with a couple thousand InvoiceItem objects and then do:
InvoiceItems distinctItems = aBunchOfInvoiceItems.Distinct();
When I set this code up and run it, I get an error that says
Cannot implicitly convert type 'System.Collections.Generic.IEnumerable' to 'InvoiceReader.Form1.InvoiceItems'. An explicit conversion exists (are you missing a cast?)
I don't understand how to fix this. Should I be taking a different approach? Any suggestions are greatly appreciated.
Distinct returns a generic IEnumerable<T>. It does not return an InvoiceItems instance. In fact, behind the curtains it returns a proxy object that implements an iterator that is only accessed on demand (i.e. as you iterate over it).
You can explicitly coerce it into a List<> by calling .ToList(). You still need to convert it to your custom list type, though. The easiest way is probably to have an appropriate constructor, and calling that:
public class InvoiceItems : List<InvoiceItem> {
public InvoiceItems() { }
// Copy constructor
public InvoiceItems(IEnumerable<InvoiceItems> other) : base(other) { }
}
// …
InvoiceItems distinctItems = new InvoiceItems(aBunchOfInvoiceItems.Distinct());
Konrad Rudolph's answer should tackle your compilation problems. There is one another important semantic correctness issue here that has been missed: none of your equality-logic is actually going to be used.
When a comparer is not provided to Distinct, it uses EqualityComparer<T>.Default. This is going to try to use the IEquatable<T> interface, and if this is missing, falls back on the plain old Equals(object other) method declared on object. For hashing, it will use the GetHashCode() method, also declared on object. Since the interface hasn't been implemented by your type, and none of the aforementioned methods have been overriden, there's a big problem: Distinct will just fall back on reference-equality, which is not what you want.
Tthe IEqualityComparer<T> interface is typically used when one wants to write an equality-comparer that is decoupled from the type itself. On the other hand, when a type wants to be able to compare an instance of itself with another; it typically implements IEquatable<T>. I suggest one of:
Get InvoiceItem to implement IEquatable<InvoiceItem> instead.
Move the comparison logic to a separate InvoiceItemComparer : IEqualityComparer<InvoiceItem> type, and then call invoiceItems.Distinct(new InvoiceItemComparer());
If you want a quick hack with your existing code, you can do invoiceItems.Distinct(new InvoiceItem());
Quite simply, aBunchOfInvoiceItems.Distinct() returns an IEnumerable<InvoiceItem> and you are trying to assign that to something that is not an IEnumerable<InvoiceItem>.
However, the base class of InvoiceItems has a constructor that takes such an object, so you can use this:
public class InvoiceItems : List<InvoiceItem>
{
public InvoiceItems(IEnumerable<InvoiceItem> items)
base(items){}
}
Then you can use:
InvoiceItems distinctItems = new InvoiceItems(aBunchOfInvoiceItems.Distinct());
As is though, I don't see much benefit in deriving from List<InvoiceItem> so I would probably lean more toward:
List<InvoiceItem> distinctItems = aBunchOfInvoiceItems.Distinct().ToList();
The error has everything to do with your class InvoiceItems, which inherits from List<InvoiceItem>.
Distinct returns an IEnumerable<InvoiceItem>: InvoiceItems is a very specific type of IEnumerable<InvoiceItem>, but any IEnumerable<InvoiceItem> is not necessarily an InvoiceItems.
One solution could be to use an implicit conversion operator, if that's what you wanted to do: Doh, totally forgot you can't convert to/from interfaces (thanks Saed)
public class InvoiceItems : List<InvoiceItem>
{
public InvoiceItems(IEnumerable<InvoiceItem> items) : base(items) { }
}
Other things to note:
Inheriting from List<T> is usually bad. Implement IList<T> instead.
Using a list throws away one of the big benefits of LINQ, which is lazy evaluation. Be sure that prefetching the results is actually what you want to do.
Aside from the custom class vs IEnumerable issue that the other answers deal with, there is one major problem with your code. Your class implements IEqualityComparer instead of IEquatable. When you use Distinct, the items being filtered must either implement IEquatable themselves, or you must use the overload that takes an IEqualityComparer parameter. As it stands now, your call to Distinct will not filter the items according to the IEqualityComparer Equals and GetHashCode methods you provided.
IEqualityComparer should be implemented by another class than the one being compared. If a class knows how to compare itself, like your InvoiceItem class, it should implement IEquatable.
Is there a way to use a collection of a generic class, without supplying the underlying type ?
Let's explain :
Here is what I'd like to have :
class TimeSerie<TValue> {
enter code here
}
List<TimeSerie<?>> blah;
Here is what I have to do so far :
class TimeSerie {}
class TypedTimeSerie<TValue> : TimeSerie {}
List<TimeSerie> blah;
So, any way to use the nice first solution ? (although I guess it would raise problems when trying to cast, for a loop for example ...)
You can make your using code generic too... but at some point you do have to specify the type argument. You're not going to be able to create an instance of the generic type without the type argument being known. You can provide that information at execution time using reflection if you must, but it has to be there somehow.
I dont see based on your question why you cannot derive your custom collection from ICollection<T> or List<T> (or maybe derive from ICollection and delegate the calls to a field of type List<T> you store internally?
(It's entirely possible I'm just not getting it, but can you give a small bit more sample code?)
Why not ?
List<TimeSerie<Object>> blah;
Then after you specify your object. Also define your base class accordingly.
Note that some 'mumbling' is possible in relation to anonymous types with c# thanks to two things:
Type inference
unification of identical anonymous types
If you are happy to rely on these two things remaining fixed (there are no guarantees on this, especially in relation to 2) then the following may be useful.
public static class Mumble
{
public static HashSet<T> HashSet<T>(T prototype)
{
return new HashSet<T>();
}
public static List<T> List<T>(T prototype)
{
return new List<T>();
}
}
You can use it like so:
var set = MumbleSet(new { Foo="", Bar="", Baz=0 });
var list = MumbleList(new { Foo="", Bar="", Baz=0 });
set.Add(new { Foo="x", Bar="y", Baz=1 });
set.Add(new { Foo="a", Bar="b", Baz=1 });
list.Add(new { Foo="a", Bar="b", Baz=1 });
var intersection = list.Intersect(set);
var concat = list.Concat(set);
This works well in cases where you have anonymous types you wish to populate into some other collection for use elsewhere within a method. A common use would be reading from a database query into a set for latter checking for existence within a loop where expressing this as a series of linq queries was either too cumbersome or too expensive.
For your motivating example you would have to add the following:
class TimeSerie<TValue>
{
// or some other constructor equivalent
public TimeSerie(TValue value) { /* assign the value */ }
}
static class TimeSerieMumble
{
public static TimeSerie<TValue> New<TValue>(TValue value)
{
return new TimeSerie<TValue>(value);
}
}
Then you could use the code like so:
var tsList = Mumble.List(TimeSerieMumble.New(new { Name="", Value=0 }));
foreach (var x in from c select new { c.Name, c.Value })
{
tsList.Add(TimeSerieMumble.New(new { x.Name, x.Value }));
}
Mumbling which 'leaks' into the public api is not feasible in c# 3.5 unless the type is to be mumbled through a series of type inferred generic methods in the same way as the above example. I have never seen a case where such a thing was useful given the resulting contortions required to the calling code. I would not think it would improve readability either. As a rule of thumb using more than the two levels of mumbling in the Name/Value example is likely to lead to serious complications down the line.
As others have said, there's no easy way to do this in C#.
However, if it's really important, it is possible to faithfully encode this pattern using a few extra types, although it's a bit ugly:
interface ITimeSeriesUser<X> {
X Use<T>(TimeSeries<T> series);
}
interface ITimeSeriesUser {
void Use<T>(TimeSeries<T> series);
}
interface ITimeSeries {
X Apply<X>(ITimeSeriesUser<X> user);
void Apply(ITimeSeriesUser user);
}
class TimeSeries<T> : ITimeSeries {
X Apply<X>(ITimeSeriesUser<X> user) { return user.Use(this); }
void Apply(ITimeSeriesUser user) { return user.Use(this); }
/* Your existing code goes here */
}
Now you can create a List<ITimeSeries> instance which holds TimeSeries<T>
values regardless of their type arguments, and you can use ITimeSeriesUser
implementations to manipulate them. Obviously this requires quite a bit of boilerplate,
but if you need a faithful way to express the concept of a TimeSeries<?> then this may be your best bet.
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.
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.