VB.NET如何确定字典(Of)中的唯一键?

VB.NET如何确定字典(Of)中的唯一键?,vb.net,dictionary,Vb.net,Dictionary,我有以下课程: Public Class Pair(Of T1, T2) Public Property First As T1 Public Property Second As T2 Public Sub New(Optional ByVal first As T1 = Nothing, Optional ByVal second As T2 = Nothing) Me.First = first Me.Second = secon

我有以下课程:

Public Class Pair(Of T1, T2)

    Public Property First As T1
    Public Property Second As T2

    Public Sub New(Optional ByVal first As T1 = Nothing, Optional ByVal second As T2 = Nothing)
        Me.First = first
        Me.Second = second
    End Sub

    Public Overrides Function tostring() As String
        Return String.Format("<[{0},{1}]>", First, Second)
    End Function

    Public Overrides Function GetHashCode() As Integer         
        Return Integer.Parse(String.Format("{0}{1}", First.GetHashCode, Second.GetHashCode))
    End Function
End Class
我的期望是,由于
p
p2
都有
123413
的散列码,因此它们将命中相同的字典元素,
WriteLine
将显示“Hello”。然而,真正发生的是,我得到了一个
KeyNotFoundException
,这使我相信
字典(Of…
的)实际上没有使用
GetHashCode
方法

那么,我需要做什么才能使这两对引用同一个dictionary元素呢


谢谢

拥有相同的散列码是不够的-两个键也需要相等,即
key1.Equals(key2)
必须为true(或自定义比较器下的等效值)

您还没有覆盖
Equals
,因此两个
Pair
对象总是不相等的

(请注意,散列码函数也会以各种方式失败,例如它们都是负数。为什么不以某种方式组合这两个整数值?)

我对VB不太了解,所以在我应该睡觉的时候,我自己不能想出合适的覆盖,但在C#中,它会是这样的:

public override bool Equals(object other)
{
    if (other == null)
    {
        return false;
    }
    if (other.GetType() != this.GetType())
    {
        return false;
    }
    var otherPair = (Pair<T1, T2>) other;
    return EqualityComparer<T1>.Default(this.First, otherPair.First) &&
           EqualityComparer<T2>.Default(this.Second, otherPair.Second);
}
public override bool Equals(对象其他)
{
如果(其他==null)
{
返回false;
}
if(other.GetType()!=this.GetType())
{
返回false;
}
var otherPair=(Pair)other;
返回EqualityComparer.Default(this.First,otherPair.First)&&
EqualityComparer.Default(this.Second,otherPair.Second);
}

(顺便说一句,我会使用
EqualityComparer.Default
生成散列码。)

拥有相同的散列码是不够的-两个键也需要相等,即
key1.Equals(key2)
必须为true(或自定义比较器下的等效值)

您还没有覆盖
Equals
,因此两个
Pair
对象总是不相等的

(请注意,散列码函数也会以各种方式失败,例如它们都是负数。为什么不以某种方式组合这两个整数值?)

我对VB不太了解,所以在我应该睡觉的时候,我自己不能想出合适的覆盖,但在C#中,它会是这样的:

public override bool Equals(object other)
{
    if (other == null)
    {
        return false;
    }
    if (other.GetType() != this.GetType())
    {
        return false;
    }
    var otherPair = (Pair<T1, T2>) other;
    return EqualityComparer<T1>.Default(this.First, otherPair.First) &&
           EqualityComparer<T2>.Default(this.Second, otherPair.Second);
}
public override bool Equals(对象其他)
{
如果(其他==null)
{
返回false;
}
if(other.GetType()!=this.GetType())
{
返回false;
}
var otherPair=(Pair)other;
返回EqualityComparer.Default(this.First,otherPair.First)&&
EqualityComparer.Default(this.Second,otherPair.Second);
}

(顺便说一句,我也会使用
EqualityComparer.Default
生成散列码。)

这里有很多问题需要处理

首先,您还必须覆盖
Equals
,因为
GetHashCode
只是用来快速确定两个对象是否不相等的方法。它永远不会告诉您对象是否相等。这就是
Equals
的目的-这是最后一次检查两个对象是否相等,计算速度可能比
GetHashCode
慢得多

这里有一个例子。假设你有三条很长的弦,两条长度相同,另一条不同。如果
GetHashCode
返回了字符串的长度,那么您可以很快确定第三个字符串肯定不等于前两个字符串。您必须检查前两个的实际内容,看看它们是否相等,相对而言,这可能是一个漫长的过程

接下来,同样重要的是,不能拥有在对象生命周期内更改的哈希代码

关键字是不能。它会破坏一切

Dictionary(Of,)
类使用一系列“bucket”根据键的哈希代码快速查找值。因此,如果您的密钥的哈希代码在添加到字典后发生更改,那么字典将无法找到它,它将允许您添加密钥两次

下面是一个例子:

Dim d = New Dictionary(Of Pair(Of Integer, Integer), String)
Dim p = new Pair(Of Integer, Integer)(10, 11)
d.Add(p, "James")
Dim before = d(p) ' Found!
p.First = 12
Dim after = d(p) ' NOT Found!
或者这个:

Dim d = New Dictionary(Of Pair(Of Integer, Integer), String)
Dim p = new Pair(Of Integer, Integer)(10, 11)
d.Add(p, "James")
p.First = 12
d.Add(p, "Tom") ' ALLOWED!
这就是可变结构不好的原因


我希望这能有所帮助。

您有许多问题需要处理

首先,您还必须覆盖
Equals
,因为
GetHashCode
只是用来快速确定两个对象是否不相等的方法。它永远不会告诉您对象是否相等。这就是
Equals
的目的-这是最后一次检查两个对象是否相等,计算速度可能比
GetHashCode
慢得多

这里有一个例子。假设你有三条很长的弦,两条长度相同,另一条不同。如果
GetHashCode
返回了字符串的长度,那么您可以很快确定第三个字符串肯定不等于前两个字符串。您必须检查前两个的实际内容,看看它们是否相等,相对而言,这可能是一个漫长的过程

接下来,同样重要的是,不能拥有在对象生命周期内更改的哈希代码

关键字是不能。它会破坏一切

Dictionary(Of,)
类使用一系列“bucket”根据键的哈希代码快速查找值。因此,如果您的密钥的哈希代码在添加到字典后发生更改,那么字典将无法找到它,它将允许您添加密钥两次

下面是一个例子:

Dim d = New Dictionary(Of Pair(Of Integer, Integer), String)
Dim p = new Pair(Of Integer, Integer)(10, 11)
d.Add(p, "James")
Dim before = d(p) ' Found!
p.First = 12
Dim after = d(p) ' NOT Found!
或者这个:

Dim d = New Dictionary(Of Pair(Of Integer, Integer), String)
Dim p = new Pair(Of Integer, Integer)(10, 11)
d.Add(p, "James")
p.First = 12
d.Add(p, "Tom") ' ALLOWED!
这就是可变结构不好的原因

我希望这能有所帮助。

有几件事:

GetHashCode
被字典用来确定密钥在内部的存储位置,但是它是
Dim Pairs as Dictionary(Of KeyValuePair(Of Integer, Integer), String)
Pairs.add(p.GetKey(), "Hello")
Console.WriteLine(Pairs(p2.GetKey()))