如何在HashCode中包含“小丑”值

时间:2018-08-22 21:20:08

标签: c# .net gethashcode

我有以下示例类:

public sealed class MyDictKey
{
    public int Type { get; }
    public int SubType { get; }

    public MyDictKey(int type, int subType) // both can only be positive values
    {
        Type = type;
        SubType = subType;
    }

    public override bool Equals(object obj)
    {
        if (obj is MyDictKey other)
        {
            bool typeEqual = other.Type == Type;
            bool subTypeEqual = other.SubType == -1 || SubType == -1 || other.SubType == SubType;
            return typeEqual && subTypeEqual;
        }

        return false;
    }

    public override int GetHashCode()
    {
        unchecked
        {
            int hash = 17;
            hash = hash * 23 + Type.GetHashCode();
            return hash;
        }
    }
}

以及以下测试(如果有人,请使用NUnit)

    [Test]
    public void CalculatorTest()
    {
        Dictionary<MyDictKey, string> myTypeProcessors = new Dictionary<MyDictKey, string>();

        myTypeProcessors.Add(new MyDictKey(10, 20), "10.20_processor");
        myTypeProcessors.Add(new MyDictKey(3, 4), "3.4_processor");
        myTypeProcessors.Add(new MyDictKey(4, -1), "4.any_processor");
        // -1 means it can process "any" subtype

        for (int i = 0; i < 1000; i++) // should work for any positive number
        {
            bool canGet = myTypeProcessors.TryGetValue(new MyDictKey(4, i), out string value);
            Assert.IsTrue(canGet);
            Assert.That(value, Is.EqualTo("4.any_processor"));

            bool canGet2 = myTypeProcessors.TryGetValue(new MyDictKey(10, i), out string value2);
            if (i == 20)
            {
                Assert.IsTrue(canGet2);
                Assert.That(value2, Is.EqualTo("10.20_processor"));
            }
            else
            {
                Assert.IsFalse(canGet2);
            }
        }
    }

我是否只能通过使用GetHashCode达到相同的机制?由于这种方式,如果只有SubTypes不同,则字典的TryGetValue将始终调用Equals方法。重要的是,新方法一定不能比原始方法慢。

我在想按位运算符;还是为此有任何神奇的数学公式?

谢谢。

1 个答案:

答案 0 :(得分:4)

这甚至不是一个定义明确的等式函数,因为它无法传递。

EG A =(1,1),B =(1,-1),C =(1,2)

A = B,B = C,但不是A = C

考虑:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

    namespace ConsoleApp5
    {
        class Program
        {
            static void Main(string[] args)
            {
                var A = new MyDictKey(1, 1);
                var B = new MyDictKey(1, -1);
                var C = new MyDictKey(1, 2);

                var h = new HashSet<MyDictKey>();
                h.Add(A);
                h.Add(B);
                h.Add(C);
                Console.WriteLine(h.Count); //outputs 2


                var h2 = new HashSet<MyDictKey>();
                h2.Add(B);
                h2.Add(C);
                h2.Add(A);
                Console.WriteLine(h2.Count); //outputs 1

                Console.ReadKey();

            }

            public sealed class MyDictKey
            {
                public int Type { get; }
                public int SubType { get; }

                public MyDictKey(int type, int subType) // both can only be positive values
                {
                    Type = type;
                    SubType = subType;
                }

                public override bool Equals(object obj)
                {
                    if (obj is MyDictKey other)
                    {
                        bool typeEqual = other.Type == Type;
                        bool subTypeEqual = other.SubType == -1 || SubType == -1 || other.SubType == SubType;
                        return typeEqual && subTypeEqual;
                    }

                    return false;
                }

                public override int GetHashCode()
                {
                    unchecked
                    {
                        int hash = 17;
                        hash = hash * 23 + Type.GetHashCode();
                        return hash;
                    }
                }
            }
        }
    }