Lets say I Have class:
public class Ident
{
public String Name { get; set; }
public String SName { get; set; }
}
and also one more:
class IdenNode
{
public Ident id { get; set; }
public List<IdenNode> Nodes { get; set; }
public IdenNode()
{
Nodes = new List<IdenNode>();
}
}
I want to use HashSet<IdenNode>
with mind that two elements of it are same(Equal) if and only if their id.Names are Equal.
So, I'm gonna override Equals
and GetHashCode
like next:
public override bool Equals(object obj)
{
IdenNode otherNode = obj as IdenNode;
return otherNode != null &&
otherNode.id != null &&
id.Name == otherNode.id.Name;
}
public override int GetHashCode()
{
if (id != null)
return id.Name.GetHashCode();
else
// what should I write here?
}
Am I think right? What should I place in GetHashCode
if so?
UPDATE
Could please tell me is it OK to use ==
and !=
in Equals
method? Or may be ReferenceEquals
or some other?
Also, should I override operators ==
and !=
?
If id
(or id.Name
) is null then it's perfectly fine to return 0. Nullable<T>
(like int?
) returns 0 for "null" values.
Keep in mind that two objects returning the same value from GetHashCode()
does NOT imply equality - it only implies that two objects might be equal. The flip, however, is that two "equal" objects must return the same hash code. Both principles seem to be fulfilled by your definition of Equals
and GetHashCode
Beware of nulls! You've got a lot of them. Take care of StackOverflow: try not use == and != within Equals
method. Usually, we return 0 as a hash code in case of null, e.g.:
public override bool Equals(object obj) {
// Often we should compare an instance with itself,
// so let's have a special case for it (optimization)
if (Object.ReferenceEquals(obj, this))
return true;
IdenNode other = obj as IdenNode;
// otherNode != null line in your code can cause StackOverflow:
// "!=" calls "Equals" which in turn calls "!=" etc...
if (Object.ReferenceEquals(null, other))
return false;
// Id can be null
if (Object.ReferenceEquals(id, other.id))
return true;
else if (Object.ReferenceEquals(id, null) || Object.ReferenceEquals(other.id, null))
return false;
// Let's be exact when comparing strings:
// i.e. should we use current locale or not etc
return String.Equals(id.Name, other.id.Name, StringComparison.Ordinal);
}
public override int GetHashCode() {
// It's typical to return 0 in case of null
if (Object.ReferenceEquals(null, id))
return 0;
else if (Object.ReferenceEquals(null, id.Name)) // <- Name can be null as well!
return 0;
return id.Name.GetHashCode();
}
What should I place in GetHashCode if so?
Returning zero is fine. Note that defining value equality on a name is a bad idea; I know of at least three other Eric Lippert
s in the United States and they're not me. There are literally millions, possibly billions, of people who have a name collision.
Could please tell me is it OK to use "==" and "!=" in Equals method? Or may be ReferenceEquals or some other?
My advice is: when mixing reference and value equality, be very clear. If you intend reference equality, say so.
Also, should I override operators "==" and "!=" ?
Yes. It is confusing to have Equals
mean one thing and ==
mean another.