C# 연산자와 식

C# 연산자와 식

C#은 아주 많은 연산자를 제공해요. 기본 제공 형식이 이 연산자들을 대부분 지원하기 때문에, 그 형식의 값만으로도 기본적인 연산을 해낼 수 있습니다.

출처: C# operators and expressions

본문

이 연산자들은 크게 다음 그룹으로 나뉘어요.

보통 이 연산자들은 오버로드할 수 있어요. 연산자를 오버로드하면 사용자 정의 형식의 피연산자에 대해 그 연산자가 어떻게 동작할지 직접 정해 줄 수 있습니다.

가장 단순한 C# 식은 리터럴(예컨대 정수실수 숫자)과 변수 이름이에요. 여기에 연산자를 쓰면 이들을 더 복잡한 식으로 묶을 수 있습니다. 식 안에서 연산이 어떤 순서로 수행되는지는 연산자의 우선 순위결합성이 정해 줍니다. 그리고 괄호를 쓰면 연산자 우선 순위와 결합성이 부과한 평가 순서를 바꿀 수 있어요.

아래 코드에서는 대입의 오른쪽에 식이 나타나는 예시를 보여 줍니다.

:::code language="csharp" source="snippets/shared/Overview.cs" id="Expressions":::

식은 보통 결과를 만들어 내고, 그래서 다른 식 안에도 들어갈 수 있어요. void 메서드 호출은 결과를 만들어 내지 않는 식의 예입니다. 그런 식은 아래 예시처럼 문(statement)으로만 쓸 수 있습니다.

Console.WriteLine("Hello, world!");

C#이 제공하는 다른 종류의 식도 있어요.

  • 형식화된 문자열을 만드는 간편한 구문을 제공하는 보간 문자열 식:

    :::code language="csharp" source="snippets/shared/Overview.cs" id="InterpolatedString":::

  • 익명 함수를 만들 수 있게 해 주는 람다 식:

    :::code language="csharp" source="snippets/shared/Overview.cs" id="Lambda":::

  • C# 안에서 바로 쿼리 기능을 사용할 수 있게 해 주는 쿼리 식:

    :::code language="csharp" source="snippets/shared/Overview.cs" id="Query":::

메서드, 생성자, 속성, 인덱서, 종료자에 대해 간결한 정의를 만들려면 식 본문 정의를 쓰면 돼요.

연산자 우선 순위

여러 연산자가 들어 있는 식에서는, 우선 순위가 높은 연산자가 낮은 연산자보다 먼저 평가돼요. 우선 순위가 같은 연산자는 어휘적 순서대로 평가됩니다. 아래 예시의 곱셈은 덧셈보다 우선 순위가 높기 때문에 먼저 수행돼요.

var a = 2 + 2 * 2;
Console.WriteLine(a); //  output: 6

연산자 우선 순위가 부과한 평가 순서를 바꾸려면 괄호를 쓰세요.

var a = (2 + 2) * 2;
Console.WriteLine(a); //  output: 8

아래 표는 C# 연산자를 우선 순위가 가장 높은 것부터 가장 낮은 것 순서로 나열한 거예요. 각 행 안의 연산자들은 서로 같은 우선 순위를 가집니다.

연산자 범주 또는 이름
x.y, f(x), a[i], x?.y, x?[y], x++, x--, x!, new, typeof, checked, unchecked, default, nameof, delegate, sizeof, stackalloc, x->y 기본(Primary)
+x, -x, !x, ~x, ++x, --x, ^x, (T)x, await, &x, *x, true and false 단항(Unary)
x..y 범위(Range)
switch, with switchwith
x * y, x / y, x % y 곱셈(Multiplicative)
x + y, x – y 덧셈(Additive)
x << y, x >> y, x >>> y 시프트(Shift)
x < y, x > y, x <= y, x >= y, is, as 관계 및 형식 테스트(Relational and type-testing)
x == y, x != y 같음(Equality)
x & y 부울 논리 AND 또는 비트 논리 AND
x ^ y 부울 논리 XOR 또는 비트 논리 XOR
x | y 부울 논리 OR 또는 비트 논리 OR
x && y 조건부 AND(Conditional AND)
x || y 조건부 OR(Conditional OR)
x ?? y Null 병합 연산자
c ? t : f 조건 연산자
x = y, x += y, x -= y, x *= y, x /= y, x %= y, x &= y, x |= y, x ^= y, x <<= y, x >>= y, x >>>= y, x ??= y, => 대입 및 람다 선언(Assignment and lambda declaration)

논리 패턴 결합자의 우선 순위에 대한 정보는 패턴 문서의 논리 패턴의 우선 순위 및 확인 순서 섹션을 참고하세요.

연산자 결합성

연산자들의 우선 순위가 같을 때는, 결합성이 연산이 수행되는 순서를 정해 줍니다.

  • 왼쪽 결합 연산자는 왼쪽에서 오른쪽 순서로 평가돼요. 대입 연산자null 병합 연산자를 제외한 모든 이항 연산자가 왼쪽 결합입니다. 예를 들어 a + b - c(a + b) - c로 평가됩니다.
  • 오른쪽 결합 연산자는 오른쪽에서 왼쪽 순서로 평가돼요. 대입 연산자, null 병합 연산자, 람다, 조건 연산자 ?:가 오른쪽 결합입니다. 예를 들어 x = y = zx = (y = z)로 평가됩니다.

[!IMPORTANT] P?.A0?.A1 형태의 식에서 Pnull이면 A0A1도 평가되지 않아요. 마찬가지로 P?.A0.A1 형태의 식에서는, P가 null일 때 A0가 평가되지 않으므로 A0.A1도 평가되지 않습니다. 더 자세한 내용은 C# 언어 사양을 참고하세요.

괄호를 쓰면 연산자 결합성이 부과한 평가 순서를 바꿀 수 있어요.

int a = 13 / 5 / 2;
int b = 13 / (5 / 2);
Console.WriteLine($"a = {a}, b = {b}");  // output: a = 1, b = 6

피연산자 평가

연산자 우선 순위나 결합성과는 별개로, 식 안의 피연산자는 왼쪽에서 오른쪽으로 평가돼요. 아래 예시들은 연산자와 피연산자가 평가되는 순서를 보여 줍니다.

평가 순서
a + b a, b, +
a + b * c a, b, c, *, +
a / b + c * d a, b, /, c, d, *, +
a / (b + c) * d a, b, c, +, /, d, *

보통 모든 연산자의 피연산자가 평가돼요. 다만 어떤 연산자는 피연산자를 조건적으로 평가합니다. 그 조건이란, 그런 연산자의 맨 왼쪽 피연산자의 값이 다른 피연산자들을 평가할지(또는 어느 것을 평가할지)를 정한다는 뜻이에요. 이런 연산자로는 조건부 논리 AND(&&)OR(||), null 병합 연산자 ????=, null 조건부 연산자 ?.?[], 조건 연산자 ?:가 있습니다. 더 자세한 내용은 각 연산자의 설명을 참고하세요.

C# 언어 사양

더 자세한 내용은 C# 언어 사양의 다음 섹션을 참고하세요.

더 알아보기