日期:2014-05-20  浏览次数:20763 次

再论hashcode,一个意想不到的结果!
class版
C# code
using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication9
{
    public class B//class版本
    {
        public int i;
    }

    class Program
    {
        static void Main(string[] args)
        {
            List<int> list = new List<int>();
            List<B> listClass = new List<B>();
            for (int i = 0; i < 10000; i++)
            {
                B b = new B();
                b.i = i;
                list.Add(b.GetHashCode());
                listClass.Add(b);
            }
            Console.WriteLine(list.Distinct().Count());//9999
            Console.ReadKey();
        }
    }
}



struct版
C# code
using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication9
{
    public struct B//struct版本
    {
        public int i;
    }

    class Program
    {
        static void Main(string[] args)
        {
            List<int> list = new List<int>();
            List<B> listClass = new List<B>();
            for (int i = 0; i < 10000; i++)
            {
                B b = new B();
                b.i = i;
                list.Add(b.GetHashCode());
                listClass.Add(b);
            }
            Console.WriteLine(list.Distinct().Count());//10000
            Console.ReadKey();
        }
    }
}



只改了一个地方class/struct

------解决方案--------------------
1.GetHashCode() 是把对应的值,通过散列算法,变换成固定长度的输出,该输出就是散列值.
不同的输入可能会散列成相同的输出.

2.class和struct:class是引用类型,而struct是值类型
struct实例分配在线程的堆栈(stack)上,它本身存储了值,而不包含指向该值的指针
new一个class的实例时,对象保存了该实例实际数据的引用地址,而对象的值保存在托管堆(managed heap)中

你例子中应该是class,0-9999 数据的引用地址在hash的时候 出现了两个相同的散列值.
在list.Distinct()的时候去重了..
而struct中实例子存的就是值, hash的时候没有出现相同的散列值. 
在list.Distinct()没能去重..






------解决方案--------------------
引用类型和值类型在有些地方是有区别的。
------解决方案--------------------
NET Framework 不保证 GetHashCode 方法的默认实现以及它所返回的值在不同版本的 .NET Framework 中是相同的
根据键对象的GetHashTable得到HashCode,如果在存储桶中该地址没有被占用,则将其存入其中

------解决方案--------------------
实际上,地址空间大于int的取值范围,所以GetHashCode()的计算结果是会有重复的——尽管散列的目的就是尽量不重复。

千万不要因此就说两个对象的HashCode就相同哦!那可是一个很简单的误会。