2012-01-02 57 views
1

下面的代码摘自一个较大的过程(周围的代码是不相关的)。任何人都可以解释为什么我无法获得第二个ContainsKey行来返回True?提示:在只有少数填充单元格的工作表上试试这一点,以减少循环。Vb.Net使用字典与Excel范围作为键

 For Each ws As Excel.Worksheet In Wb.Worksheets 
      Dim dic As New Dictionary(Of Excel.Range, String) 
      rngUsed = ws.UsedRange 
      For Each cell As Excel.Range In rngUsed 
       dic.Add(cell, "test") 
       'THE FOLLOWING TWO MESSAGES SHOULD DISPLAY THE SAME RESULT, BUT DO NOT. WHY??? 
       MsgBox(dic.ContainsKey(cell)) 'Returns True 
       MsgBox(dic.ContainsKey(ws.Range(cell.Address))) 'Returns False 
      Next 
     Next 

更新:我已添加以下代码和它似乎是工作:

Dim dic As New Dictionary(Of Excel.Range, String)(New MyComparer()) 'replaces line from above 

Class MyComparer 
Implements IEqualityComparer(Of Excel.Range) 
Public Function Equals1(ByVal x As Excel.Range, ByVal y As Excel.Range) As Boolean Implements System.Collections.Generic.IEqualityComparer(Of Excel.Range).Equals 
    If x.Address(External:=True) = y.Address(External:=True) Then 
     Return True 
    Else 
     Return False 
    End If 
End Function 
Public Function GetHashCode1(ByVal obj As Excel.Range) As Integer Implements System.Collections.Generic.IEqualityComparer(Of Excel.Range).GetHashCode 
    Return obj.Count.GetHashCode 
End Function 

末级

+0

为什么不使用'cell.Address'作为关键? – 2012-01-02 20:25:31

+0

Tim,回答你的问题,这是因为行的插入/移除会把我的钥匙搞砸。我发布了我认为是上述答案的东西(到目前为止,它似乎工作正常)。 – OfficeAddinDev 2012-01-02 20:27:01

+0

@Ryan如果您对自己的解决方案感到满意,您应该将更新转到答案并接受它。 – 2012-01-02 20:35:11

回答

1
Dim dic As New Dictionary(Of Excel.Range, String)(New MyComparer()) 'replaces line from above 

Class MyComparer 
Implements IEqualityComparer(Of Excel.Range) 
Public Function Equals1(ByVal x As Excel.Range, ByVal y As Excel.Range) As Boolean Implements System.Collections.Generic.IEqualityComparer(Of Excel.Range).Equals 
    If x.Address(External:=True) = y.Address(External:=True) Then 
     Return True 
    Else 
     Return False 
    End If 
End Function 
Public Function GetHashCode1(ByVal obj As Excel.Range) As Integer Implements System.Collections.Generic.IEqualityComparer(Of Excel.Range).GetHashCode 
    Return obj.Count.GetHashCode 
End Function 

这是解决方案。请注意,在这个自定义比较器中使用的GetHashCode非常缓慢,所以如果任何人有一个想法来加快速度,我很乐意听到它。 @competent_tech,我必须使用对象作为键,因为对于范围来说没有字符串表示是唯一的并且不会改变(例如,当添加/删除行时地址如何改变)。

1

当对象被用作密钥的字典,.NET使用GetHashCode生成在底层散列表中使用的密钥。由于您使用了两个不同的对象,因此您将得到不同的值。

请参阅the MSDN documentation了解更多详情。

更好的方法是将范围转换为字符串表示并将其用作关键字。