true 연산자와 false 연산자 — 객체를 Boolean 값처럼 다루기
true 연산자와 false 연산자 — 객체를 Boolean 값처럼 다루기
C#에는 객체가 '참(true)' 인지 '거짓(false)' 인지를 물어볼 때 쓰는 true 연산자와 false 연산자가 있어요. 이 두 연산자를 오버로드하면 여러분이 만든 타입을 Boolean 값처럼 다룰 수 있는데요, 오늘은 이 연산자가 어떤 의미를 갖고 어떻게 활용되는지를 차근차근 살펴볼게요.
출처: Microsoft Learn
본문
true 연산자는 피연산자가 확실히 참(true) 임을 나타낼 때 bool 값 true를 돌려줍니다. 반대로 false 연산자는 피연산자가 확실히 거짓(false) 임을 나타낼 때 bool 값 true를 돌려줘요. 여기서 조금 헷갈릴 수 있는데요, false 연산자가 "거짓이다"라고 답할 때 false가 아니라 true를 반환한다는 점을 기억해 두세요. 즉 두 연산자 모두 "예, 맞습니다"라고 대답하는 상황이면 true를 반환하는 방식이에요.
[!INCLUDEcsharp-version-note]
true 연산자와 false 연산자를 둘 다 구현하는 타입은 다음 의미를 따라야 합니다.
- "이 객체는 참인가?"라는 질문은
true연산자로 해결됩니다. 객체가 참이라면true연산자가true를 반환해서, "네, 이 객체는 참입니다"라고 대답하는 거죠. - "이 객체는 거짓인가?"라는 질문은
false연산자로 해결됩니다. 객체가 거짓이라면false연산자가true를 반환해서, "네, 이 객체는 거짓입니다"라고 대답합니다.
여기서 꼭 알아두셔야 할 점이 있어요. true 연산자와 false 연산자는 서로 보완 관계가 보장되지 않습니다. 즉 같은 피연산자에 대해 true 연산자와 false 연산자가 둘 다 bool 값 false를 반환할 수도 있어요. 그리고 이 두 연산자 중 하나만 정의할 수는 없고, 하나를 정의하면 반드시 다른 하나도 함께 정의해야 합니다.
[!TIP] 3값 논리(three-valued logic)를 지원해야 한다면 — 예를 들어 3값 Boolean 타입을 지원하는 데이터베이스를 다룰 때처럼요 —
bool?타입을 사용하는 게 좋습니다. C#은bool?피연산자에 대해 3값 논리를 지원하는&연산자와|연산자를 제공해요. 자세한 내용은 Boolean 논리 연산자 문서의 Nullable Boolean 논리 연산자 섹션을 참고하세요.
Boolean 식
true 연산자가 정의된 타입은 제어 흐름을 결정하는 조건식의 결과 타입이 될 수 있어요. 구체적으로는 if 문, do 문, while 문, for 문에서, 그리고 조건 연산자 ?:에서 그 타입을 조건식으로 쓸 수 있어요. 자세한 내용은 C# 언어 사양의 Boolean 식 섹션을 참고하세요.
사용자 정의 조건부 논리 연산자
true 연산자와 false 연산자가 모두 정의된 타입이 논리 OR 연산자 | 또는 논리 AND 연산자 &를 오버로드하면, 그 타입의 피연산자에 대해 각각 조건부 논리 OR 연산자 || 또는 조건부 논리 AND 연산자 &&를 평가할 수 있게 됩니다. 자세한 내용은 C# 언어 사양의 사용자 정의 조건부 논리 연산자 섹션을 참고하세요.
예제
다음 예제는 true 연산자와 false 연산자를 모두 정의한 타입을 보여줍니다. 이 타입은 논리 AND 연산자 &도 오버로드하는데, 그 덕분에 이 타입의 피연산자에 대해 && 연산자도 평가할 수 있어요.
public struct LaunchStatus
{
public static readonly LaunchStatus Green = new LaunchStatus(0);
public static readonly LaunchStatus Yellow = new LaunchStatus(1);
public static readonly LaunchStatus Red = new LaunchStatus(2);
private int status;
private LaunchStatus(int status)
{
this.status = status;
}
public static bool operator true(LaunchStatus x) => x == Green || x == Yellow;
public static bool operator false(LaunchStatus x) => x == Red;
public static LaunchStatus operator &(LaunchStatus x, LaunchStatus y)
{
if (x == Red || y == Red || (x == Yellow && y == Yellow))
{
return Red;
}
if (x == Yellow || y == Yellow)
{
return Yellow;
}
return Green;
}
public static bool operator ==(LaunchStatus x, LaunchStatus y) => x.status == y.status;
public static bool operator !=(LaunchStatus x, LaunchStatus y) => !(x == y);
public override bool Equals(object obj) => obj is LaunchStatus other && this == other;
public override int GetHashCode() => status;
}
public class LaunchStatusTest
{
public static void Main()
{
LaunchStatus okToLaunch = GetFuelLaunchStatus() && GetNavigationLaunchStatus();
Console.WriteLine(okToLaunch ? "Ready to go!" : "Wait!");
}
static LaunchStatus GetFuelLaunchStatus()
{
Console.WriteLine("Getting fuel launch status...");
return LaunchStatus.Red;
}
static LaunchStatus GetNavigationLaunchStatus()
{
Console.WriteLine("Getting navigation launch status...");
return LaunchStatus.Yellow;
}
}
이 예제에서 && 연산자의 단락(short-circuit) 동작을 눈여겨보세요. GetFuelLaunchStatus 메서드가 LaunchStatus.Red를 반환하면 && 연산자의 오른쪽 피연산자는 평가되지 않습니다. 그 조건은 확실히 거짓이고, 논리 AND의 결과는 오른쪽 피연산자의 값에 의존하지 않기 때문이에요. 위 예제의 출력 결과는 다음과 같습니다.
Getting fuel launch status...
Wait!