← C# 강의 목록으로
🟣
기초
기초 · 선수: 이전 단원

03. 연산자와 표현식

연산자는 값을 조합해 새로운 값을 만들어 냅니다. 산술·비교·논리·할당·증감·null 병합·삼항·비트 연산자를 한 단원에서 정리합니다.

C#.NET 8기초연산자
소요 시간
약 1~1.5시간
난이도
📊 초급
선수 조건
🎯 이전 단원 또는 동등 지식
결과물
연산자는 값을 조합해 새로운 값을 만들어 냅니다. 산술·비교·논리·할당·증감·null 병합·삼항·비트 연산자를 한 단원에서 정리합니다.

이 강의에서 배우는 것

  • 1산술/비교/논리 연산자의 우선순위를 안다
  • 2`int / int` 와 `double / int` 의 결과 차이를 이해한다
  • 3`&&` / `||` 의 **단락 평가(short-circuit)** 동작을 안다
  • 4`?.` `??` `??=` 로 null 을 안전하게 처리한다
  • 5`is` / `as` 로 타입 검사·변환을 한다
  • 6삼항 연산자 `?:` 로 표현식을 간결하게 쓴다

소개

연산자는 값을 가공하는 기본 도구입니다. C#은 일반적인 산술/비교/논리 외에도 **null 안전 연산자**, **패턴 매칭(`is`)**, **삼항 연산자(`?:`)** 같은 표현식 친화 기능이 풍부합니다.

핵심 개념

1) 산술 연산자

`+`, `-`, `*`, `/`, `%` 가 있습니다. 핵심은 **타입 규칙**입니다.

csharp
int x = 7 / 2;        // 3   (정수 나눗셈, 소수점 버림)
double y = 7 / 2;     // 3.0 (먼저 정수 나눗셈 후 double 변환)
double z = 7.0 / 2;   // 3.5 (한쪽이 double 이면 실수 나눗셈)
int r = 7 % 2;        // 1   (나머지)

2) 비교/논리 연산자

  • 비교: `==`, `!=`, `<`, `<=`, `>`, `>=` → `bool` 반환
  • 논리: `&&`(AND), `||`(OR), `!`(NOT)

**단락 평가(short-circuit)**: `&&` 는 왼쪽이 `false` 면 오른쪽을 안 본다. `||` 는 왼쪽이 `true` 면 오른쪽을 안 본다.

csharp
int? n = null;
if (n != null && n.Value > 0)   // n == null 이면 .Value 평가 안 됨
    Console.WriteLine("양수");

3) null-conditional `?.` 과 null-coalescing `??`, `??=`

  • `obj?.Member` : `obj` 가 `null` 이면 전체가 `null`, 아니면 `Member` 평가
  • `a ?? b` : `a` 가 `null` 이면 `b`
  • `a ??= b` : `a` 가 `null` 일 때만 `b` 대입
csharp
string? name = null;
int len = name?.Length ?? 0;          // null 이면 0
name ??= "(이름 없음)";               // null 일 때만 대입
Console.WriteLine($"{name} ({len})"); // (이름 없음) (0)

4) `is` 와 `as`

  • `obj is Type` : 타입이면 `true`, 패턴 매칭과 결합 가능
  • `obj as Type` : 캐스팅 실패 시 **예외 대신 `null`**
csharp
object o = "hello";
if (o is string s)                 // 타입 검사 + 변수 선언
    Console.WriteLine(s.Length);   // 5

object o2 = 42;
string? s2 = o2 as string;         // 캐스팅 실패 → s2 == null

5) 삼항 연산자 `?:`

"조건 ? 참값 : 거짓값" — 짧은 if-else 를 표현식으로.

csharp
int score = 75;
string grade = score >= 60 ? "합격" : "불합격";

핵심 예제

예제 1 — `Arithmetic/Program.cs` : 정수 vs 실수 나눗셈

csharp
int a = 7, b = 2;

Console.WriteLine($"{a} + {b} = {a + b}");
Console.WriteLine($"{a} - {b} = {a - b}");
Console.WriteLine($"{a} * {b} = {a * b}");
Console.WriteLine($"{a} / {b} = {a / b}          (정수 나눗셈)");
Console.WriteLine($"{a} % {b} = {a % b}");
Console.WriteLine($"(double)a / b = {(double)a / b}  (실수 나눗셈)");

**실행 결과**

text
7 + 2 = 9
7 - 2 = 5
7 * 2 = 14
7 / 2 = 3          (정수 나눗셈)
7 % 2 = 1
(double)a / b = 3.5  (실수 나눗셈)

**메모:** 한쪽만 `(double)` 로 캐스팅해도 결과가 `double` 이 됩니다.

예제 2 — `LogicalOps/Program.cs` : 단락 평가 시연

csharp
static bool Log(string label, bool value)
{
    Console.WriteLine($"  [{label} 평가됨 → {value}]");
    return value;
}

Console.WriteLine("(false && X) 결과:");
bool r1 = Log("A", false) && Log("B", true);
Console.WriteLine($"  => {r1}");

Console.WriteLine("(true || X) 결과:");
bool r2 = Log("C", true) || Log("D", false);
Console.WriteLine($"  => {r2}");

**실행 결과**

text
(false && X) 결과:
  [A 평가됨 → False]
  => False
(true || X) 결과:
  [C 평가됨 → True]
  => True

**메모:** `B`, `D` 는 평가되지 않습니다. 이게 단락 평가입니다.

예제 3 — `NullSafety/Program.cs` : `?.` `??` `??=`

csharp
string? name = null;

int len = name?.Length ?? 0;          // null 이면 0
Console.WriteLine($"길이: {len}");

name ??= "(이름 없음)";               // null 일 때만 대입
Console.WriteLine($"이름: {name}");

// 다시 한 번: 이제는 null 이 아니므로 변하지 않음
name ??= "또 다른 기본값";
Console.WriteLine($"최종: {name}");

**실행 결과**

text
길이: 0
이름: (이름 없음)
최종: (이름 없음)

**메모:** `?.` 는 null 일 때 **전체 식이 null** 이 됩니다. 그래서 `??` 와 짝꿍처럼 자주 씁니다.

예제 4 — `IsAs/Program.cs` : 타입 검사와 캐스팅

csharp
object[] items = ["hello", 42, 3.14, true];

foreach (object item in items)
{
    if (item is string s)
        Console.WriteLine($"문자열: '{s}' (길이 {s.Length})");
    else if (item is int n)
        Console.WriteLine($"정수: {n}");
    else
        Console.WriteLine($"기타: {item} ({item.GetType().Name})");
}

object boxed = 100;
string? wrong = boxed as string;      // 캐스팅 실패 → null
Console.WriteLine($"as 결과: {wrong ?? "(null)"}");

**실행 결과**

text
문자열: 'hello' (길이 5)
정수: 42
기타: 3.14 (Double)
기타: True (Boolean)
as 결과: (null)

**메모:** `is Type 변수` 패턴이 가장 깔끔합니다. `(string)boxed` 처럼 강제 캐스팅하면 실패 시 예외가 발생하니, 안전하게 가려면 `as` 또는 `is` 를 쓰세요.

전체 예제 코드 (src/)

src/Arithmetic/Arithmetic.csproj

xml
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <RootNamespace>CodingNow.Lecture.Basics03</RootNamespace>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>

src/Arithmetic/Program.cs

csharp
// 산술 연산자 - 정수 vs 실수 나눗셈
int a = 7, b = 2;

Console.WriteLine($"{a} + {b} = {a + b}");
Console.WriteLine($"{a} - {b} = {a - b}");
Console.WriteLine($"{a} * {b} = {a * b}");
Console.WriteLine($"{a} / {b} = {a / b}          (정수 나눗셈)");
Console.WriteLine($"{a} % {b} = {a % b}");
Console.WriteLine($"(double)a / b = {(double)a / b}  (실수 나눗셈)");

src/IsAs/IsAs.csproj

xml
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <RootNamespace>CodingNow.Lecture.Basics03</RootNamespace>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>

src/IsAs/Program.cs

csharp
// is / as 타입 검사·캐스팅
object[] items = ["hello", 42, 3.14, true];

foreach (object item in items)
{
    if (item is string s)
        Console.WriteLine($"문자열: '{s}' (길이 {s.Length})");
    else if (item is int n)
        Console.WriteLine($"정수: {n}");
    else
        Console.WriteLine($"기타: {item} ({item.GetType().Name})");
}

object boxed = 100;
string? wrong = boxed as string;      // 캐스팅 실패 → null
Console.WriteLine($"as 결과: {wrong ?? "(null)"}");

src/LogicalOps/LogicalOps.csproj

xml
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <RootNamespace>CodingNow.Lecture.Basics03</RootNamespace>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>

src/LogicalOps/Program.cs

csharp
// && / || 의 단락 평가 시연
static bool Log(string label, bool value)
{
    Console.WriteLine($"  [{label} 평가됨 → {value}]");
    return value;
}

Console.WriteLine("(false && X) 결과:");
bool r1 = Log("A", false) && Log("B", true);
Console.WriteLine($"  => {r1}");

Console.WriteLine("(true || X) 결과:");
bool r2 = Log("C", true) || Log("D", false);
Console.WriteLine($"  => {r2}");

src/NullSafety/NullSafety.csproj

xml
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <RootNamespace>CodingNow.Lecture.Basics03</RootNamespace>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>

src/NullSafety/Program.cs

csharp
// ?. ?? ??= 시연
string? name = null;

int len = name?.Length ?? 0;          // null 이면 0
Console.WriteLine($"길이: {len}");

name ??= "(이름 없음)";               // null 일 때만 대입
Console.WriteLine($"이름: {name}");

// 이미 값이 있으니 변하지 않음
name ??= "또 다른 기본값";
Console.WriteLine($"최종: {name}");

자주 하는 실수

  1. `7 / 2` 가 `3.5` 일 거라 기대 — 정수끼리는 정수 나눗셈.
  2. `if (count = 0)` 처럼 `=` 와 `==` 혼동 — C#은 `bool` 이 아닌 식을 `if` 에 넣을 수 없어 컴파일 에러가 나서 그나마 안전하지만 주의.
  3. `??` 와 `?:` 헷갈리기 — `??` 는 **null 여부**, `?:` 는 **일반 조건**.
  4. `as` 로 값 타입 캐스팅 — `as int` 는 불가, `as int?` 로 써야 함.
  5. `null` 인 객체에 `.` 으로 접근 → `NullReferenceException`. **항상 `?.` 고려**.

정리

  • 정수 나눗셈/실수 나눗셈을 구분한다
  • `&&`/`||` 의 단락 평가로 null 체크와 연쇄 검사를 안전하게
  • `?.` `??` `??=` 는 null 처리 3종 세트
  • `is`/`as` 로 타입을 안전하게 검사·변환
  • 삼항 `?:` 는 짧은 분기를 깔끔하게 표현

과제

**과제 - 03. 연산자와 표현식**

문제 1 — BMI 계산기

  • 프로젝트 폴더: `Homework01/`
  • 핵심 개념: `double` 연산, 비교 연산자, 문자열 보간 `:F2`

요구사항

  • 키(cm)와 몸무게(kg)를 입력받는다
  • BMI = `몸무게 / (키[m] × 키[m])` 으로 계산한다
  • 소수점 둘째 자리까지 출력한다 (`{bmi:F2}`)

예상 출력

text
키(cm): 172
몸무게(kg): 70
BMI: 23.66

힌트

  • cm 를 m 로 바꾸려면 `/ 100.0` (꼭 `100.0` 으로 — `double` 보장)
  • `double.Parse(Console.ReadLine()!)` 로 실수 입력

문제 2 — 짝수/홀수 판별 (삼항 연산자)

  • 프로젝트 폴더: `Homework02/`
  • 핵심 개념: `%`, 삼항 연산자 `?:`

요구사항

  • 정수 하나를 입력받는다
  • 삼항 연산자로 짝수/홀수를 판별해 출력한다
  • 0 을 입력하면 "0 은 짝수입니다" 라고 출력한다 (0 은 짝수로 처리)

예상 출력

text
정수: 7
7 은 홀수입니다.

힌트

  • `n % 2 == 0` 이면 짝수
  • `string result = ... ? "짝수" : "홀수";`

정답 확인

직접 풀어 본 후 [`answer/`](./answer/) 폴더의 정답과 비교해 보세요.

정답 (answer/)

homework/answer/Homework01/Homework01.csproj

xml
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <RootNamespace>CodingNow.Lecture.Basics03</RootNamespace>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>

homework/answer/Homework01/Program.cs

csharp
// BMI 계산기
Console.Write("키(cm): ");
double heightCm = double.Parse(Console.ReadLine()!);

Console.Write("몸무게(kg): ");
double weightKg = double.Parse(Console.ReadLine()!);

double heightM = heightCm / 100.0;
double bmi = weightKg / (heightM * heightM);

Console.WriteLine($"BMI: {bmi:F2}");

homework/answer/Homework02/Homework02.csproj

xml
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <RootNamespace>CodingNow.Lecture.Basics03</RootNamespace>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>

homework/answer/Homework02/Program.cs

csharp
// 짝수/홀수 판별 - 삼항 연산자
Console.Write("정수: ");
int n = int.Parse(Console.ReadLine()!);

string kind = n % 2 == 0 ? "짝수" : "홀수";
Console.WriteLine($"{n} 은 {kind}입니다.");

직접 해 보기

bash
cd src/Arithmetic && dotnet run
cd ../LogicalOps && dotnet run
cd ../NullSafety && dotnet run
cd ../IsAs && dotnet run

다음 단원

[04_제어문](../04_제어문/) — 조건과 반복으로 프로그램의 흐름을 제어합니다.

예제 코드 / 강의 자료

전체 강의 자료와 예제 코드는 GitHub에서 자유롭게 받아볼 수 있습니다.

GitHub에서 보기 ↗