C# 理解行为与行为;重写GetHashCode()
我试图遵循MSDN中的,也提到了,但下面的行为似乎不符合预期 我试图表示一个类似于FQN的结构,其中好像P1在P2之前列出,P2将只存在于与P1相同的集合中。比如范围是如何工作的C# 理解行为与行为;重写GetHashCode(),c#,dictionary,C#,Dictionary,我试图遵循MSDN中的,也提到了,但下面的行为似乎不符合预期 我试图表示一个类似于FQN的结构,其中好像P1在P2之前列出,P2将只存在于与P1相同的集合中。比如范围是如何工作的 关于GetHashCode()的主题 我有一个类具有这样的属性 class data{ public readonly string p1, p2; public data(string p1, string p2) { this.p1 = p1; this.p2 = p2;
关于GetHashCode()的主题 我有一个类具有这样的属性
class data{
public readonly string p1, p2;
public data(string p1, string p2) {
this.p1 = p1;
this.p2 = p2;
}
public override int GetHashCode()
{
return this.p1.GetHashCode() ^ this.p2.GetHashCode();
}
/*also show the equal for comparison*/
public override bool Equals(System.Object obj)
{
if (obj == null)
return false;
data d = obj as data;
if ((System.Object)d == null)
return false;
/*I thought this would be smart*/
return d.ToString() == this.ToString();
}
public override string ToString() {
return "[" + p1 +"][" + p2+ "]";
}
}
在字典
(dict)中,我使用数据
作为键,因此这将使作用域看起来像d1.p1.p2
(或者更确切地说是d1中p1的p2,但您更愿意想象它)
结果是两个元素都4
关于词典的主题 在监视窗口(VS2013)中,我让字典的键列表显示给我,而不是像我通常期望的那样,每个索引都有一个键,我的数据对象的每个属性都是单个索引的键。因此,我不确定问题是否存在,或者我只是误解了Watch窗口将对象表示为键。我知道VS显示对象的方式是这样的,但我不确定字典中键的显示方式是这样的
1132917379 string: [ABC][ABC]
-565659420 string: [ABC][123]
-1936108909 string: [123][123]
//second loop with next set of strings
1132917379 string: [xxx][xxx]
-565659420 string: [xxx][yyy]
//...etc
GetHashCode
返回0,它将是“正确的”。那肯定不好
也就是说,您的特定实现并没有它可能的那么好。例如,在您的类中,字符串的顺序很重要。即新数据(“A”、“B”)!=新数据(“B”、“A”)
。但是,由于GetHashCode
实现是对称的,所以这些哈希值总是相等的。最好以某种方式打破对称。例如:
public int GetHashCode()
{
return p1.GetHashCode() ^ ( 13 * p2.GetHashCode() );
}
现在,两个不相等的实例发生碰撞的可能性降低了
对象的转换也是冗余的。整件事最好写成:
public bool Equals( object obj )
{
var other = obj as data;
if( other == null ) return false;
return p1 == obj.p1 && p2 == obj.p2;
}
我还删除了对ToString
的调用,因为它不会显著简化代码或使其更具可读性。这也是执行比较的一种低效方法,因为在进行比较之前必须构造两个新字符串。直接比较成员可以让您有更多的机会提前退出,更重要的是,更容易阅读(实际的平等实现不依赖于字符串表示)
如果他们都很好,这种行为是怎么发生的
我不知道,因为你给的代码不能这样做。它也不会编译。您的数据
类有两个只读
字段,您不能使用初始值设定项列表分配这些字段,正如您在上一个代码段中所示
我只能推测你所看到的行为,因为你在这里展示的任何东西都不会导致所描述的行为
我能给出的最好建议是确保您的密钥类是不可变的可变类型不能很好地使用字典
。Dictionary
类不希望对象的哈希代码发生更改,因此如果GetHashCode
依赖于类中任何可变的部分,则很可能会将事情弄得一团糟
我认为GetHachCode()是字典的主要“比较”操作,这总是正确的吗
Dictionary
仅使用GetHashCode
作为“寻址”对象的一种方式(具体来说,哈希代码用于标识项目应放在哪个bucket中)。它不一定直接用作比较。如果是这样,它只能用它来确定两个物体不相等,它不能用它来确定它们是否相等
键是对象的字典的真正“索引”是什么
我不完全确定你在问什么,但我倾向于说答案是这无关紧要。物品的去向并不重要。如果你关心这类事情,你可能不应该使用字典
GetHashCode()是否被正确重写
否。您允许为p1
或p2
和null传递null
。GetHashCode()
抛出NullReferenceException
中不允许的NullReferenceException
。禁止传递null
,或使GetHashCode
为null返回int
(可以为零)
你也在对不变的整数进行XORing;这意味着您创建的每个包含两个相同值的类的hashCode为零。这是很常见的碰撞,;通常情况下,将每个哈希代码乘以一个素数以避免出现这种情况
是否正确重写了Equals
否。您链接到的页面是由System.Collections.HashTable
使用的非通用Equals
。您正在使用genericSystem.Collections.generic.Dictionary
,它使用
public int GetHashCode()
{
return p1.GetHashCode() ^ ( 13 * p2.GetHashCode() );
}
public bool Equals( object obj )
{
var other = obj as data;
if( other == null ) return false;
return p1 == obj.p1 && p2 == obj.p2;
}
public class MatPair : IEquatable<MatPair>
{
public readonly string MatNeedsToExplainWhatThisRepresents;
public readonly string MatNeedsToExplainThisToo;
public MatPair(string matNeedsToExplainWhatThisRepresents,
string matNeedsToExplainThisToo)
{
if (matNeedsToExplainWhatThisRepresents == null) throw new ArgumentNullException("matNeedsToExplainWhatThisRepresents");
if (matNeedsToExplainThisToo == null) throw new ArgumentNullException("matNeedsToExplainThisToo");
this.MatNeedsToExplainWhatThisRepresents = matNeedsToExplainWhatThisRepresents;
this.MatNeedsToExplainThisToo = matNeedsToExplainThisToo;
}
[Obsolete]
public override bool Equals(object obj)
{
return Equals(obj as MatPair);
}
public bool Equals(MatPair matPair)
{
return matPair != null
&& matPair.MatNeedsToExplainWhatThisRepresents == MatNeedsToExplainWhatThisRepresents
&& matPair.MatNeedsToExplainThisToo == MatNeedsToExplainThisToo;
}
public override int GetHashCode()
{
unchecked
{
return MatNeedsToExplainWhatThisRepresents.GetHashCode() * 31
^ MatNeedsToExplainThisToo.GetHashCode();
}
}
public override string ToString()
{
return "{" + MatNeedsToExplainWhatThisRepresents + ", "
+ MatNeedsToExplainThisToo + "}";
}
}