왜 목록.ForEach는 목록 수정을 허용합니까?
내가 사용하는 경우 :
var strings = new List<string> { "sample" };
foreach (string s in strings)
{
Console.WriteLine(s);
strings.Add(s + "!");
}
Add
의는 foreach
우리가 우리의 발 아래에서 양탄자를 당겨 때문에 나는, 논리적 생각하는 (열거 작업이 실행되지 않을 수 있습니다 컬렉션이 수정 된) InvalidOperationException이 발생합니다.
그러나 다음을 사용하는 경우 :
var strings = new List<string> { "sample" };
strings.ForEach(s =>
{
Console.WriteLine(s);
strings.Add(s + "!");
});
OutOfMemoryException이 발생할 때까지 반복하여 즉시 발에 자신을 쏘습니다.
난 항상 List.ForEach가 중 단지 래퍼라고 생각 이것은, 나에게 깜짝 온다 foreach
또는 위해 for
.
이 행동의 방법과 이유에 대한 설명이있는 사람이 있습니까?
( 끝없이 반복되는 Generic List에 대한 ForEach 루프에서 영감을 얻음 )
때문입니다 ForEach
열거를 사용하지 않는 방법은, 그것은을 가진 항목을 통해 루프 for
루프 :
public void ForEach(Action<T> action)
{
if (action == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
}
for (int i = 0; i < this._size; i++)
{
action(this._items[i]);
}
}
(JustDecompile로 얻은 코드)
열거자를 사용하지 않기 때문에 목록이 변경되었는지 확인 for
하지 않으며 _size
반복 할 때마다 증가 하므로 루프 의 끝 조건에 도달하지 않습니다 .
List<T>.ForEach
for
내부를 통해 구현 되므로 열거자를 사용하지 않고 컬렉션을 수정할 수 있습니다.
List 클래스에 연결된 ForEach는 내부적으로 내부 멤버에 직접 연결된 for 루프를 사용하기 때문에 .NET 프레임 워크의 소스 코드를 다운로드하여 확인할 수 있습니다.
http://referencesource.microsoft.com/netframework.aspx
foreach 루프가 무엇보다도 컴파일러 최적화이지만 관찰자로서 컬렉션에 대해 작동해야하는 경우-컬렉션이 수정되면 예외가 발생합니다.
우리는이 문제에 대해 알고 있으며 원래 작성되었을 때 감독이었습니다. 안타깝게도 이전에 작동하던 코드가 실행되지 않도록 할 수 있으므로 변경할 수 없습니다.
var list = new List<string>();
list.Add("Foo");
list.Add("Bar");
list.ForEach((item) =>
{
if(item=="Foo")
list.Remove(item);
});
Eric Lippert가 지적 했듯이이 방법 자체의 유용성은 의심 스럽기 때문에 Metro 스타일 앱 (예 : Windows 8 앱) 용 .NET에는 포함하지 않았습니다.
David Kean (BCL 팀)
참고 URL : https://stackoverflow.com/questions/9311730/why-does-listt-foreach-allow-its-list-to-be-modified
'program tip' 카테고리의 다른 글
클래스 다이어그램을 만들기위한 도구 (0) | 2020.09.04 |
---|---|
사용하지 않는 함수 매개 변수 값을 void로 캐스팅하는 이유는 무엇입니까? (0) | 2020.09.04 |
CSS 입력 유형 선택기- "or"또는 "not"구문을 사용할 수 있습니까? (0) | 2020.09.03 |
장고 프레임 워크의 양식 필드에서 값을 얻는 방법은 무엇입니까? (0) | 2020.09.03 |
ffmpeg로 프레임 수 가져 오기 (0) | 2020.09.03 |