public class DitonaryTest : MonoBehaviour
{
public Dictionary<string, bool> checkList;
void Start()
{
checkList = new();
checkList["aaa"] = true;
checkList["bbb"] = false;
checkList["ccc"] = true;
checkList["ddd"] = false;
// 요소 삭제
foreach(var work in checkList)
{
if(work.Key == "ccc")
{
checkList.Remove("ccc");
}
}
// 요소 출력
foreach(var work in checkList)
{
Debug.Log(work.Key + " : " + work.Value);
}
}
}
데이터를 이름를 키로, bool값을 값으로 가지는 딕셔너리에서 딕셔너리의 특정 키값을 가지는 요소를 제거할려는 상황이였다.

InvalidOperationException: Collection was modified; enumeration operation may not execute.
System.Collections.Generic.Dictionary`2+Enumerator[TKey,TValue].MoveNext () (at <17d9ce77f27a4bd2afb5ba32c9bea976>:0)
이 에러는 foreach안에서 해당 요소를 삭제하였을 때 생기는 문제이다.
foreach는 내부적으로 이터레이터(Enumerator)를 사용하여 컬렉션을 순회하는데
순회하는 동안 항목을 삭제하면 이터레이터가 예상치 못한 변경을 감지하고 예외를 발생시킨다.
그렇기에 foreach내에서 요소를 삭제한다면 딕셔너리, 리스트등을 가지리 않고 발생한다.
List<int> numbers = new List<int>{1, 2, 3, 4};
foreach(var num in numbers)
{
if(num == 3)
{
numbers.Remove(3);
}
}
예를 들어 위와 같이 리스트의 요소를 foreach내부에서 요소를 삭제하면 다음과 같은 오류가 발생한다.
InvalidOperationException: Collection was modified; enumeration operation may not execute.
System.Collections.Generic.List`1+Enumerator[T].MoveNextRare () (at <17d9ce77f27a4bd2afb5ba32c9bea976>:0)
System.Collections.Generic.List`1+Enumerator[T].MoveNext () (at <17d9ce77f27a4bd2afb5ba32c9bea976>:0)
위 에러도 역시 이터레이터가 변경을 감지 하였기에 예외를 발생시킨다.
foreach(var work in checkList.ToList())
{
if(work.Key == "ccc")
{
checkList.Remove("ccc");
}
}
위와 같이 TiList()를 통해 복사본을 만들고 원본 리스트만을 변경한다.
그렇기에 삭제하는 컬렉션과 탐색하는 컬렉션이 다르기 때문에 이터레이터의 영향을 받지 않는다.
List<int> numbers = new List<int>{1, 2, 3, 4};
numbers.RemoveAll(num => num == 3);
numbers와 같은 리스트의 같은 경우 foreach 이외의 방법을 사용하면 예외 사항이 발생하지 않는다.
RemoveAll는 내부적으로 for문을 이용한 탐색과 수정은 예외 사항이 발행하지 않는다.

위와 같이 정상적으로 요소가 삭제 되고 딕셔너리의 요소가 출력된다.
컬렉션을 순회하면서 수정을 할 경우에는 탐색하는 요소를 직접 수정/삭제하지 않고 ToList()를 사용하여 복사본을 만들어 원본의 탐색과 수정을 동시에 하지 않는 방법을 사용하도록 한다.