C# Academy · Lektion

Annotationer: ?, !, MaybeNull och NotNull

Använd ? för nullable-typer, ! för null-forgiving och attribut som MaybeNull och NotNullWhen för noggrann flödesanalys.

Lektion 2 av 412 steg

Annotationer: ?, !, MaybeNull och NotNull är en gratis lektion i C# Academy på CoddyKit. Detta är lektion 2 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för C# Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i C# Academy innehåller totalt 4 lektioner.

Bortom ? och !: nullbarhetsattribut

Den grundläggande ?-annoteringen och nullkontrollen hanterar de flesta fall, men vissa mönster kräver mer uttrycksfulla annoteringar. Namnrymden System.Diagnostics.CodeAnalysis tillhandahåller attribut som ger kompilatorn djupare insikt i nullflödet.

MaybeNull och NotNull

[MaybeNull] talar om för kompilatorn att en icke-nullbar returtyp i praktiken ändå kan vara null, till exempel från en generisk metod. [NotNull] lovar att en nullbar parameter inte är null efter anropet.

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: villkorad icke-nullbarhet

[NotNullWhen(true)] talar om för kompilatorn att en out-parameter är icke-nullbar när metoden returnerar true. Så annoteras standardmönstret 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: villkorad nullbarhet

[MaybeNullWhen(false)] är motsatsen — resultatet kan vara null när metoden returnerar false. Det används i ordbokens TryGetValue-mönster.

// 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 och DisallowNull

[AllowNull] på en icke-nullbar egenskap tillåter anropare att skicka null till den, till exempel för en setter som omvandlar null till en tom sträng. [DisallowNull] förbjuder null för en nullbar typ.

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: sprida nullbarhet

[NotNullIfNotNull(paramName)] betyder: om parameter X inte är null är returvärdet inte heller null. Det är användbart för transformeringsfunktioner.

[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] markerar en metod som alltid kastar ett undantag. Kompilatorn vet att koden efter anropet är onåbar och undertrycker ogrundade nullvarningar.

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: eftervillkor för fält

[MemberNotNull] talar om för kompilatorn att en metod garanterar att vissa fält inte är null när den har returnerat. Det är användbart för hjälpfunktioner för fördröjd initiering.

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
    }
}

Kombinera annoteringar

Attribut kan kombineras för precisa API-kontrakt. Här är en fluent guard-hjälpmetod som kombinerar flera attribut.

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

Nulloperatorer: ?. ?? ??=

Operatorerna för nullvillkor (?.), nullkoalescering (??) och nullkoalescerande tilldelning (??=) gör det möjligt att skriva kortfattad nullsäker kod utan utförliga if-kontroller.

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";

Snabbkontroll

Vad talar [NotNullWhen(true)] på en out-parameter om för kompilatorn?

Sammanfattning: nullbarhetsannoteringar

Viktiga slutsatser:

  • [NotNullWhen(true)]: TryParse-mönstret — icke-null vid returvärdet true
  • [MaybeNull]: en icke-nullbar typ kan ändå returnera null (generiska standardvärden)
  • [DoesNotReturn]: metoden kastar alltid ett undantag — koden efteråt är onåbar
  • [MemberNotNull]: metoden garanterar att fält är initierade när den har returnerat
  • ?., ??, ??=: kortfattad nullsäker navigering och standardvärden
Gratis att börja

Lär dig C# med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
93
Lektioner
346

Vanliga frågor

Är lektionen ”Annotationer: ?, !, MaybeNull och NotNull” gratis?

Ja – hela texten till ”Annotationer: ?, !, MaybeNull och NotNull” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i C# Academy, kan Ni uppgradera till CoddyKit PRO. Kursen i C# Academy innehåller totalt 4 lektioner.

Vad lär jag mig i ”Annotationer: ?, !, MaybeNull och NotNull”?

Använd ? för nullable-typer, ! för null-forgiving och attribut som MaybeNull och NotNullWhen för noggrann flödesanalys. Ni övar på C# Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig C# Academy?

Du behöver inga förkunskaper. Utbildningen i C# Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 2 av 4.

Hur lång tid tar lektionen ”Annotationer: ?, !, MaybeNull och NotNull”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här C# Academy-lektionen?

Ja. Varje C# Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Aktivera och förstå NRT
  2. Annotationer: ?, !, MaybeNull och NotNull
  3. Null-conditional- och null-coalescing-operatorer
  4. Migrera en kodbas till NRT
← Tillbaka till C# Academy