Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在循环中更新C#哈希表?_C#_Data Structures_Loops_Hashtable - Fatal编程技术网

如何在循环中更新C#哈希表?

如何在循环中更新C#哈希表?,c#,data-structures,loops,hashtable,C#,Data Structures,Loops,Hashtable,我试图更新循环中的哈希表,但出现错误:System.InvalidOperationException:集合已修改;枚举操作不能执行 private Hashtable htSettings_m = new Hashtable(); htSettings_m.Add("SizeWidth", "728"); htSettings_m.Add("SizeHeight", "450"); string sKey = ""; string sValue = ""; foreach (Dictionar

我试图更新循环中的哈希表,但出现错误:System.InvalidOperationException:集合已修改;枚举操作不能执行

private Hashtable htSettings_m = new Hashtable();
htSettings_m.Add("SizeWidth", "728");
htSettings_m.Add("SizeHeight", "450");
string sKey = "";
string sValue = "";
foreach (DictionaryEntry deEntry in htSettings_m)
{
    // Get value from Registry and assign to sValue.
    // ...
    // Change value in hashtable.
    sKey = deEntry.Key.ToString();
    htSettings_m[sKey] = sValue;
}

是否有办法解决这个问题,或者是否有更好的数据结构用于此目的?

在对集合进行枚举时,不能更改集合中存储的项集,因为在大多数情况下,这使得迭代器的工作非常困难。考虑集合表示平衡树的情况,并且可以在插入之后进行旋转。列举者没有任何合理的方法来记录它所看到的一切

但是,如果您只是尝试更新该值,则可以编写:

deEntry.Value = sValue
更新此处的值对枚举数没有影响。

在概念中,我会:

Hashtable table = new Hashtable(); // ps, I would prefer the generic dictionary..
Hashtable updates = new Hashtable();

foreach (DictionaryEntry entry in table)
{
   // logic if something needs to change or nog
   if (needsUpdate)
   {
      updates.Add(key, newValue);
   }
}

// now do the actual update
foreach (DictionaryEntry upd in updates)
{
   table[upd.Key] = upd.Value;
}

也许你可以使用Hashtable.Keys集合?在更改哈希表时,可能会枚举该值。但这只是一个猜测…

您可以先将密钥集合读入另一个IEnumerable实例,然后再读入该列表

        System.Collections.Hashtable ht = new System.Collections.Hashtable();

        ht.Add("test1", "test2");
        ht.Add("test3", "test4");

        List<string> keys = new List<string>();
        foreach (System.Collections.DictionaryEntry de in ht)
            keys.Add(de.Key.ToString());

        foreach(string key in keys)
        {
            ht[key] = DateTime.Now;
            Console.WriteLine(ht[key]);
        }
System.Collections.Hashtable ht=new System.Collections.Hashtable();
ht.添加(“测试1”、“测试2”);
ht.添加(“测试3”、“测试4”);
列表键=新列表();
foreach(System.Collections.DictionaryEntry de in ht)
添加(de.Key.ToString());
foreach(字符串键入键)
{
ht[key]=DateTime.Now;
控制台写入线(ht[键]);
}

这取决于在哈希表中循环项目的原因。但是,您可能能够遍历这些键。所以

foreach (String sKey in htSettings_m.Keys)
{   // Get value from Registry and assign to sValue.
    // ...    
    // Change value in hashtable.
    htSettings_m[sKey] = sValue;
}
另一个选项是创建一个新的哈希表。迭代第一个,同时向第二个添加项目,然后用新项目替换原始项目。

不过,循环遍历键需要更少的对象分配。

最简单的方法是将键复制到单独的集合中,然后迭代遍历该集合


您正在使用.NET3.5吗?如果是这样,LINQ会让事情变得更简单。

如果您使用字典而不是哈希表,以便知道键的类型,那么创建键集合副本以避免此异常的最简单方法是:

foreach (string key in new List<string>(dictionary.Keys))
foreach(新列表中的字符串键(dictionary.Keys))
为什么会出现一个异常,告诉您您已经修改了正在迭代的集合,而实际上您还没有修改

在内部,Hashtable类有一个version字段。Add、Insert和Remove方法会增加此版本。在哈希表公开的任何集合上创建枚举器时,枚举器对象包括哈希表的当前版本。枚举器的MoveNext方法会对照哈希表检查枚举器的版本,如果它们不相等,则抛出您看到的InvalidOperationException

这是一种非常简单的机制,用于确定哈希表是否已被修改。事实上,这有点太简单了。Keys集合实际上应该维护自己的版本,其GetEnumerator方法应该在枚举器中保存集合的版本,而不是哈希表的版本


这种方法还有另一个更微妙的设计缺陷。该版本是一个Int32。UpdateVersion方法不进行边界检查。因此,如果您对哈希表进行了正确次数的修改(2次
Int32.MaxValue
,给定或获取),则哈希表和枚举器上的版本可能是相同的,即使您在创建枚举器后彻底更改了哈希表。因此,MoveNext方法不会抛出异常,即使它应该抛出异常,您也会得到意外的结果。

关键部分是ToArray()方法

var dictionary = new Dictionary<string, string>();
foreach(var key in dictionary.Keys.ToArray())
{
    dictionary[key] = "new value";
}
var dictionary=newdictionary();
foreach(dictionary.Keys.ToArray()中的var key)
{
字典[键]=“新值”;
}

这是我在字典里做的;将dict中的每个值重置为false:

Dictionary<string,bool> dict = new Dictionary<string,bool>();

for (int i = 0; i < dict.Count; i++)
{
    string key = dict.ElementAt(i).Key;
    dict[key] = false;
}
Dictionary dict=new Dictionary();
对于(int i=0;i
List keyList=htSettings\u m.Keys.Cast().ToList();
foreach(键列表中的字符串键){

它与其他答案相同,但我喜欢用一行来获取密钥。

将其转换为数组:

private Hashtable htSettings_m = new Hashtable();
htSettings_m.Add("SizeWidth", "728");
htSettings_m.Add("SizeHeight", "450");
string sKey = "";
string sValue = "";

ArrayList htSettings_ary = new ArrayList(htSettings_m.Keys)
foreach (DictionaryEntry deEntry in htSettings_ary)
{
    // Get value from Registry and assign to sValue.
    // ...
    // Change value in hashtable.
    sKey = deEntry.Key.ToString();
    htSettings_m[sKey] = sValue;
}

请相信这是一个dup问题请参见:那不是编译:无法修改'deEntry'的成员,因为它是一个'foreach迭代变量',这是在不进行测试的情况下从错误内存响应的问题。我再次思考了这个问题,我记得哈希表对哈希表及其键使用相同的枚举器类型。seri在我看来,实现存在严重缺陷。不,问题不在于枚举器类型——问题在于Keys属性没有获取所有键的副本,它只是在基础集合上迭代。当需要获取副本时,请显式执行。这是我个人想要和期望的行为。我不得不在这里不同意你的观点:Keys集合n是键集合而不是哈希表,键枚举器应该只对键集合中的更改敏感,而不是对整个哈希表中的更改敏感。我认为这是哈希表类中的设计缺陷。请参阅我的答案中的更多详细信息。比当前最简单的解决方案简单得多。
List<string> keyList = htSettings_m.Keys.Cast<string>().ToList();
foreach (string key in keyList) {
private Hashtable htSettings_m = new Hashtable();
htSettings_m.Add("SizeWidth", "728");
htSettings_m.Add("SizeHeight", "450");
string sKey = "";
string sValue = "";

ArrayList htSettings_ary = new ArrayList(htSettings_m.Keys)
foreach (DictionaryEntry deEntry in htSettings_ary)
{
    // Get value from Registry and assign to sValue.
    // ...
    // Change value in hashtable.
    sKey = deEntry.Key.ToString();
    htSettings_m[sKey] = sValue;
}