방프리
21.09.19 Chapter4. LINQ 활용 (Item 44) 본문
Item 44 : 바인딩된 변수는 수정하지 말라
이번에도 클로저를 사용했을 때의 경우 유의해야하는 부분이다.
쿼리문을 실행하면서 지역 변수라든지 이미 클로저에서 캡쳐된 변수를 수정하는 코드를 넣을 수도 있는데
이는 컴파일러가 어떻게 동작을 할 것인지 결정에 따라 동작 방식이 크게 차이가 난다.
public class ModFilter
{
private readonly int modulus;
public ModFilter(int mod)
{
modulus = mod;
}
public IEnumerable<int> FindValues(IEnumerable<int> sequence)
{
int numValues = 0;
return from n in sequence
where n % modulus == 0
select n * n / ++numValues;
}
}
위의 코드를 컴파일러는 다음과 비슷한 코드로 동작한다.
public class ModFilter
{
private sealed class Closure
{
public ModFilter outer;
public int numValues;
public int SelectClause(int n) => ((n * n) / ++this.numValues);
}
private readonly int modulus;
public ModFilter(int mod)
{
this.modulus = mod;
}
private bool WhereClause(int n) => ((n % this.modulus) == 0);
public IEnumerable<int> FindValues(IEnumerable<int> sequence)
{
var c = new Closure();
c.outer = this;
c.numValues = 0;
return sequence.Where<int>(
new Func<int, bool>(this.WhereClause))
.Select<int, int>(
new Func<int, int>(c.SelectClause));
}
}
하단의 코드를 보면 컴파일러가 람다 표현식 내에서 사용하는 모든 지역변수를 포함하는 중첩 클래스를
생성한다는 것을 알 수 있다.
실제로 람다 표현식 내에서 사용된 모든 지역변수들은 중첩 클래스 내의 필드로 대체된다.
여러 개의 쿼리를 연달아 수행할 때 바인딩된 변수의 값을 수정하면 앞서 말한 것처럼 컴파일러의 동작 방식에 따라
문제가 발생될 수도 있다. 그러기에 바인딩된 변수는 수정하지 않는 것이 좋다.
'C# > Effective C#' 카테고리의 다른 글
21.09.24 Chapter5. 예외처리 (Item 46) (0) | 2021.09.24 |
---|---|
21.09.19 Chapter5. 예외처리 (Item 45) (0) | 2021.09.19 |
21.09.18 Chapter4. LINQ 활용 (Item 43) (0) | 2021.09.18 |
21.09.18 Chapter4. LINQ 활용 (Item 42) (0) | 2021.09.18 |
21.09.18 Chapter4. LINQ 활용 (Item 41) (0) | 2021.09.18 |
Comments