Pregunta

I need to know the ways to compare many objects using hashcode. So here is one of the class.

public class Test: IEquatable<Test>
{
    public Test()
    {
    }

    public string ID { get; set; }
    public string Name{ get; set; }

    public static int SafeGetHashCode<T>(this T value) where T : class
    {
        return value == null ? 0 : value.GetHashCode();
    }

    public override int GetHashCode()
    {
        int hash = 19;
        hash = hash * 31 + ID.SafeGetHashCode();
        hash = hash * 31 + Name.SafeGetHashCode();
        return hash;
    }

    public override bool isSame(object obj)
    {
         // compare objects here
    }
}

But there are 2 errors. Both are same.

'string' does not contain a definition for 'SafeGetHashCode' and no extension method 'SafeGetHashCode' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)

And for isSame(), I do not know how to write the code. the concept is compare all the objects and if there are 2 same ID & Name, group them together.

Item A = new Item();
Item B = new Item();
Item c = new Item();

A.ID = "Exam1";
A.Name = "Apple";

B.ID = "Exam1";
B.Name = "Orange";

C.ID = "Exam1";
C.Name = "Apple";

So Item A and C will group together.

¿Fue útil?

Solución

Extension method must be member of static class, which should take care of first error. Move SafeGetHashCode out of your Test class so you can use it as extension on String and other reference types:

public static class TestHashCodeExtension
{
    public static int SafeGetHashCode<T>(this T value) where T : class
    {
        return value == null ? 0 : value.GetHashCode();
    }
}

As for implementation of IEquatable<T>.Equals (I assume your isSame is just incorrectly named method, also strangely marked with override - there is no isSame in any of .Net classes, especially not in Object):

  • make sure to implement base Equals as well IEquatable<T>.Equals
  • see sample in IEquatable.Equals for implementation of both Equals calls

Shortened sample:

public bool Equals(Test other) 
{
  return (other == null) ?
     false : (Id == other.Id) && (Name == other.Name);
}

public override bool Equals(Object obj)
{
  Test testObj = obj as Test;
  return testObj == null ? false : Equals(testObj);   
}

Note: normally Equals does not need to use GetHashCode first. Dictionary (the main reason GetHashCode exists) always checks hash code itself before calling Equals. In most cases both GetHashCode and Equals are implemented as per-member hash/comparisons. So unless you know for sure that your class caches result of GetHashCode there is no practical reason to check hash-code in Equals as you'll end up touching each twice (and Equals can short-circuit comparison if first fields are not equal unlike GetHashCode that need to use all/most fields to compute result).

Otros consejos

Personally I'd just inline it - no need for the extra method:

public override int GetHashCode()
{
    int hash = 19;
    hash = hash * 31 + (ID == null ? 0 : ID.GetHashCode());
    hash = hash * 31 + (Name == null ? 0 : Name.GetHashCode());
    return hash;
}

Adding unconstrained extension methods pollutes things like intellisense.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top