C# using two different equality comparers - c#

I need to write a second equality comparer for a business object. It is a specialized equality comparer which is only applicable in certain situations. I do not want to override the Equal() because our persistent layer uses that to compare objects internally for its own uses.
Let me give you an example of a class:
public class Product : BusinessObjectBase
{
string Name {get;set;}
string Desc {get;set;}
double Price {get;set;}
}
Since we mark the three properties as persistent data properties in our data access layer, the Equals() in the BusinessObjectBase compares those properties. Now, in a specific instance I would like to check if product A it equal to product B only be Name. I do not want to hardcode the actual property on the check because this property might change later.
While IComparer could be used here, but based on the description on MSDN, IComparer should be used not to equate items but to sort them, so that does not seem like a 100% correct answer.
I would like to use something .NET already has and not create another interface.
What is the best way to do this?
Thanks

You're looking for IEqualityComparer<T>.

Related

C# override Dictionary ContainsKey

I just can't find any proper piece of code to do what i need.
Im using Dict.ContainsKey but due to the fact im always creating the Key i need to look for, i always get false for the ContainsKey (because hashKey is different and im creating the key i want to check all the time).
can someone please advise how to override Contains key or how to handle keys comparing in this situation ?
My dictionary Looks like
Dictionary<someObj, int>
public class someObj
{
public int someobjParam {get;set;}
public int someobjParamTwo {get;set;}
}
You don't need to override ContainsKey - you need to either override Equals and GetHashCode in someObj (which should be renamed to conform to .NET naming conventions, btw) or you need to pass an IEqualityComparer<someObj> to the Dictionary<,> constructor. Either way, that code is used to compare keys (and obtain hash codes from them).
Basically you need to make Equals determine equality, and make GetHashCode return the same code for equal objects and ideally different codes for different objects - see Eric Lippert's article on GetHashCode for more details.
Also, you should consider making someObj immutable: mutable dictionary keys are generally a bad idea, as if you modify the key in a hashcode-sensitive way after using it as a key within the dictionary, you won't be able to find it again. If the point of your custom type really is to be a key, then just make it immutable.
For simplicity, you should also consider making someObj implement IEquatable<someObj>, and also think about whether it would be appropriate to be a struct instead of a class. If you implement IEquatable<someObj> you should also override object.Equals in a consistent way. Usually the object.Equals implementation will just call the most strongly-typed IEquatable<T>.Equals implementation.
You don't need to override ContainsKey, but rather instruct the dictionary when it should consider that two keys are equal.
One way to do that is by implementing IEquatable<someObj> in your key class. Do this if the concept of equality is global across your app:
public class someObj : IEquatable<someObj>
{
public int someobjParam {get;set;}
public int someobjParamTwo {get;set;}
// override GetHashCode() and Equals(); for an example
// see http://msdn.microsoft.com/en-us/library/ms131190%28v=vs.110%29.aspx
}
Another one is by implementing an IEqualityComparer<someObj> and passing it to the dictionary's constructor.

When to use a GUID for a class

I'm working on a simple application with a few classes. This all started when I wanted to use the Remove method on a List<Car>. This method requires that you override the Equals and the GetHashCode methods for the Car type. In this situation, I decided to implement an ID property on the Car class. That way, my Equals method simply checks for ID equality, and my GetHashCode method returns base.GetHashCode().
Is this a good approach, or is implementing a GUID for a small class too heavy-handed? There wouldn't be any need for it without the reasons I explained above. The only requirement for uniqueness for this Car type is that it be unique within the List<T> collection to which it belongs. But adding the GUID property seemed like the quickest way around the GetHashCode mess. BTW, there are no int properties on my Car type.
There wouldn't be any need for it without the reasons I explained above.
If your class doesn't logically have an ID, then it certainly seems odd to include it just for the sake of equality.
For example, if you have two instances which have equal properties for everything apart from ID, are they really non-equal? If they are, you should potentially just use the default implementation of Equals/GetHashCode which uses reference identity for equality. Where you would use two objects with the same ID, you just use two references to the same object instead.
It really all depends on the context, and you haven't given much of that - but adding an ID just for equality is a bit of a design smell.
Instead of implementing Equals and GetHashCode just use RemoveAll:
myList.RemoveAll(x => x.ID == myCar.ID);
This allows you to specify a predicate that indicates what items should be removed instead (it doesn't matter that you are only removing one item).
Implementing Equals and GetHashCode in the way you describe strikes me as extremely dodgey - if your Equals implementation returns true then your GetHashCode method needs to return the same value so that those two objects will be placed in the same bucket in a hashtable. Your implementation (as I understand it) doesn't match this criteria as the base GetHashCode implementation is almost certainly going to return different values for two Car instances, regardless of if they have the same ID or not.
Implementing Equals and GetHashCode isn't entirely trivial and is probably something I'd generally avoid doing if there are alternatives. If you really want to do this then take a look at these resoruces:
What is the best algorithm for an overridden System.Object.GetHashCode?
Default implementation for Object.GetHashCode().
implementing the Equals method
Also hash codes are not GUIDs

What would be the easiest way to provide a way to configure a tree of objects to the user?

So I have an object tree that looks similar to this:
AbstractA
string PropA
int PropB
AbstractC PropC
AbstractD PropD
AbstractB
string PropA
string PropB
AbstractC : AbstractB
string PropC
AbstractD : AbstractB
int PropC
ConcreteA1 : AbstractA
int PropE
ConcreteC1 : AbstractC
bool PropD
ConcreteC2 : AbscractC
decimal PropD
ConcreteD1 : AbstractD
string PropD
ConcreteD2 : AbstractD
long PropD
The issue I'm having is finding a comprehensive way to provide the user with the ability to configure the object tree. There are multiple concrete classes that extend my abstracts and I would like to refrain from building a user control for every concrete type. To throw an additional constraint in the mix, the class definition is coming from my WCF proxy class. I'd like to avoid rolling my own proxy/model definitions if at all possible, but if the only way to accomplish my goal is to do so then so be it.
I originally tried to use PropertyGrid but my knowledge of it is pretty weak and I wasn't having much luck googling any good examples last night.
it sounds like you are using .net on both sides of the interaction and have control of both sides. if this is the case, instead of generating proxy classes, you could put the contracts into a common assembly referenced by both the service and the client and use the contract classes and interfaces directly instead of using generated proxies and thereby have complete control over the classes being used and have the ability to use whatever attributes you desire.
To avoid building a control for each type, you need to use reflection on each object's properties and convert the data to and from easy to manipulate strings. A grid control with two columns, the left side for property names and the right for their values (as strings). When an edit takes place, converts the value to the right type. Every base type has an inherit converter that is relatively easy to access.
Your grid/listview needs to be a list of properties, and these properties need to map to your class instance. The list of objects will represent each property of the item(your concrete object). The list of objects will need to remember a few things, the item, the property info of the property and the value, plus whatever else you want the grid to do based on the property information.
Using Reflection and TypeConverter's you can get at each property and edit their values and therefore create one control(the grid/listview of properties for a class instance) to edit any of your classes.

Dictonary.ContainsKey Comparison

I am trying to do something along the lines of the following:
class Test
{
public string Name { get; set;}
public string Location { get; set;}
public Test(string name, string location)
{
Name = name;
Location = location;
}
}
Now, in a method in another class, I am trying to add these Test classes into a Dictionary with a KeyValuePair of
Dictionary<Test,int> resources = new Dictionary<Test,int>();
resources.Add(new Test("First Resource", "Home"), 1);
Now, what I am trying to do, and need to be able to do is:
bool contains = resources.ContainsKey(new Test("First Resource", "Home"));
resources[new Test("First Resource", "Home")] = 2;
As of now, this returns false. How can I get this to return true?
I have tried overriding the Equals function of my Test class and even implementing IComparible and doing custom comparisons.
You need to override GetHashCode in your Test class, add the following to your class:
public override int GetHashCode()
{
return (Name+Location).GetHashCode();
}
This will ensure that any two Test instances have the same hash only if the concatenation of Name and Location are the same. You could use other strategies for this, however, this is the simplest form.
You need to implement GetHashCode and Equals in the key class or provide an IEqualityComparer<Test> implementation in the constructor of the dictionary.
In the case of the comparer, you would define proper GetHashCode and Equals methods inside the comparer for Test, with the benefit that these implementations are not universal for all Test objects, but can be used at will when necessary (such as for use in dictionaries, hashsets, various Linq queries, etc.) By decoupling the equality and hashcode functions from the class, you are then free to use different implementations of the comparer as the need arises.
(For a good set of guidelines on GetHashCode, please visit this blog.)
Dictionary uses GetHashCode of the key to determine in which data bucket to store an object, and then Equals to make sure that the objects are actually equal. In other words, for this to work, you will need to implement GetHashCode() and Equals for your type.
It is considered good practice to make objects used for keys in a dictionary immutable. If the object changes, its hashcode changes, and you might not be able to find it in the dictionary.

What is the correct implementation of a "composite" variable type?

I have a program that have to manage objects with a composite key.
this key, to be simple is a couple of strings.
I have the following code :
public struct MyKey
{
public string Part1 { get; set;} // always set
public string Part2 { get; set;} // can be null
public MyKey(string part1, string part2) : this()
{
this.Part1 = part1;
this.Part2 = part2;
}
}
this is ok for storing my values.
Now I want to be able to :
use the equals operator (part1 and part2 are equals)
use the key in a Dictionnary, especially for using Contains method
I've guessing a number of things (override equals operator, overriding GetHashCode and Equals methods, implementing IComparable, etc.), but I'm not sure what are the necessary steps to reach my goals and what will cause an overhead.
thx in advance
Use .NET 4.0 Tuple, it has a correct Equals() and GetHashCode() based on the component values. I've used Tuple before or if they are string keys you can always concat with a separator, but if you truly want to keep that class as your key you do want a proper Equals() and GetHashCode(), so in that case have YourType implement IEqualityComparer<YourType>.
p.s. Here's a good example of overriding the GetHashCode() if you want to do that manually instead of a Tuple...
What is the best algorithm for an overridden System.Object.GetHashCode?
You need to override Equals and GetHashCode in order to use your object as a key in a dictionary. This answer provides an excellent explanation.
First of all, I would stay away from struct because of boxing and various coding pitfalls it can fall us into.
I would override both GetHashCode and Equals. GetHashCode since it is used in dictionaries and Equals since it is used by various ORMs and can be handy in implementing business logic.

Categories

Resources