【问题标题】:GetHashCode() method returning value instead of addressGetHashCode() 方法返回值而不是地址
【发布时间】:2018-07-02 06:00:15
【问题描述】:
class FirstClass { }
class SecondClass { }
class Program
{
    private static void Main(string[] args)
    {
       var firstClass1  = new FirstClass();
       var firstClass2  = firstClass1;
       var secondClass1 = new SecondClass();;
       var secondClass2 = secondClass1;

       object null1 = null;
       object null2 = null;

       int a = 10, b = 10, c = 20;

       Console.WriteLine("firstClass1 == firstClass2:\t"   + SameReference(firstClass1, firstClass2));
       Console.WriteLine("secondClass1 == secondClass2:\t" + SameReference(secondClass1, secondClass2));
       Console.WriteLine("firstClass1 == secondClass1:\t"  + SameReference(firstClass1, secondClass1));
       //Console.WriteLine("null1 == null2:\t" + SameReference(null1, null2));
       Console.WriteLine("null1==firstClass1:\t" + SameReference(null1, firstClass1));
       Console.WriteLine("a == b:\t" + SameReference(a, b));
       Console.ReadKey();             
    }
    public static bool SameReference(object object1,object object2)
    {
        if ((object1 == null && object2 != null) || (object1 != null && object2 == null))
            return false;
        if ((object1 == null && object2 == null) || (object1.GetHashCode() == object2.GetHashCode()))
        {
            Console.WriteLine(object1.GetHashCode() + "\t" + object2.GetHashCode());
            return true;
        }
        return false;
    }
}

在上面的代码中,GetHashCode() 方法为 a 和 b 返回 10 和 10,但我想比较地址。这就是 GetHashCode() 方法的工作原理。请解释一下。

【问题讨论】:

  • 我正在尝试实现 ReferenceEquals(object A,object B) 方法,它应该为值类型返回 false,因为值类型被装箱并且它们存储在不同的地址。
  • 您能告诉我们为什么您希望两个相同的值类型具有不同的哈希码吗?
  • 另外,请解释为什么要在 ReferenceEquals 已经存在时重新实现它。虽然实现很简单:object1 == object2.
  • 这对你有帮助吗??

标签: c#


【解决方案1】:

请参阅the docs(强调我的):

GetHashCode 方法可以被派生类型覆盖。如果 GetHashCode 未被覆盖,引用类型的哈希码通过调用基类的 Object.GetHashCode 方法计算,该方法根据对象的引用计算哈希码;有关详细信息,请参阅 RuntimeHelpers.GetHashCode。换句话说,ReferenceEquals 方法返回 true 的两个对象具有相同的哈希码。 如果值类型不覆盖 GetHashCode,则基类的 ValueType.GetHashCode 方法使用反射来根据类型字段的值计算哈希码。换句话说,其字段具有相同值的值类型具有相同的哈希码。有关覆盖 GetHashCode 的更多信息,请参阅“继承者注意事项”部分。

根据this answerGetHashCode()int 旨在返回int 的值。如果您将the C# source code 视为Int32,也可以看到这一点:

// The absolute value of the int contained.
public override int GetHashCode() {
    return m_value;
}

【讨论】:

    【解决方案2】:

    GetHashCode() 正在按预期工作。根据MSDN

    哈希码是一个数值,用于在基于哈希的集合(例如 Dictionary 类、Hashtable 类或从 DictionaryBase 类派生的类型)中插入和标识对象。 GetHashCode 方法为需要快速检查对象相等性的算法提供此哈希码。

    GetHashCode() 而言,int a=10,b=10 的哈希码始终相同,因为 - 因为 int 是原始类型 - ab 彼此相等.

    【讨论】:

    • 字典会变得很有趣:)
    【解决方案3】:

    如果你想检查引用相等性(当你有来自同一类的对象而不是来自两个不同类的对象时很有帮助)那么你应该使用

    .ReferenceEquals() 测试两个对象是否是同一个实例并且不能被覆盖。

    因为 GethashCode :-

    Two objects that are equal return hash codes that are equal. 
    However, the reverse is not true:
    

    为此,您应该在您的类中重写 GetHashcode,如下所示,并根据属性计算哈希码,然后尝试通过重写 Equal 方法找到相等或不相等。

    public class FirstClass 
    {
        public int Id {get;set;}
        public override bool Equals(Object obj)
        {
           if (!(obj is FirstClass)) return false;
    
           FirstClass f = (FirstClass) obj;
           return thid.Id == f.id;
        }
    
        public override int GetHashCode()
        { 
            return this.Id;
        } 
    }
    

    仅从您的代码中,您就有两个不同类的对象,因为它们属于两个不同的类,它们不会相等。请参阅 C# 文档以获取 GetHashCode and Equal.

    所以这行代码是无效的:

    Console.WriteLine("firstClass1==secondClass1:\t"+SameReference(firstClass1,secondClass1));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-03
      相关资源
      最近更新 更多