我刚刚遇到了这种奇怪的情况:我正在编辑一些看起来像这样的遗留代码:
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.
这种不同行为的原因是什么?
答案 0 :(得分:15)
迭代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>())
{
}
答案 1 :(得分:1)
Hashtable中的每个产生的项目都是DictionaryEntry。因此你也可以这样做
foreach (DictionaryEntry de in hashtable)
{
var myStruct = (MyStruct)de.Value;
//more code
}