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.
Tip
Den här artikeln är en del av avsnittet Grunderna för utvecklare som redan 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.
Kommer du från ett annat språk? Uttryck i C# fungerar ungefär som i Java, C++ och JavaScript. En skillnad som är värd att notera: sammansatta tilldelningsoperatorer som += och inkrementsoperatorn ++ är uttryck i C#, så att de kan visas i större uttryck.
Ett uttryck är en kod som kompilatorn utvärderar för att skapa ett värde – ett tal, en sträng, en referens eller en bool. Är till exempel 3 + 4 * 2 ett uttryck som utvärderas till heltal 11och total > 10 är ett uttryck som utvärderas till true eller false.
De enklaste uttrycken är literaler (som 42 eller "hello") och variabelnamn (till exempel total). Du skapar mer komplexa uttryck genom att kombinera enklare uttryck med operatorer.
Uttryck och satser
Ett uttryck genererar ett värde. En instruktion är en fullständig instruktion som programmet kör. Många satser innehåller uttryck. Till exempel int total = 3 + 4 * 2; är en variabeldeklarationssats. Kompilatorn utvärderar initieringsuttrycket 3 + 4 * 2, som producerar 11och tilldelar värdet till den nya variabeln total.
Du kan tänka dig ett uttryck som en fras och en C#-instruktion som en fullständig mening. Dessa arbetsdefinitioner hjälper dig att förstå den formella terminologi och förklaringar som du kommer att stöta på när du lär dig mer om C#, även om vanlig kodning sällan kräver att du kommer ihåg skillnaden medvetet.
Kombinera uttryck
Uttryck kan kombineras. Tänk på 3 + 4 * 2. Det här enkla uttrycket innehåller faktiskt två mindre uttryck: multiplikationsuttrycket4 * 2 och additionsuttrycket3 + <result>. När uttryck kombineras behöver C# en regel för att bestämma vilken som ska utvärderas först. Den regeln är operatorprioret.
Du behöver inte memorera den fullständiga prioritetshierarkin. I nästa avsnitt sammanfattas de vardagliga grupperna, och med parenteser kan du alltid göra beställningen explicit när du är osäker.
Operatorernas prioritet
Operatorprioretens avgör hur ett kombinerat uttryck grupperas i underuttryck. Det här konceptet liknar driftordningsreglerna från matematikklassen. En operator med högre prioritet binder tätare till sina operander. Uttrycket är strukturerat som om dessa operander omsluts av parenteser tillsammans. I 3 + 4 * 2 har + högre prioritet än 3 + (4 * 2), så grupperas uttrycket som (3 + 4) * 2, inte *.
C# har fler prioritetsgrupper än de fyra som sammanfattas här. Dessa ytterligare grupper tillämpar välbekanta regler – till exempel multiplikation före tillägg – och täcker hela uppsättningen operatorer. Följande grupper beskriver det du stöter på oftast i daglig kod:
-
Primärt, unary och intervall – dessa är tre distinkta prioritetsgrupper, som alla binder hårdare än aritmetik. Den här sammanfattningen kombinerar dem i ett steg eftersom de i praktiken gäller före aritmetik.
-
Primära operatorer – medlemsåtkomst (
x.y), metodanrop (f()), indexering (a[i]) och null-villkorlig åtkomst (?.,?[]) – binder mest av alla. -
Unära operatorer verkar på en enda operand: negation (
-x), logisk NOT (!flag), prefixinkrementering (++i) och postfixinkrementering (i++). -
Intervalloperatorn (
..) skapar indexintervall för segmentuttryck, till exempelarray[1..4].
-
Primära operatorer – medlemsåtkomst (
-
Aritmetik –
*,/,%bind hårdare än+och-. Multiplikation och division sker före addition och subtraktion. -
Jämförelse –
<,>,<=,>=,==,!=binder mindre starkt än aritmetiska operatorer, så de aritmetiska operationerna utförs före jämförelsen. -
Logiska —
&&och||har lägst prioritet av de vanliga operatorerna, så jämförelser utförs före den logiska kombinationen.
Den här prioriteten innebär att uttrycket score + bonus > threshold && attempts < maxAttempts utvärderas exakt som du läst det: lägg till score och bonus, jämför summan med threshold, jämför med attemptsmaxAttemptsoch kombinerar sedan de två bool resultaten med &&. Om du lägger till parenteser för att göra varje gruppering explicit visas samma struktur: ((score + bonus) > threshold) && (attempts < maxAttempts).
Fullständig prioritetshierarki för varje operator finns i C#-operatorer och -uttryck.
Använda parenteser för att göra avsikten tydlig
Parenteser åsidosätter prioritet och dokumenterar din avsikt samtidigt. När ordningen inte är uppenbar från grupperna ovan lägger du till parenteser:
int score = 80;
int bonus = 15;
int threshold = 90;
bool eligible = true;
// Without parentheses: || binds less tightly than &&, so this reads as:
// eligible && (score + bonus > threshold) || bonus > 20
bool result1 = eligible && score + bonus > threshold || bonus > 20;
// With parentheses: forces the || to combine two complete conditions
bool result2 = (eligible && score + bonus > threshold) || bonus > 20;
Console.WriteLine(result1); // => True
Console.WriteLine(result2); // => True
// Parentheses can also change the result:
bool isAdmin = false;
bool isOwner = true;
// Without: && binds tighter, so: (isAdmin && isOwner) || true
bool access1 = isAdmin && isOwner || true;
// With: forces the || to run first
bool access2 = isAdmin && (isOwner || true);
Console.WriteLine(access1); // => True (false && true is false; false || true is true)
Console.WriteLine(access2); // => False (false && anything is false)
De två sista raderna visar att parenteser kan ändra resultatet, inte bara formatet. När && och || visas tillsammans lägger du till parenteser för att ange vilket villkor som kombineras först. En läsare som ser (isAdmin && isOwner) || isSuperUser vet avsikten omedelbart.
Hur uttryck utvärderas
Det är enklare att förstå hur C# utvärderar kombinerade uttryck med en analogi. Tänk på att arbeta igenom ett komplext matematiskt problem med penna och papper: du identifierar underuttrycket innersta eller högsta prioritet, beräknar dess interimsvärde, skriver ned resultatet och upprepar sedan med nästa underuttryck – fortsätter tills du når det slutliga svaret.
C# följer samma process, vägledd av två regler:
Regel 1: Operander utvärderas från vänster till höger. För alla binära uttryck måste båda operanderna utvärderas fullständigt innan operatorn tillämpas. C# utvärderar den vänstra operanden först, sedan den högra och utför därefter operationen.
Regel 2: Vissa operatorer kortsluter. Vissa operatorer slutar utvärdera så snart resultatet har fastställts och hoppar över eventuella återstående operander:
-
&&(villkorsstyrd AND): returnerarfalseså snart den vänstra sidan ärfalse. Den högra sidan utvärderas aldrig. -
||(villkorsstyrd ELLER): returnerartrueså snart den vänstra sidan ärtrue. Den högra sidan utvärderas aldrig. -
?:(villkorsstyrd/ternary): utvärderar endast den gren som matchar villkoret – den andra grenen utvärderas aldrig. -
?.(nullvillkorad medlemsåtkomst) och?[](nullvillkorad elementåtkomst): avbryt och returneranullomedelbart när vänstersidan ärnull, och hoppa över medlemsåtkomsten eller indexet. -
??=(null-sammanslagningstilldelning): tilldelar endast höger sida när den vänstra sidan ärnull.
Utvärdering av papper och penna
Överväg uttrycket 3 + 6 / 2. Även om tillägget visas först i läsordning har / högre prioritet än +, så 6 / 2 är det underuttryck som utvärderas först. Arbeta igenom det steg för steg – precis som på papper:
3 + 6 / 2
↓ (evaluate 6 / 2 → 3)
3 + 3
↓ (evaluate 3 + 3 → 6)
6
// 3 + 6 / 2
// Step 1: 6 / 2 has higher precedence → interim value 3
// Step 2: 3 + 3 → final result 6
int result = 3 + 6 / 2;
Console.WriteLine(result); // => 6
Interimvärdet 3 som skapas av 6 / 2 blir rätt operand för +, och slutresultatet är 6. Varje underuttryck genererar ett interimvärde. dessa interimvärden matar in nästa underuttryck tills endast ett värde finns kvar.
Associativitet är ett relaterat begrepp: när två operatorer har samma prioritet bestämmer associativitet vilken som går först. De flesta C# -operatorer är vänster-associativa, vilket innebär att de grupperar från vänster till höger. Så a - b - c är samma som (a - b) - c, inte a - (b - c).
Kortslutningsutvärdering i praktiken
Kortslutande utvärdering är särskilt användbar vid nullkontroller:
string? text = null;
// Safe: second condition runs only when text is not null
bool hasContent = text != null && text.Length > 0;
Console.WriteLine(hasContent); // => False (short-circuits after null check; no NullReferenceException)
text = "hello";
hasContent = text != null && text.Length > 0;
Console.WriteLine(hasContent); // => True
// || short-circuits on true: right side is never evaluated when left side is true
string word = "hello";
bool anyMatch = word.StartsWith("h") || word.StartsWith("x");
Console.WriteLine(anyMatch); // => True (right side never evaluated)
// ?. short-circuits on null: returns null without accessing .Length
string? maybeNull = null;
int? length = maybeNull?.Length; // length is null; no NullReferenceException
Console.WriteLine(length.HasValue); // => False
text != null && text.Length > 0 är säkert eftersom det andra villkoret bara utvärderas när text inte är null.
?. På samma sätt stoppas utvärderingen när den stöter på en null referens, vilket undviker en NullReferenceException utan explicit if kontroll.
En bredare titt på null-säkra operatorer finns i C#-nulloperatorer.
Se även
- C#-operatorer och uttryck (språkreferens) – fullständig prioritetstabell och varje operator
- Aritmetiska, jämförelse-, logiska och tilldelningsoperatorer – de dagliga operatorerna på djupet
-
Likhetsjämförelser – hur
==,!=ochEqualsfungerar -
C# null-operatorer –
?.,??och??= - Booleska logiska operatorer