Short-Circuit Evaluation
Short-Circuit Evaluation
단락 방식
대부분의 프로그래밍 언어에서는, 불 연산에 Short-Circuit Evaluation 이 적용된다.
위 그림처럼,
순서대로 연산하는 도중 이미 결과가 결정되는 경우,
굳이 남은 피연산자들까지 계산할 필요가 없기 때문에, 결과가 결정된 시점에서 계산을 마친다.
1
2
SomeObject a = null;
if (a != null && a.SomeFunc())
C# 에서 &&
은 Short-Circuit Evaluation 이 적용되기 때문에,
위 코드에서는 a != null
에서 계산이 끝나고, a.SomeFunc()
가 실행되지 않아 런타임 에러가 발생하지 않는다.
이런식으로 활용할 수 있다.
만약 Short-Circuit Evaluation 이 적용되지 않았다면,
위 코드에서 a
가 null
인채로 a.SomeFunc()
가 실행되어 NullReferenceException
이 발생했을 것이다.
1
2
3
4
5
6
7
8
9
// 1: 최소 1ms
if (takes1ms() || takes1s())
// 2: 최소 1s
if (takes1s() || takes1ms())
// a: 최소 O(1)
if (boolVariable || take1s())
// b: 최소 1s
if (takes1s() || boolVariable)
또, 만약 함수의 반환 값을 피연산자로 사용하는 경우,
상대적으로 비용이 높은 함수를 뒷쪽에 배치하여 시간 복잡도를 줄일 수도 있다.
1
2
if (false & SomeFunc())
if (true | SomeFunc())
반면, 결과와 상관없이 피연산자로 존재하는 모든 함수들을 실행시키고 싶은 경우가 있을 수 있다.
(예시가 딱 떠오르지는 않지만)
이 경우, C# 에서는 &
이나 |
를 사용할 수 있다.
&
와 |
는 비트 연산자로 쓰이기도 하지만, 불 연산 식에 사용될 경우, 불 논리 연산자로써 사용된다.
&
이나 |
를 불 논리 연산자로써 사용하면, 결과와 상관없이 모든 피연산자들을 계산한다.
때문에 위 두 줄의 코드는, 첫 번째 피연산자에서 이미 결과가 결정되어버리지만, 계산을 끝내지 않고 SomeFunc() 함수를 실행시킨다.
이때, 이런 &
와 |
를 &&
와 ||
에 구분지어,
Eager Operators (&
, |
) 와 Short-Circuit Operators (&&
, ||
) 로 부를 수 있다.
C# 튜플 비교 시, Short-Circuit Evaluation 이 적용된다.