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とVS2008を使用しています。このエラーの原因となるプロジェクトごとの違いがわかりません。テストはコンソールアプリケーションであり、プログラムはwinformsアプリです。

これらのコレクションのデフォルトのプロパティが変更される原因となる条件は何ですか?

編集-辞書をループする方法を教えてくれるすべての答えをありがとう。ただし、これらの回答は、なぜ一方のプロジェクトでインデックスを使用でき、もう一方のプロジェクトでは使用できないのかという私の質問には答えません。ある.netプロジェクトから別のプロジェクトにコードをコピーして貼り付け、同じように機能させることはできませんか?そして、いいえ、オプションは厳密ですが、問題の原因ではありません。

編集-私が見ているものを再現しようとします:

  • VS2008を使用して新しい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 ++;)を使用してループすることは、ハッシュテーブル(辞書)を通過する正しい方法ではありません。これは配列ではないため、実際には配列インデックス(array [index])の概念がないためです。

于 2009-04-25T03:10:37.617 に答える
3

すべてのプロジェクトがそうであるように、実際のプロジェクトには がOPTION STRICT ONあり、テスト プロジェクトにはそれがオフになっているに違いありません。これが、テスト プロジェクトでコンパイラ エラーが発生しなかった理由です。

編集:ポスターは、両方のプロジェクトで OPTION STRICT ON を持っていると言っています。それはこれをより面白くします。

この違いの最も可能性の高い理由は、あるケースではコンパイラがコードをコンパイルしてエラーを確認したことだと今でも考えています。しかし、それ以外の場合、コンパイラはコードをコンパイルしませんでした。これは、同時に同じマシン上の同じバージョンの Visual Studio ですか? どちらの場合も .NET Framework のバージョンは同じですか?

これらはどちらも同じタイプのプロジェクトですか? たとえば、どちらもコンソール アプリケーションですか? ASP.NET Web サイトの "プロジェクト" は通常、コードが呼び出されるまでコードをコンパイルしようとしないためです。テスト プロジェクトがそのような「プロジェクト」であり、実際にコードをテストしなかった場合 (つまり、実際にこのコードに足を踏み入れて機能することを確認しなかった場合) は、 F5 を押すことができるということは、すべてのコードがコンパイルされていないときにコンパイルされたことを意味します。

私の次の考えは、両方のケースで MyDictionary が本当に同じ型であるかどうかを確認することです。

それを超えて、なぜこれが起こったのかを本当に知る必要がある場合は、「実際の」プロジェクトのコピーを作成し、それをテスト プロジェクトのように変更し始めます。これはおそらく、最初は大量削除の問題になるでしょう。問題が見つかるまで、または2つが同一になるまで、変更を続けます。

編集 2:デフォルトのコンソール プロジェクトは、System.Linq 名前空間をインポートします (プロジェクト プロパティの [参照] タブを参照してください)。このインポートにより、ElementAtOrDefault 拡張メソッドがスコープに含まれます。この拡張メソッドは IEnumerable(Of T); を拡張します。あなたの場合、Keys プロパティが実装する IEnumerable(Of Double) です。

これについて驚いたのは、VB.NET がこの拡張メソッドを自動的に適用していることです。C# では、メソッドに明示的に名前を付ける必要があります。

System.Linq のインポートを削除すると、テスト アプリケーションで実稼働アプリケーションと同じエラーが発生することがわかります。

于 2009-04-25T13:17:58.340 に答える
2

Dictionary(Of TKey、TValue)のKeys and Valuesプロパティには、インデクサープロパティがありません。これらはICollectionとIListの実装であるため、インデックスによるアクセスをサポートしていません。ディクショナリを反復処理する場合、最良の方法はForEachループです。

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

編集

System.Coreが両方のプロジェクトで参照されていること、およびSystem.Linqのプロジェクトレベルのインポートがあることを確認しましたか?それが、system.Core内のメソッドであるElementAtOrDefaultに違いをもたらすと私が考えることができる唯一のことです。

なぜそのメソッドが単純なインデクサーにバインドされるのか、私はまだ少し困惑しています。それを調べに行く

于 2009-04-25T03:14:14.703 に答える