[C#] ?. , ?? , ??= : null 처리 연산자

[C#] ?. , ?? , ??= : null 처리 연산자

안녕하세요. 이번 글에서는 C#의 null 처리 연산자인 ?., ??, ??=에 대해 알아보겠습니다.

null 검사를 위한 if 문이 겹겹이 쌓이면 코드가 길어지고 읽기 어려워집니다. 세 연산자를 사용하면 null 검사를 한 줄로 줄일 수 있습니다.

한눈에 보기

연산자이름동작
?.null 조건 연산자왼쪽이 null이면 멤버 접근을 건너뛰고 null 반환
??null 병합 연산자왼쪽이 null이면 오른쪽 값 사용
??=null 병합 할당 연산자왼쪽이 null일 때만 오른쪽 값 할당 (C# 8.0)

예제 코드

using System;

class Person
{
    public string Name { get; set; }
    public Address Address { get; set; }
}

class Address
{
    public string City { get; set; }
}

class Program
{
    static void Main()
    {
        Person p = new Person();

        // before : null 검사 중첩
        string city1 = null;
        if (p != null && p.Address != null)
            city1 = p.Address.City;

        // after : ?. 사용
        string city2 = p?.Address?.City;

        // ?? : 기본값 지정
        string name = p.Name ?? "이름 없음";

        // ??= : null일 때만 할당
        p.Name ??= "Guest";
        p.Name ??= "Other";   // 이미 값이 있으므로 변경되지 않음

        Console.WriteLine(city2 ?? "city is null");
        Console.WriteLine(name);
        Console.WriteLine(p.Name);
    }
}

실행 결과는 다음과 같습니다.

city is null
이름 없음
Guest

활용과 주의할 점

  • 배열·컬렉션에는 ?[ ]를 씁니다. list?[0]
  • 이벤트 호출은 Changed?.Invoke(this, e) 형태로 null 검사와 호출을 함께 처리합니다.
  • 값 형식에 ?.를 쓰면 결과가 nullable이 됩니다. int? len = str?.Length;
  • ?? throw 형태로 필수 값을 검사할 수 있습니다. var v = arg ?? throw new ArgumentNullException(nameof(arg));
  • ?.는 null일 때 뒤쪽 호출 전체를 건너뛰지만, 그 결과를 다시 쓰는 곳에서는 null이 될 수 있다는 점을 잊으면 안 됩니다.

정리

  • ?. : null이면 접근하지 않고 null 반환
  • ?? : null이면 대체값 사용
  • ??= : null일 때만 할당

이상으로 C#의 null 처리 연산자에 대해 간단히 알아보았습니다.

참고(References)