如何在 HashCode 中包含 "joker" 值
How to include a "joker" value in HashCode
我有下面的例子class:
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 以某种方式达到相同的机制? 因为这样,如果只有 SubType 不同,字典的 TryGetValue 将始终调用 Equals 方法。重要的是新方法一定不能比原来的慢。
我在想按位运算符;或者有什么神奇的数学公式吗?
提前致谢。
这甚至不是一个定义明确的等式函数,因为它不能传递。
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;
}
}
}
}
}
我有下面的例子class:
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 以某种方式达到相同的机制? 因为这样,如果只有 SubType 不同,字典的 TryGetValue 将始终调用 Equals 方法。重要的是新方法一定不能比原来的慢。
我在想按位运算符;或者有什么神奇的数学公式吗?
提前致谢。
这甚至不是一个定义明确的等式函数,因为它不能传递。
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;
}
}
}
}
}