6

我有一个 VB.NET 项目,我可以在其中使用索引遍历字典对象的键和值集合:


MyDictionary.Keys(idx)
MyDictionary.Values(idx)

当此代码从测试项目中取出并放入实际项目中时,我收到以下错误:

'System.Collections.Generic.Dictionary(Of Double, String).KeyCollection' 不能被索引,因为它没有默认属性。

'System.Collections.Generic.Dictionary(Of Double, String).ValueCollection' 无法被索引,因为它没有默认属性。

这是使用 VB.NET 和 VS 2008。我不知道从一个项目到下一个项目会有什么不同会导致此错误。测试是一个控制台应用程序,程序是一个 winforms 应用程序。

什么条件会导致这些集合的默认属性发生变化?

编辑- 感谢您提供所有告诉我如何遍历字典的答案。然而,这些答案并不能回答我为什么可以在一个项目而不是另一个项目中使用索引的问题。我是否应该无法将代码从一个 .net 项目复制并粘贴到另一个项目并使其工作相同?而且,不,选项严格,不是问题的原因。

编辑- 尝试重现我所看到的:

  • 使用 VS 2008 创建一个新的 VB.NET 控制台应用程序
  • 将以下代码复制并粘贴到模块中:

Imports System.Collections
Imports System.Collections.Generic

Module Module1

    Public dtf As Dictionary(Of Double, String)

    Public Sub BuildDictionary()

        dtf = New Dictionary(Of Double, String)

        dtf.Add(1.0, "1")
        dtf.Add(0.0, "0")

    End Sub

    Public Sub Search()
        For idx As Integer = 0 To dtf.Keys.Count - 1
            If dtf.Keys(idx) = 0 Then
                Exit Sub
            End If
        Next
    End Sub

    Sub Main()

    End Sub

End Module

在子搜索中显示“dtf.Keys(idx) = 0”的行中,将光标放在右括号和退格之后,您应该会得到一个工具提示,上面写着“<Extension> ElementAtOrDefault(index as Integer) as Double - index:要检索的索引的从零开始的元素。

我没有在我的其他项目中得到这个。即使看起来我有相同的参考和设置。

4

3 回答 3

4

KeyCollection 没有实现这样的索引器,您必须通过 MyDictionary.Keys 进行枚举。

C#

foreach(double key in MyDictionary.Keys)
 Console.Write( MyDictionary[ key ] )

VB

For Each key As Double in MyDictionary.Keys
   Console.Write( MyDictionary( key )
Next key

使用 for(;i++;) 循环不是通过哈希表(字典)的正确方法,因为它不是数组,它实际上没有数组索引的概念(数组 [索引])

于 2009-04-25T03:10:37.617 回答
3

我敢打赌,你的真实项目OPTION STRICT ON和所有项目一样,并且你的测试项目已经关闭了它。这就是为什么您的测试项目中没有出现编译器错误的原因。

编辑:海报说他对这两个项目都有 OPTION STRICT ON。这使得这更有趣。

我仍然认为造成这种差异的最可能原因是,在一种情况下,编译器编译了代码并看到了错误;但在另一种情况下,编译器没有编译代码。这是同一台机器上同一版本的 Visual Studio 吗?两种情况下的 .NET Framework 版本相同吗?

例如,它们是否都是同一类型的项目,它们都是控制台应用程序吗?我问是因为 ASP.NET 网站“项目”通常在调用代码之前不会尝试编译代码。如果您的测试项目是这样一个“项目”,并且您没有实际测试代码(也就是说,如果您没有实际进入此代码并看到它工作),那么您可能会假设您可以按 F5 意味着所有代码都已编译,而没有。

我接下来的想法是看看 MyDictionary 在这两种情况下是否真的属于同一类型。

除此之外,如果您真的需要知道为什么会发生这种情况,我会复制“真实”项目,并开始将其更改为越来越像测试项目。起初这可能是大规模删除的问题。我会一直更改它,直到发现问题,或者直到两者相同。

编辑 2:默认控制台项目导入 System.Linq 命名空间(请参阅项目属性中的“参考”选项卡)。此导入将 ElementAtOrDefault 扩展方法引入范围。此扩展方法扩展了 IEnumerable(Of T); 在您的情况下 IEnumerable(Of Double),这是 Keys 属性实现的。

让我吃惊的是 VB.NET 会自动应用这种扩展方法。在 C# 中,需要显式命名该方法。

如果您删除 System.Linq 的 Import,您会发现您的测试应用程序得到与生产应用程序相同的错误。

于 2009-04-25T13:17:58.340 回答
2

Dictionary(Of TKey,TValue) 的 Keys 和 Values 属性没有索引器属性。它们是 ICollection 与 IList 的实现,因此不支持通过索引进行访问。如果要遍历字典,最好的方法是 For Each 循环。

For Each pair in MyDictionary
  Dim key = pair.Key
  Dim value = pair.Value
Next

编辑

您是否检查以确保两个项目中都引用了 System.Core,并且您有 System.Linq 的项目级导入?这是我能想到的唯一一件事,它会在 ElementAtOrDefault 中产生差异,ElementAtOrDefault 是 system.Core 内部的一种方法。

我仍然有点困惑,为什么该方法会被绑定到一个简单的索引器。要去调查那个

于 2009-04-25T03:14:14.703 回答