2

私はちょうど今、この奇妙な状況に出くわしました: 次のようなレガシーコードを編集していました:

Hashtable hashtable = GetHashtable();

for (int i = 0; i < hashtable.Count; i++)
{
    MyStruct myStruct = (MyStruct)hashtable[i];

    //more code
}

これをforeachループに変更すると:

var hashtable = GetHashtable();

foreach (var item in hashtable)
{
    var myStruct = (MyStruct)item;

    //more code
}

動作は同じだと思っていましたが、System.InvalidCastException: Specified cast is not valid.

この異なる動作の理由は何ですか?

4

2 に答える 2

15

a のHashtable反復はその値を反復するのではなく、キーと値のペアをDictionaryEntryオブジェクトとして反復します。

.Values代わりに、そのコレクションを反復してみてください。

foreach (var item in hashtable.Values)
{
    var myStruct = (MyStruct)item;
}

古いレガシー コードをリファクタリングしているため、可能であれば、Dictionary<TKey, TValue>代わりにジェネリックを使用することも検討する必要があります。struct値のセマンティクスを利用して、ボクシングを回避します。


オブジェクトを反復したい場合はDictionaryEntry、そうすることができますが、あなたのMyStruct:

foreach (DictionaryEntry entry in hashtable)
{
    var myStruct = (MyStruct)entry.Value;
}

最後に、Linq ソリューションがありますが、これはレガシー コードであるため、適用できない場合があります。利用できない場合があります。

foreach(var myStruct in hashtable.Values.Cast<MyStruct>())
{

}
于 2013-07-22T12:30:34.023 に答える
1

Hashtable で生成された各項目は DictionaryEntry です。したがって、このようにすることもできます

foreach (DictionaryEntry de in hashtable)
{
    var myStruct = (MyStruct)de.Value;
    //more code
}
于 2013-07-22T12:39:09.800 に答える