GetHashCode()经常替换冲突方式

时间:2018-08-14 03:04:34

标签: c# unity3d override hashcode gethashcode

我使用的是unity,而unity中没有元组,因此我创建了自己的元组类,因为我的Dictionary需要它。

Dictionary <Tuple<int,int>, Tile>

我创建的平铺课程,与解决此问题并不相关(至少我认为这无济于事)。

但是问题是我在元组中同时使用了负整数和正整数,并且当我将当前的GetHashCode()Tuples一起使用时,有时会得到相同的HashCode,例如{当我返回哈希码时,{1}}和Tuple<-10, 8>都给出-172。

是否有任何好的GetHashCode不会让我产生冲突? 老实说,我只使用运算符Tuple<-9,-10>,因为我需要检查两个元组内部是否具有相同的整数,如果我能得到只有两个整数都冲突时才冲突的运算符==相同和相同的顺序,它将解决我的问题。

其他一些小问题,我无法理解Equals覆盖,它确实可以正常工作,但是我不知道它的工作原理,因为我一直在更改每件事直到它起作用为止。

==

4 个答案:

答案 0 :(得分:4)

GetHashCode()不应无冲突。您应该使用它来确定两个事物可能是否是相同的对象,然后您必须进行彻底的检查以查看它们是否相同。

例如,您的==方法应这样写:

public static bool operator==(Tuple<T1, T2> obj1, Tuple<T1, T2> obj2)
{
    if (ReferenceEquals(null, obj2))
        return false;

    if (obj1.GetHashCode() != obj2.GetHashCode())
    {
        return false;
    }
    return DefaultComparer<T1>.Equals(obj1.First, obj2.First) && DefaultComparer<T2>.Equals(obj1.Second, obj2.Second);
}

此外,不要忘记考虑obj1obj2都是null的情况。

如果您要实现自己的Tuple,则可以考虑从Reference Source存储库中窃取Microsoft的存储,或者至少将其用作自己的基础。

答案 1 :(得分:3)

  

我使用的是unity,而unity中没有元组

如果您拥有 Unity 2017 及更高版本,它将支持Tuple。

转到编辑-> 项目设置->播放器-> 其他设置-> 配置-> 脚本运行时版本-> .NET 4.x等效

重新加载或重新启动Visual Studio,您应该可以使用Tuple。如果您不使用 Unity 2017 及更高版本,并且也不想更新,请参阅John的answer

答案 2 :(得分:3)

这是reshaper会自动为您生成的内容。只需注意它们如何执行GetHashCode()和Equals。

docker run -v

答案 3 :(得分:-2)

我发现PropertyCompare(*)在自动生成Equals实现中很有用。它将自动比较所有公共属性(因此,如果您添加新的公共属性,则无需更改除外 GetHashCode(甚至从技术上来说也是可选)。

它使用Cache来达到合理的性能-一次性点击(每种类型)以生成用于比较的适当表达式。

using System;
using System.Linq.Expressions;

namespace YourApp
{
    public class Tuple<T1, T2>
    {
        public T1 First { get; private set; }
        public T2 Second { get; private set; }

        public Tuple(T1 _First, T2 _Second)
        {
            First = _First;
            Second = _Second;
        }
        public override int GetHashCode()
        {
            var hash = 0;

            // Implement this however you like
            hash = First.GetHashCode() * 17 + Second.GetHashCode() + First.GetHashCode();

            return hash;
        }
        public static bool operator ==(Tuple<T1, T2> x, Tuple<T1, T2> y)
        {
            return PropertyCompare.Equal(x, y);
        }
        public static bool operator !=(Tuple<T1, T2> x, Tuple<T1, T2> y)
        {
            return !PropertyCompare.Equal(x, y);
        }
        public bool Equals(Tuple<T1, T2> other)
        {
            return PropertyCompare.Equal(this, other);

        }
        public override bool Equals(object obj)
        {
            return PropertyCompare.Equal(this, obj);
        }
    }
    public static class Tuple
    {
        public static Tuple<T1, T2> New<T1, T2>(T1 first, T2 second)
        {
            var tuple = new Tuple<T1, T2>(first, second);
            return tuple;
        }
    }

    public class Program
    {
        public static void Main()
        {
            var bob1 = Tuple.New("a", 1);
            var bob2 = Tuple.New("a", 1);

            Console.WriteLine(bob1 == bob2);
            Console.ReadLine();
        }
    }

    public static class PropertyCompare
    {
        public static bool Equal<T>(T x, object y) where T : class
        {
            return Cache<T>.Compare(x, y as T);
        }

        public static bool Equal<T>(T x, T y)
        {
            if (x == null)
            {
                return y == null;
            }

            if (y == null)
            {
                return false;
            }

            return Cache<T>.Compare(x, y);
        }

        private static class Cache<T>
        {
            internal static readonly Func<T, T, bool> Compare;
            static Cache()
            {
                var props = typeof(T).GetProperties();
                if (props.Length == 0)
                {
                    Compare = delegate { return true; };
                    return;
                }
                var x = Expression.Parameter(typeof(T), "x");
                var y = Expression.Parameter(typeof(T), "y");

                Expression body = null;
                for (var i = 0; i < props.Length; i++)
                {
                    var propEqual = Expression.Equal(
                        Expression.Property(x, props[i]),
                        Expression.Property(y, props[i]));
                    if (body == null)
                    {
                        body = propEqual;
                    }
                    else
                    {
                        body = Expression.AndAlso(body, propEqual);
                    }
                }
                Compare = Expression.Lambda<Func<T, T, bool>>(body, x, y)
                              .Compile();
            }
        }
    }
}

(*)我在某个地方在线找到了它,可惜我不记得在哪里,而且Google在这里令我失望。