0Pricing
C# Academy · 강의

주석: ?, !, MaybeNull과 NotNull

nullable 형식에는 ?, null 용서에는 !를 사용하고 정확한 흐름 분석에는 MaybeNull 및 NotNullWhen 같은 특성을 사용합니다.

주석: ?, !, MaybeNull과 NotNull은(는) CoddyKit의 무료 C# Academy 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 C# Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. C# Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

?와 !를 넘어서: Nullability 특성

기본적인 ? 주석과 null 확인만으로 대부분의 경우를 처리할 수 있지만, 일부 패턴에는 더 표현력이 높은 주석이 필요합니다. System.Diagnostics.CodeAnalysis 네임스페이스는 컴파일러가 null 흐름을 더 깊이 이해하도록 돕는 특성을 제공합니다.

MaybeNull과 NotNull

[MaybeNull]은 null 비허용 반환 형식이 실제로는 null일 수 있음을 컴파일러에 알립니다(예: 제네릭 메서드). [NotNull]은 호출 후 null 허용 매개 변수가 null이 아님을 보장합니다.

using System.Diagnostics.CodeAnalysis;

// [MaybeNull]: return might be null even though T is non-nullable
[return: MaybeNull]
public T Find<T>(int id)
{
    // Returns default(T) which is null for reference types
    return _cache.TryGetValue(id, out var val) ? val : default!;
}

// [NotNull]: after this call, output is guaranteed non-null
public static void EnsureNotNull<T>(
    [NotNull] ref T? value,
    T defaultValue) where T : class
{
    value ??= defaultValue;
}

NotNullWhen: 조건부 null 비허용

[NotNullWhen(true)]은 메서드가 true를 반환할 때 출력 매개 변수가 null이 아님을 컴파일러에 알립니다. 표준 TryParse 패턴에 이 방식의 주석이 사용됩니다.

using System.Diagnostics.CodeAnalysis;

public static bool TryParseEmail(
    string? input,
    [NotNullWhen(true)] out string? email)
{
    if (input?.Contains('@') == true)
    {
        email = input.Trim().ToLower();
        return true;
    }
    email = null;
    return false;
}

// Usage — no warning after true check:
if (TryParseEmail(raw, out var email))
    Console.WriteLine(email.Length); // safe — email is non-null here

MaybeNullWhen: 조건부 null 허용

[MaybeNullWhen(false)]은 그 반대의 의미로, 메서드가 false를 반환할 때 출력 값이 null일 수 있음을 나타냅니다. 사전의 TryGetValue 패턴에 사용됩니다.

// This is how Dictionary<K,V>.TryGetValue is annotated:
public bool TryGetValue(
    TKey key,
    [MaybeNullWhen(false)] out TValue value)
{ ... }

// Usage:
if (!dict.TryGetValue("key", out var value))
    return; // early return — value is null in this branch

Console.WriteLine(value.Length); // safe after the guard

AllowNull과 DisallowNull

null 비허용 속성에 [AllowNull]을 지정하면 호출자가 해당 속성에 null을 전달할 수 있습니다(예: null을 빈 문자열로 변환하는 설정자). [DisallowNull]은 null 허용 형식에 null을 전달하지 못하도록 합니다.

public class Config
{
    private string _name = "";

    // Allow setting null (setter converts null -> empty)
    [AllowNull]
    public string Name
    {
        get => _name;
        set => _name = value ?? "";
    }

    // Getter always returns non-null: fine
    // Setter accepts null: [AllowNull] tells compiler that's OK
}

NotNullIfNotNull: null 허용성 전파

[NotNullIfNotNull(paramName)]은 매개 변수 X가 null이 아니면 반환 값도 null이 아님을 의미합니다. 변환 함수에 유용합니다.

[return: NotNullIfNotNull(nameof(value))]
public static string? Normalize(string? value)
{
    return value?.Trim().ToLower();
}

// Usage:
string  name = "  Alice  ";
string  norm1 = Normalize(name)!; // guaranteed non-null
string? raw   = GetRaw();
string? norm2 = Normalize(raw);   // still nullable (raw might be null)

DoesNotReturn

[DoesNotReturn]은 항상 예외를 발생시키는 메서드를 표시합니다. 컴파일러는 호출 뒤의 코드에 도달할 수 없음을 알고 불필요한 null 경고를 억제합니다.

using System.Diagnostics.CodeAnalysis;

[DoesNotReturn]
public static void ThrowNotFound(int id)
    => throw new KeyNotFoundException($"Entity {id} not found");

// Usage — no null warning after the call:
var order = _db.Orders.Find(id);
if (order is null) ThrowNotFound(id);

Console.WriteLine(order.Id); // no CS8602 — compiler knows ThrowNotFound threw

MemberNotNull: 필드에 대한 사후 조건

[MemberNotNull]은 메서드가 반환된 후 특정 필드가 null이 아님을 보장한다고 컴파일러에 알립니다. 지연 초기화 도우미에 유용합니다.

public class DataLoader
{
    private string? _data;

    [MemberNotNull(nameof(_data))]
    private void EnsureLoaded()
    {
        if (_data is null)
            _data = LoadFromFile();
    }

    public string GetData()
    {
        EnsureLoaded();
        return _data; // no CS8603 — compiler knows _data is set
    }
}

주석 조합하기

정확한 API 계약을 위해 특성을 조합할 수 있습니다. 다음은 여러 특성을 조합한 연속 호출형 검사 도우미입니다.

public static class Guard
{
    [return: NotNull]
    public static T NotNull<T>(
        [NotNull][AllowNull] T? value,
        [CallerArgumentExpression(nameof(value))] string? name = null)
        where T : class
    {
        ArgumentNullException.ThrowIfNull(value, name);
        return value;
    }
}

// Usage:
var product = Guard.NotNull(await _repo.FindAsync(id));
Console.WriteLine(product.Name); // no warning

null 연산자: ?. ?? ??=

null 조건부 연산자(?.), null 병합 연산자(??), null 병합 할당 연산자(??=)를 사용하면 장황한 if 확인 없이 간결하고 null에 안전한 코드를 작성할 수 있습니다.

string? name = GetName();

// ?. safe navigation
int? len = name?.Length;
string? upper = name?.ToUpper().Trim();

// ?? default value
string display = name ?? "Anonymous";

// ??= lazy init
name ??= "Default";

// Chaining
string result = user?.Profile?.DisplayName ?? user?.Name ?? "Guest";

빠른 확인

out 매개 변수에 [NotNullWhen(true)]를 지정하면 컴파일러에 무엇을 알립니까?

복습: Nullability 주석

핵심 요점:

  • [NotNullWhen(true)]: TryParse 패턴으로, true를 반환하면 null이 아님
  • [MaybeNull]: null 비허용 형식도 null을 반환할 수 있음(제네릭 기본값)
  • [DoesNotReturn]: 메서드가 항상 예외를 발생시키므로 뒤의 코드는 실행되지 않음
  • [MemberNotNull]: 메서드가 반환된 후 필드가 설정되어 있음을 보장
  • ?., ??, ??=: 간결하고 null에 안전한 탐색 및 기본값 처리

자주 묻는 질문

“주석: ?, !, MaybeNull과 NotNull” 강의는 무료인가요?

네 — “주석: ?, !, MaybeNull과 NotNull” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 C# Academy 강의 전체를 잠금 해제할 수 있습니다. C# Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“주석: ?, !, MaybeNull과 NotNull”에서 뭘 배우나요?

nullable 형식에는 ?, null 용서에는 !를 사용하고 정확한 흐름 분석에는 MaybeNull 및 NotNullWhen 같은 특성을 사용합니다. 브라우저에서 직접 실행하는 실습 코드로 C# Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

C# Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 C# Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.

“주석: ?, !, MaybeNull과 NotNull” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 C# Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 C# Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. NRT 활성화와 이해
  2. 주석: ?, !, MaybeNull과 NotNull
  3. null 조건부 및 null 병합 연산자
  4. 코드베이스를 NRT로 마이그레이션하기
← C# Academy(으)로 돌아가기