C# - For 루프 패러독스
For 루프 패러독스
우선 for 루프 패러독스가 무엇입니까?
i
내에서 for 루프의 async Task
값을 사용할 때 발생합니다. 작업은 i
의 마지막 값만 사용하여 실행됩니다. for 루프가 매우 큰 경우 작업 중 일부가 중간 값을 얻을 수도 있습니다.
하지만 이 동작을 보여주는 몇 가지 코드를 살펴보겠습니다.
class Program
{
static async Task Main(string[] args)
{
var tasks = new List<Task>();
for (var i = 0; i <= 9; i++)
{
tasks.Add(Task.Run(() =>
{
Console.WriteLine(i);
}));
}
await Task.WhenAll(tasks.ToArray());
}
}
예상되는 결과는 0에서 9까지의 모든 값을 임의의 순서로 콘솔에 인쇄하는 것입니다. 이러한 값은 태스크이고 순서 지정이 보장되지 않기 때문입니다.
그러나 우리가 실제로 얻는 것을 보자:
흠... 뭔가 잘못되었습니다. 우리는 실제로 전혀 예상하지 못한 숫자 10만 인쇄하고 있습니다...
왜 이런 일이 발생합니까?
이것은 클로저의 일반적인 동작이며, 이 코드 조각은 다음과 같습니다.
tasks.Add(Task.Run(() =>
{
Console.WriteLine(i);
}));
실행 당시 i
의 값을 사용하고 있습니다.
Closures close over variables, not over values.
알겠습니다. 하지만 이 문제를 해결하는 방법은 무엇입니까?
수정은 매우 간단합니다. i
값을 새 변수에 할당하기만 하면 됩니다.
class Program
{
static async Task Main(string[] args)
{
var tasks = new List<Task>();
for (var i = 0; i <= 9; i++)
{
// work around for closure behavior
var j = i;
tasks.Add(Task.Run(() =>
{
// use the new j variable here
Console.WriteLine(j);
}));
}
await Task.WhenAll(tasks.ToArray());
}
}
이제 for 루프를 반복할 때마다 새 변수 j를 만듭니다. 각 클로저는 한 번만 할당되고 각 반복에서 i
변수의 올바른 현재 값을 유지하는 다른 j 변수에 대해 닫힙니다.
이제 콘솔에서 예상 결과를 얻습니다!
역사 수업 시작!
이 동작은 foreach
루프를 사용할 때도 발생했지만 C# 팀은 C# 5를 릴리스하고 이 동작을 "수정"할 때 주요 변경 사항을 적용했습니다.
그러나 for loop
에 대해서는 그대로 유지하기로 결정했습니다.
더 많은 리소스
C#의 클로저와 클로저를 유리하게 사용하는 방법에 대한 자세한 내용은 Jon SkeetThe Beauty of Closures의 문서에서 확인할 수 있습니다.
이 기사를 읽으면 디버그 시간을 절약할 수 있기를 바랍니다.
사랑을 담아 작성한 글입니다❤️
Reference
이 문제에 관하여(C# - For 루프 패러독스), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/rickystam/c-the-for-loop-paradox-2l1j
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
class Program
{
static async Task Main(string[] args)
{
var tasks = new List<Task>();
for (var i = 0; i <= 9; i++)
{
tasks.Add(Task.Run(() =>
{
Console.WriteLine(i);
}));
}
await Task.WhenAll(tasks.ToArray());
}
}
이것은 클로저의 일반적인 동작이며, 이 코드 조각은 다음과 같습니다.
tasks.Add(Task.Run(() =>
{
Console.WriteLine(i);
}));
실행 당시
i
의 값을 사용하고 있습니다.Closures close over variables, not over values.
알겠습니다. 하지만 이 문제를 해결하는 방법은 무엇입니까?
수정은 매우 간단합니다. i
값을 새 변수에 할당하기만 하면 됩니다.
class Program
{
static async Task Main(string[] args)
{
var tasks = new List<Task>();
for (var i = 0; i <= 9; i++)
{
// work around for closure behavior
var j = i;
tasks.Add(Task.Run(() =>
{
// use the new j variable here
Console.WriteLine(j);
}));
}
await Task.WhenAll(tasks.ToArray());
}
}
이제 for 루프를 반복할 때마다 새 변수 j를 만듭니다. 각 클로저는 한 번만 할당되고 각 반복에서 i
변수의 올바른 현재 값을 유지하는 다른 j 변수에 대해 닫힙니다.
이제 콘솔에서 예상 결과를 얻습니다!
역사 수업 시작!
이 동작은 foreach
루프를 사용할 때도 발생했지만 C# 팀은 C# 5를 릴리스하고 이 동작을 "수정"할 때 주요 변경 사항을 적용했습니다.
그러나 for loop
에 대해서는 그대로 유지하기로 결정했습니다.
더 많은 리소스
C#의 클로저와 클로저를 유리하게 사용하는 방법에 대한 자세한 내용은 Jon SkeetThe Beauty of Closures의 문서에서 확인할 수 있습니다.
이 기사를 읽으면 디버그 시간을 절약할 수 있기를 바랍니다.
사랑을 담아 작성한 글입니다❤️
Reference
이 문제에 관하여(C# - For 루프 패러독스), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/rickystam/c-the-for-loop-paradox-2l1j
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
class Program
{
static async Task Main(string[] args)
{
var tasks = new List<Task>();
for (var i = 0; i <= 9; i++)
{
// work around for closure behavior
var j = i;
tasks.Add(Task.Run(() =>
{
// use the new j variable here
Console.WriteLine(j);
}));
}
await Task.WhenAll(tasks.ToArray());
}
}
이 동작은
foreach
루프를 사용할 때도 발생했지만 C# 팀은 C# 5를 릴리스하고 이 동작을 "수정"할 때 주요 변경 사항을 적용했습니다.그러나
for loop
에 대해서는 그대로 유지하기로 결정했습니다.더 많은 리소스
C#의 클로저와 클로저를 유리하게 사용하는 방법에 대한 자세한 내용은 Jon SkeetThe Beauty of Closures의 문서에서 확인할 수 있습니다.
이 기사를 읽으면 디버그 시간을 절약할 수 있기를 바랍니다.
사랑을 담아 작성한 글입니다❤️
Reference
이 문제에 관하여(C# - For 루프 패러독스), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/rickystam/c-the-for-loop-paradox-2l1j
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
Reference
이 문제에 관하여(C# - For 루프 패러독스), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/rickystam/c-the-for-loop-paradox-2l1j텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)