문제

루프에서 해시 테이블을 업데이트하려고하지만 오류가 발생합니다. 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;
}

그 주위에 방법이 있습니까 아니면 그러한 목적을위한 더 나은 데이터 구조가 있습니까?

도움이 되었습니까?

해결책

키 컬렉션을 먼저 다른 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]);
        }

다른 팁

개념적으로 나는 할 것이다 :

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;
}

해시 테이블 대신 사전을 사용하는 경우 키 유형이 알려져 있으면이 예외를 피하기 위해 키 컬렉션의 사본을 만드는 가장 쉬운 방법은 다음과 같습니다.

foreach (string key in new List<string>(dictionary.Keys))

왜 그렇지 않은 경우 반복하고있는 컬렉션을 수정했다고 말하는 이유는 무엇입니까?

내부적으로 Hashtable 클래스에는 버전 필드가 있습니다. 메소드를 추가, 삽입 및 제거 하여이 버전을 증가시킵니다. 해시 테이블이 노출되는 컬렉션에 열거자를 만들 때, 열거 자체에는 해시 테이블의 현재 버전이 포함됩니다. 열거 자의 MOVENEXT 메소드는 열거 자의 버전을 해시 테이블에 대해 확인하고 동일하지 않은 경우보고있는 InvalidOperationException을 던졌습니다.

이것은 해시 가능이 수정되었는지 여부를 결정하기위한 매우 간단한 메커니즘입니다. 사실 너무 간단합니다. Keys Collection은 실제로 자체 버전을 유지해야하며 GetEnumerator 방법은 Hashtable의 버전이 아닌 Enumerator에 컬렉션의 버전을 저장해야합니다.

이 접근법에는 또 다른 미묘한 디자인 결함이 있습니다. 버전은 int32입니다. updateversion 메소드는 한계 검사를 수행하지 않습니다. 따라서 해시 가능에 대한 올바른 수정을 정확히하면 가능합니다 (2 배 Int32.MaxValue, 주 또는 가져 가기), 해시 테이블의 버전과 열거자가 동일하게되도록 열거자를 생성 한 이후 해시 테이블을 근본적으로 변경하더라도 동일합니다. 따라서 MOVENEXT 메소드는 예외를 제외해야하지만 예상치 못한 결과를 얻을 수 있습니다.

가장 간단한 방법은 키를 별도의 컬렉션에 복사 한 다음 대신 반복하는 것입니다.

.NET 3.5를 사용하고 있습니까? 그렇다면 LINQ는 상황을 조금 더 쉽게 만듭니다.

핵심 부분은 ToArray () 방법

var dictionary = new Dictionary<string, string>();
foreach(var key in dictionary.Keys.ToArray())
{
    dictionary[key] = "new value";
}

당신은 컬렉션에 저장된 항목 세트를 변경할 수 없습니다. 이는 대부분의 경우 반복자에게는 삶이 매우 어렵 기 때문에 컬렉션을 열거하고 있습니다. 컬렉션이 균형 잡힌 트리를 나타내는 경우를 고려하고 삽입 후 회전을 잘받을 수 있습니다. 열거는 그것이 본 것을 추적하는 그럴듯한 방법이 없을 것입니다.

그러나 값을 업데이트하려는 경우 다음을 작성할 수 있습니다.

deEntry.Value = sValue

여기서 값을 업데이트하면 열거 자에 영향을 미치지 않습니다.

이것이 내가 사전 내에서 그것을 한 방법입니다. DITT의 모든 값을 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;
}

해시 가능의 항목을 통해 루프를하는 이유에 따라 다릅니다. 그러나 당신은 아마도 키를 대신 반복 할 수있을 것입니다. 그래서

foreach (String sKey in htSettings_m.Keys)
{   // Get value from Registry and assign to sValue.
    // ...    
    // Change value in hashtable.
    htSettings_m[sKey] = sValue;
}

다른 옵션은 새로운 해시 테이블을 만드는 것입니다. 두 번째에 항목을 추가하면서 첫 번째를 반복 한 다음 원본을 새 제품으로 교체하십시오.
키를 통한 반복은 객체 할당이 적습니다.

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;
}
private Hashtable htSettings_m = new Hashtable();

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

hashtable.keys 컬렉션을 사용할 수 있습니까? 해시 테이블을 변경하는 동안이를 통해 열거 할 수 있습니다. 하지만 그것은 단지 추측 일뿐입니다 ...

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top