【发布时间】:2021-07-23 11:16:14
【问题描述】:
我正在尝试将一些代码从 Java 移植到 C#。在 C# 中,我使用的是 Dictionary 而不是 Java HashMap。但是,我发现当我调用 Dictionary.Add() 时,我得到了重复的键。我怀疑这是因为键是不同的引用类型,但对象应该相等。我在这里创建了一个最小的示例:
抽象类:
using System;
using System.Text;
public abstract class HandState
{
public int[] _cards; // ranks only
public int _index; // into _allStates array
public char _levelIndex; // into _levelArrays[n]
private static String _cardValues = "23456789TJQKA";
private static int SUIT_COUNT = 4;
public abstract bool IsFinal();
public abstract char Value(); // the generated array value
public override String ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append("[");
for (int i = 0; i < _cards.Length; i++)
{
int card = _cards[i];
sb.Append(_cardValues[card]);
if (i != _cards.Length - 1)
sb.Append(" ");
}
sb.Append("]");
return sb.ToString();
}
public bool LegalTransistion(int card)
{
int rankCount = 0;
for (int i = 0; i < _cards.Length; i++)
{
if (_cards[i] == card)
{
rankCount++;
}
}
return rankCount != SUIT_COUNT;
}
public void Init(HandState prev, int card)
{
int prevlen = prev._cards.Length;
_cards = new int[prevlen + 1];
Array.Copy(prev._cards, 0, _cards, 0, prevlen);
_cards[prevlen] = card;
Array.Sort(_cards);
}
}
扩展类:
using System;
using System.Collections;
using System.Collections.Generic;
public class NonFinalHandState : HandState //extends
{
public HandState[] _transistions;
private static List<HandState> _allStatesVec = new List<HandState>();
private static int RANK_SIZE = 13;
public NonFinalHandState(int[] cards)
{
_cards = (int[])cards.Clone();
}
public NonFinalHandState(NonFinalHandState prev, int card)
{
Init(prev, card);
}
public NonFinalHandState()
{
_cards = new int[0];
_index = _allStatesVec.Count;
_transistions = new HandState[RANK_SIZE];
_allStatesVec.Add(this);
}
public override bool IsFinal()
{
return false;
}
public override char Value()
{
return _levelIndex;
}
public override bool Equals(Object o)
{
if (!(o.GetType() == typeof(NonFinalHandState)))
return false;
NonFinalHandState other = (NonFinalHandState)o;
return Array.Equals(_cards, other._cards);
}
public override int GetHashCode()
{
return ((IStructuralEquatable)_cards).GetHashCode(EqualityComparer<int>.Default); //JAVA: Arrays.hashCode(_cards);
}
}
程序:
using System;
using System.Collections.Generic;
namespace ConsoleAppTest
{
class Program
{
static void Main(string[] args)
{
int[] cards = { 1, 2, 3, 4 };
NonFinalHandState nfhs1 = new NonFinalHandState(cards);
NonFinalHandState nfhs2 = new NonFinalHandState(cards);
Dictionary<HandState, HandState> dictionary = new Dictionary<HandState, HandState>();
dictionary.Add(nfhs1, nfhs1);
//dictionary.Add(nfhs2, nfhs2);
if (!dictionary.ContainsKey(nfhs2))
{
dictionary.Add(nfhs2, nfhs2);
}
else
{
dictionary[nfhs2] = nfhs2;
}
Console.WriteLine(dictionary.Keys.Count);
}
}
}
输出为 2,但我需要将密钥识别为相同。我认为 Dictionary.Add() 检查键是否相等,但即便如此,我还是在添加新条目之前检查 containsKey。我怀疑我的 GetHashCode 的 C# 实现可能有问题? Java 版本显示为注释。
有什么想法吗?
【问题讨论】:
-
提示,
Array.Equals(_cards, other._cards);没有按照您的想法行事。它实际上只是Object.Equals的别名。
标签: c# dictionary gethashcode