Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Tips/Råd
Den här artikeln är en del av avsnittet Grunderna för utvecklare som känner till minst ett programmeringsspråk och lär sig C#. Om du inte har använt programmering tidigare börjar du med självstudierna Komma igång först. För den fullständiga operatorreferensen, se Åtkomstoperatörer för medlemmar och null-koalescerande operatorer i språkreferensen.
C# innehåller flera operatorer som gör null-säker kod koncis. I stället för att kapsla if (x != null) skydd i koden kan du med dessa operatorer uttrycka null-säker åtkomst, återställningsvärden och null-tester i ett enda uttryck.
Den här artikeln beskriver ?. och ?[] för null-villkorlig åtkomst, ?? för nullsammanslagning, ??= för nullsammanslagningstilldelning och is null/is not null för null-mönstermatchning.
Åtkomst till null-villkorlig medlem ?.
Operatorn ?. kommer endast åt en medlem när objektet inte är null. När objektet är null utvärderas hela uttrycket till null i stället för att utlösa ett NullReferenceException.
string? name = null;
// Without ?., accessing a member on null throws NullReferenceException:
// int len = name.Length; // throws if name is null
// ?. returns null instead of throwing:
int? len = name?.Length;
Console.WriteLine(len.HasValue); // False
name = "C#";
Console.WriteLine(name?.Length); // 2
Operatorns ?.kortslutning: när den vänstra sidan är nullhoppas allt till höger över. Inga metodanrop körs och inga biverkningar inträffar.
Du kan länka flera ?. operatorer i ett enda uttryck. Kedjan stoppas vid den första null som den möter.
string? input = null;
// Chain ?. across multiple method calls — short-circuits at the first null:
string? upper = input?.Trim()?.ToUpperInvariant();
Console.WriteLine(upper ?? "(none)"); // (none)
input = " hello ";
Console.WriteLine(input?.Trim()?.ToUpperInvariant()); // HELLO
Åtkomst till null-villkorsstyrd indexerare ?[]
Operatorn ?[] tillämpar samma kortslutningsbeteende på indexerare och matrisåtkomst. Använd den när själva samlingen kan vara null:
string[]? tags = null;
// ?[] accesses an element only when the collection is non-null
string? first = tags?[0];
Console.WriteLine(first ?? "(none)"); // (none)
tags = ["csharp", "dotnet", "nullable"];
Console.WriteLine(tags?[0]); // csharp
Kedja nullvillkorsoperatorer
Länka flera ?. operatorer för att traversera en väg med potentiellt nullreferenser. Kedjan kortsluter vid det första null:
var order = new Order("ORD-001", null);
// Each ?. short-circuits when null: Customer is null, so Address and City are never accessed
string? city = order.Customer?.Address?.City;
Console.WriteLine(city ?? "(no city)"); // (no city)
var fullOrder = new Order("ORD-002",
new Customer("Alice", new Address("123 Main St", "Springfield", "IL")));
Console.WriteLine(fullOrder.Customer?.Address?.City); // Springfield
När Customer är null, varken Address eller City utvärderas. Hela uttrycket returnerar null.
Trådsäkert ombudsanrop
?. ger ett rent, trådsäkert sätt att anropa en delegering eller utlösa en händelse. Delegeringsuttrycket utvärderas bara en gång, så det finns ingen möjlighet för en annan tråd att avprenumerera mellan null-kontrollen och anropet.
EventHandler? clicked = null;
// No subscribers — ?.Invoke does nothing instead of throwing NullReferenceException
clicked?.Invoke(null, EventArgs.Empty);
clicked += (_, _) => Console.WriteLine("Button clicked!");
// With a subscriber — ?.Invoke calls the handler
clicked?.Invoke(null, EventArgs.Empty);
// Output: Button clicked!
Det här mönstret ersätter det äldre if (clicked != null) clicked(...) formspråket.
Null-sammanfogning ??
Operatorn ?? returnerar sin vänstra operande när den inte är null och dess högra operande när vänster är null. Använd det för att ange ett standardvärde:
string? username = null;
// ?? returns the right-hand value when the left-hand is null
string display = username ?? "Guest";
Console.WriteLine(display); // Guest
username = "alice";
display = username ?? "Guest";
Console.WriteLine(display); // alice
?? är rätt associativ, så a ?? b ?? c utvärderas som a ?? (b ?? c). Det första värdet som inte är null vinner. Ett vanligt mönster är att länka ?. med ??: använd ?. för att på ett säkert sätt korsa en null-möjlig kedja och sedan ?? ersätta en standard om kedjan returnerade null. Ett fullständigt exempel finns i Kombinera null-operatorer.
Null-sammankopplingstilldelning ??=
Operatorn ??= tilldelar endast högervärdet till en variabel när variabeln är null. Använd den för lat initiering:
List<string>? cache = null;
// ??= assigns only when the variable is null
cache ??= LoadData();
Console.WriteLine(cache.Count); // 3
// cache is already non-null, so LoadData() isn't called again
cache ??= LoadData();
Console.WriteLine(cache.Count); // 3
static List<string> LoadData() => ["alpha", "beta", "gamma"];
Det högra uttrycket utvärderas endast när variabeln är null. När variabeln redan har ett värde utvärderas inte den högra sidan alls.
Null-villkorsstyrd tilldelning (C# 14)
Från och med C# 14 kan du använda ?. och ?[] som tilldelningsmål. Tilldelningen körs endast när det vänstra objektet inte är null:
AppConfig? config = new AppConfig();
// Assigns only when config is non-null (C# 14)
config?.Theme = "dark";
Console.WriteLine(config?.Theme); // dark
AppConfig? missing = null;
missing?.Theme = "light"; // no-op: missing is null
Console.WriteLine(missing?.Theme ?? "(no config)"); // (no config)
Den högra sidan utvärderas endast när den vänstra sidan är känd för att inte vara null.
Null-mönstermatchning: is null och is not null
Mönstren is null och is not null testar om ett uttryck är null:
string? input = null;
// is null is the preferred test — unaffected by operator overloading
if (input is null)
{
Console.WriteLine("No input provided.");
}
// == null also works, but a custom == operator can change its behavior
if (input == null)
{
Console.WriteLine("Still no input.");
}
Föredrar is null över == null för null-kontroller. Operatorn == kan överbelastas, vilket innebär att x == null kan returnera true även när x inte är null om typen definierar en anpassad jämförelseoperator. Mönstret is null testar alltid för den faktiska null-referensen, oavsett operatoröverlagring.
string? value = "hello";
if (value is not null)
{
Console.WriteLine(value.ToUpper()); // HELLO
}
Kombinera null-operatorer
I praktiken kombinerar du ofta flera av dessa operatorer. Ett uttryck kan på ett säkert sätt traversera en djup objektgraf, tillämpa en reserv och sedan övervaka resultatet.
Order? order = GetPendingOrder();
// Chain ?. for safe traversal, ?? for a fallback, is null for a clear guard
string city = order?.Customer?.Address?.City ?? "unknown";
if (order is null)
{
Console.WriteLine("No pending order.");
}
else
{
Console.WriteLine($"Shipping to: {city}");
}
// Output: No pending order.
Null-förlåtande operator !
Postfixoperatorn ! undertrycker nullbara varningar. Lägg till ! för att tala om för kompilatorn att "det här uttrycket definitivt inte är null." Operatorn har ingen effekt vid körning. Det påverkar bara kompilatorns null-tillståndsanalys.
string? name = FindUser("alice");
// Use ! only when you have information the compiler doesn't.
// FindUser guarantees a non-null result for known usernames.
int length = name!.Length;
Console.WriteLine(length); // 5
Använd ! sparsamt och endast när du har information som kompilatorn inte har. Exempel är tester som avsiktligt köra null för att verifiera logiken för argumentkontroll, eller anropa en metod vars kontrakt garanterar en icke-null-retur för kända indata. Överanvändning ! motverkar syftet med nullbara referenstyper. En fullständig förklaring finns i Referenstyper som kan ogiltigförklaras.