C# 未调用元组作为键GetHashCode的字典
说明C# 未调用元组作为键GetHashCode的字典,c#,dictionary,.net-core,hashtable,C#,Dictionary,.net Core,Hashtable,说明 正在尝试创建以元组为键的字典 但是,不会调用GetHashCode和Equals函数,因此会将重复的键添加到字典中 这是我想用作字典键的键类: class Key : IEqualityComparer<Tuple<int, int>> { private Tuple<int, int> _tuple; public Key(int a, int b) { _tuple
正在尝试创建以元组为键的字典 但是,不会调用GetHashCode和Equals函数,因此会将重复的键添加到字典中 这是我想用作字典键的
键
类:
class Key : IEqualityComparer<Tuple<int, int>>
{
private Tuple<int, int> _tuple;
public Key(int a, int b)
{
_tuple = new Tuple<int, int>(a, b);
}
public bool Equals(Tuple<int, int> x, Tuple<int, int> y)
{
return (x.Item1 == y.Item1 && x.Item2 == y.Item2);
}
public int GetHashCode(Tuple<int, int> obj)
{
return obj.Item1.GetHashCode() ^ obj.Item2.GetHashCode();
}
}
类密钥:IEqualityComparer
{
私有元组;
公钥(INTA、INTB)
{
_tuple=新的tuple(a,b);
}
公共布尔等于(元组x,元组y)
{
返回(x.Item1==y.Item1&&x.Item2==y.Item2);
}
public int GetHashCode(元组对象)
{
返回obj.Item1.GetHashCode()^obj.Item2.GetHashCode();
}
}
驱动程序代码:
public static void Main() {
var map = new Dictionary<Key, int>();
map.Add(new Key(1, 2), 3);
map.Add(new Key(1, 2), 4); // <==== Should not add!
}
publicstaticvoidmain(){
var map=newdictionary();
地图添加(新键(1,2,3);
map.Add(新键(1,2,4);//您可以尝试以下解决方案
public class Key : IEquatable<Key>
{
private Tuple<int, int> _tuple;
public Key(int a, int b)
{
_tuple = new Tuple<int, int>(a, b);
}
public bool Equals(Key other)
{
return (this.GetHashCode() == other.GetHashCode());
}
public override int GetHashCode()
{
return _tuple.GetHashCode();
}
}
公共类密钥:IEquatable
{
私有元组;
公钥(INTA、INTB)
{
_tuple=新的tuple(a,b);
}
公共布尔等于(关键其他)
{
返回(this.GetHashCode()==other.GetHashCode());
}
公共覆盖int GetHashCode()
{
返回_tuple.GetHashCode();
}
}
您可以尝试以下解决方案
public class Key : IEquatable<Key>
{
private Tuple<int, int> _tuple;
public Key(int a, int b)
{
_tuple = new Tuple<int, int>(a, b);
}
public bool Equals(Key other)
{
return (this.GetHashCode() == other.GetHashCode());
}
public override int GetHashCode()
{
return _tuple.GetHashCode();
}
}
公共类密钥:IEquatable
{
私有元组;
公钥(INTA、INTB)
{
_tuple=新的tuple(a,b);
}
公共布尔等于(关键其他)
{
返回(this.GetHashCode()==other.GetHashCode());
}
公共覆盖int GetHashCode()
{
返回_tuple.GetHashCode();
}
}
另一种方法是使用ValueTuple
作为键,默认情况下将根据其值进行比较
public static void Main()
{
var map = new Dictionary<(int, int), int>();
map.Add((1, 2), 3);
map.Add((1, 2), 4); // Throw an exception
}
publicstaticvoidmain()
{
var map=newdictionary();
地图添加((1,2,3);
Add((1,2,4);//引发异常
}
如果您想拥有自己的类来表示一个键,您只需创建Tuple
的子类,并“免费”获得所需的行为
公共类密钥:元组
{
公钥(int item1,int item2):基(item1,item2)
{
}
}
另一种方法是使用ValueTuple
作为键,默认情况下将根据其值进行比较
public static void Main()
{
var map = new Dictionary<(int, int), int>();
map.Add((1, 2), 3);
map.Add((1, 2), 4); // Throw an exception
}
publicstaticvoidmain()
{
var map=newdictionary();
地图添加((1,2,3);
Add((1,2,4);//引发异常
}
如果您想拥有自己的类来表示一个键,您只需创建Tuple
的子类,并“免费”获得所需的行为
公共类密钥:元组
{
公钥(int item1,int item2):基(item1,item2)
{
}
}
如果要使用自己的类键
:
public class Key
{
public Key(int item1, int item2)
{
Tuple = new Tuple<int, int>(item1, item2);
}
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (obj is Key other)
{
return Tuple.Equals(other.Tuple);
}
return false;
}
public override int GetHashCode()
{
return Tuple.GetHashCode();
}
public Tuple<int, int> Tuple { get; private set; }
}
public void Do()
{
var map = new Dictionary<Key, int>();
map.Add(new Key(1, 2), 3);
map.Add(new Key(1, 2), 4); // will throw System.ArgumentException
}
如果要使用自己的类键
:
public class Key
{
public Key(int item1, int item2)
{
Tuple = new Tuple<int, int>(item1, item2);
}
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (obj is Key other)
{
return Tuple.Equals(other.Tuple);
}
return false;
}
public override int GetHashCode()
{
return Tuple.GetHashCode();
}
public Tuple<int, int> Tuple { get; private set; }
}
public void Do()
{
var map = new Dictionary<Key, int>();
map.Add(new Key(1, 2), 3);
map.Add(new Key(1, 2), 4); // will throw System.ArgumentException
}
问题是,在向字典添加项时,将调用默认的Equals
和GetHashCode
方法,它们使用引用比较来确定相等性
如果要覆盖此行为,则需要使用override
关键字,并覆盖该方法:
class Key : IEquatable<Key>
{
private readonly Tuple<int, int> tuple;
public Key(int a, int b)
{
tuple = new Tuple<int, int>(a, b);
}
public bool Equals(Key other)
{
return other != null &&
tuple.Item1 == other.tuple.Item1 &&
tuple.Item2 == other.tuple.Item2;
}
public override bool Equals(object obj)
{
return Equals(obj as Key);
}
public override int GetHashCode()
{
return tuple.Item1.GetHashCode() ^ tuple.Item2.GetHashCode();
}
}
类密钥:IEquatable
{
私有只读元组;
公钥(INTA、INTB)
{
tuple=新的tuple(a,b);
}
公共布尔等于(关键其他)
{
返回其他!=null&&
tuple.Item1==other.tuple.Item1&&
tuple.Item2==other.tuple.Item2;
}
公共覆盖布尔等于(对象对象对象)
{
返回等于(obj作为键);
}
公共覆盖int GetHashCode()
{
返回tuple.Item1.GetHashCode()^tuple.Item2.GetHashCode();
}
}
问题在于,在向字典添加项时,将调用默认的Equals
和GetHashCode
方法,它们使用引用比较来确定相等性
如果要覆盖此行为,则需要使用override
关键字,并覆盖该方法:
class Key : IEquatable<Key>
{
private readonly Tuple<int, int> tuple;
public Key(int a, int b)
{
tuple = new Tuple<int, int>(a, b);
}
public bool Equals(Key other)
{
return other != null &&
tuple.Item1 == other.tuple.Item1 &&
tuple.Item2 == other.tuple.Item2;
}
public override bool Equals(object obj)
{
return Equals(obj as Key);
}
public override int GetHashCode()
{
return tuple.Item1.GetHashCode() ^ tuple.Item2.GetHashCode();
}
}
类密钥:IEquatable
{
私有只读元组;
公钥(INTA、INTB)
{
tuple=新的tuple(a,b);
}
公共布尔等于(关键其他)
{
返回其他!=null&&
tuple.Item1==other.tuple.Item1&&
tuple.Item2==other.tuple.Item2;
}
公共覆盖布尔等于(对象对象对象)
{
返回等于(obj作为键);
}
公共覆盖int GetHashCode()
{
返回tuple.Item1.GetHashCode()^tuple.Item2.GetHashCode();
}
}
这里只发布了@Dmitri答案的简化版本作为参考
最简单的方法(无需安装额外的软件包)是不实现任何接口,只需覆盖Equals
和GetHashCode
方法,如下所示:
public class Key
{
private readonly Tuple<int, int> _tuple;
public Key(int item1, int item2)
{
_tuple = new Tuple<int, int>(item1, item2);
}
public override bool Equals(object obj)
{
var other = obj as Key;
return _tuple.Item1 == other?._tuple.Item1 && _tuple.Item2 == other?._tuple.Item2;
}
public override int GetHashCode()
{
return _tuple.Item1.GetHashCode() ^ _tuple.Item2.GetHashCode();
}
}
公共类密钥
{
私有只读元组u元组;
公钥(int项1、int项2)
{
_tuple=新的tuple(item1,item2);
}
公共覆盖布尔等于(对象对象对象)
{
var other=作为键的obj;
返回_tuple.Item1==other?_tuple.Item1&&u tuple.Item2==other?_tuple.Item2;
}
公共覆盖int GetHashCode()
{
返回_tuple.Item1.GetHashCode()^ _tuple.Item2.GetHashCode();
}
}
这里只发布了@Dmitri答案的简化版本作为参考
最简单的方法(无需安装额外的软件包)是不实现任何接口,只需覆盖Equals
和GetHashCode
方法,如下所示:
public class Key
{
private readonly Tuple<int, int> _tuple;
public Key(int item1, int item2)
{
_tuple = new Tuple<int, int>(item1, item2);
}
public override bool Equals(object obj)
{
var other = obj as Key;
return _tuple.Item1 == other?._tuple.Item1 && _tuple.Item2 == other?._tuple.Item2;
}
public override int GetHashCode()
{
return _tuple.Item1.GetHashCode() ^ _tuple.Item2.GetHashCode();
}
}
公共类密钥
{
私有只读元组u元组;
公钥(int项1、int项2)
{
_tuple=新的tuple(item1,item2);
}
公共覆盖布尔等于(对象对象对象)
{
var other=作为键的obj;
返回_tuple.Item1==other?_tuple.Item1&&u tuple.Item2==other?_tuple.Item2;
}
公共覆盖int GetHashCode()
{