c#在重写object中的Equal方法时需要对GetHashCode进行重写(Dictionary引用)

//先看一个不负责任的写法
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;


namespace nothing
{
    class MyMethod
    {
        //用a值代替Hash值
        public int a { get; set; }
         public override int GetHashCode()
        {
            return a;
        }
        public override bool Equals(object obj)
        {
            return true;
        }

    }
    class Program
    {
            
        static void Sum<T>() where T : MyMethod, new()
        {
            T t1 = new T();
            T t2 = new T();
             
            t1.a = 3; t2.a = 4;//不会报错           
             //t1.a=3;t2.a=3;报错,字典中已经存在相同键
             Dictionary<MyMethod, int> d = new Dictionary<MyMethod, int>();
            d.Add(t1, 1);
            d.Add(t2, 2);
            
            
        }
        static void Main(string[] args)
        {
            
            Sum<MyMethod>();
            Console.Read();

        }
       
    }
 
}
 

再说Dictionary的Add的具体实现:

ILSpy反编译中C#Dictionary的Add方法源码:


public void Add(TKey key, TValue value)
{
    this.Insert(key, value, true);
}


private void Insert(TKey key, TValue value, bool add)
{
    if (key == null)
    {
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
    }
    if (this.buckets == null)
    {
        this.Initialize(0);
    }
    
    int num = this.comparer.GetHashCode(key) & 2147483647;
    int num2 = num % this.buckets.Length;
    int num3 = 0;
    for (int i = this.buckets[num2]; i >= 0; i = this.entries[i].next)
    {
        //如果hash值和字典中某个值的hash值相等 且 两个值的Equals返回值为True Trow 异常:已添加了具有相同键的项。
        if (this.entries[i].hashCode == num && this.comparer.Equals(this.entries[i].key, key))
        {
            if (add)
            {
                ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate);
            }
            this.entries[i].value = value;
            this.version++;
            return;
        }
        num3++;
    }
    int num4;
    if (this.freeCount > 0)
    {
        num4 = this.freeList;
        this.freeList = this.entries[num4].next;
        this.freeCount--;
    }
    else
    {
        if (this.count == this.entries.Length)
        {
            this.Resize();
            num2 = num % this.buckets.Length;
        }
        num4 = this.count;
        this.count++;
    }
    this.entries[num4].hashCode = num;
    this.entries[num4].next = this.buckets[num2];
    this.entries[num4].key = key;
    this.entries[num4].value = value;
    this.buckets[num2] = num4;
    this.version++;
    if (num3 > 100 && HashHelpers.IsWellKnownEqualityComparer(this.comparer))
    {
        this.comparer = (IEqualityComparer<TKey>)HashHelpers.GetRandomizedEqualityComparer(this.comparer);
        this.Resize(this.entries.Length, true);
    }
}

当每次调用Dictionary的Add方法时,参数都将与Dictionary中的值进行Equals,大家都知道DIctionary是用Hash值进行存储的,而hash值的计算方法是通过Object.GetHashCode实现的,如果这2个方法不一致,那么很容易就出现问题,特别是Dictionary中的Add方法这种情况。

个人理解Dictionary的Add方法的实现:

Add()->GetHashCode(),Equals()->判断2个hashcode是否相等 和Equals返回值是否为True->若同时成立,抛异常。


以上纯属个人观点,如有不当,欢迎讨论。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值