방프리
21.09.18 Chapter4. LINQ 활용 (Item 41) 본문
Item 41 : 값비싼 리소스를 캡처하지 말라
처음으로 C#에서 클로저라는 단어를 들었다. Swift에서 사용되는 클로저와 비슷한 느낌인데
간단히 풀어서 람다 표현식이 동작하는 메서드의 지역변수를 람다 표현식에서 사용하면 클로저라고 한다.
클로저는 예시로 보는게 더 이해가 쉬울 것 같다.
public void DoSomething()
{
int localVariable = 0;
Action<int> operatorLambda = delegate(int value)
{
int result = localVariable + value;
}
}
이 클로저는 대표적으로 LINQ에서 자주 사용된다고 한다.
해당 주제는 이 클로저를 사용할 때 문제가 발생하는 것에 대해 지적한다.
보통 개발자들은 로직을 만들 때 지역변수는 해당 블록을 벗어나면 자연스럽게 소멸되거나, 가비지 컬렉터로
이동한다고 생각한다. 하지만 클로저는 조금 예외이다. 어느 영역에서 반환하느냐에 따라 소멸 시기가 다르기 때문이다.
소멸 시기가 다르다보니 파일 스트림을 사용 후 닫는 코드는 넣는 시점을 개발자가 알기 어렵다.
이에 따라 메모리 누수 또는 파일스트림이 닫힌 후에도 리소스에 접근하려는 코드가 생길 수 있다.
그렇다면 Dispose가 호출되는 시점에서 파일스트림을 닫으면 어떻게 될까?
public IEnumerable<int> SomeFunction()
{
using (Generator g = new Generator())
{
while (true)
{
yield return g.GetNextNumber();
}
}
}
var query = (from n in SomeFunction()
select n).Take(5);
foreach (var s in query)
{
Console.WriteLine(s);
}
WriteLine("Again");
foreach (var s in query)
{
WriteLine(s);
}
// result
// 0
// 1
// 2
// 3
// 4
// Disposing now
// Again
// 0
// 1
// 2
// 3
// 4
// Disposing now
분명 Dispose가 한 번만 출력될거라 생각하지만 그렇지 않다. 그렇기 때문에 저자는 클로저를 사용할 때
특히 무거운 리소스를 관리하는 객체라면 어느 시점에서 해제가 진행되어야 하는지? 그리고 클로저를 사용할 땐
변수를 제대로 정리하는지 확인한 상태에서 사용해야 한다고 주의를 주고 있다.
'C# > Effective C#' 카테고리의 다른 글
21.09.18 Chapter4. LINQ 활용 (Item 43) (0) | 2021.09.18 |
---|---|
21.09.18 Chapter4. LINQ 활용 (Item 42) (0) | 2021.09.18 |
21.09.06 Chapter4. LINQ 활용 (Item 40) (0) | 2021.09.14 |
21.09.04 Chapter4. LINQ 활용 (Item 39) (0) | 2021.09.04 |
21.09.01 Chapter4. LINQ 활용 (Item 38) (0) | 2021.09.03 |
Comments