Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Tip
Questo articolo fa parte della sezione Nozioni fondamentali per gli sviluppatori che già conoscono almeno un linguaggio di programmazione e stanno imparando C#. Se non si ha familiarità con la programmazione, iniziare prima con le esercitazioni introduttive .
Venire da un'altra lingua? Le espressioni in C# funzionano come funzionano in Java, C++ e JavaScript. Una differenza vale la pena notare: gli operatori di assegnazione composta come += e l'operatore ++ di incremento sono espressioni in C#, in modo che possano essere visualizzate in espressioni più grandi.
Un espressione è un frammento di codice che il compilatore valuta per produrre un valore — un numero, una stringa, un riferimento o un bool. Ad esempio, 3 + 4 * 2 è un'espressione che restituisce l'intero 11ed total > 10 è un'espressione che restituisce true o false.
Le espressioni più semplici sono valori letterali (ad esempio 42 o "hello") e nomi di variabili (ad esempio total). È possibile creare espressioni più complesse combinando quelle più semplici con gli operatori.
Espressioni e istruzioni
Un'espressione produce un valore.
Un'istruzione è un'istruzione completa eseguita dal programma. Molte istruzioni contengono espressioni. Ad esempio, int total = 3 + 4 * 2; è un'istruzione di dichiarazione di variabile. Il compilatore valuta l'espressione 3 + 4 * 2dell'inizializzatore , che produce 11e assegna tale valore alla nuova variabile total.
È possibile considerare un'espressione come una frase e un'istruzione C# come una frase completa. Queste definizioni di lavoro consentono di comprendere la terminologia formale e le spiegazioni che si incontreranno man mano che si apprenderanno altre informazioni su C#, anche se la codifica comune richiede raramente di ricordare la distinzione in modo consapevole.
Combinazione di espressioni
Le espressioni possono essere combinate. Considera 3 + 4 * 2. Questa singola espressione contiene effettivamente due espressioni più piccole: l'espressione 4 * 2di moltiplicazione e l'espressione 3 + <result>di addizione. Quando le espressioni vengono combinate, C# richiede una regola per decidere quale valutare per prima. Tale regola è la precedenza dell'operatore.
Non è necessario memorizzare la gerarchia di precedenza completa. La sezione successiva riepiloga i gruppi quotidiani e le parentesi consentono sempre di rendere l'ordine esplicito quando non si è certi.
Precedenza dell'operatore
La precedenza dell'operatore determina il modo in cui un'espressione combinata si raggruppa in sottoespressione. Questo concetto è simile alle regole di ordine delle operazioni della classe matematica. Un operatore con precedenza superiore si lega più strettamente ai suoi operandi. L'espressione è strutturata come se tali operandi siano racchiusi tra parentesi. In 3 + 4 * 2, * ha una precedenza maggiore di +, quindi i gruppi di espressioni come 3 + (4 * 2), non (3 + 4) * 2.
C# ha più gruppi di precedenza rispetto ai quattro riepilogati qui. Questi gruppi aggiuntivi applicano regole familiari, ad esempio la moltiplicazione prima dell'aggiunta, e coprono il set completo di operatori. I gruppi seguenti illustrano ciò che si incontra più spesso nel codice quotidiano:
-
Primario, unario e intervallo : si tratta di tre gruppi di precedenza distinti, tutti più strettamente associati all'aritmetica. Questo riepilogo li combina in un unico passaggio perché, per scopi pratici, si applicano tutti prima dell'aritmetica.
-
Operatori primari : accesso ai membri (
x.y), chiamate al metodo (f()), indicizzazione (a[i]) e accesso condizionale null (?.,?[]) - associano più strettamente tutti. -
Gli operatori unari agiscono su un singolo operando: negazione (
-x), NOT logico (!flag), incremento del prefisso (++i) e incremento del prefisso (i++). - L'operatore range (
..) compila gli intervalli di indici per le espressioni di sezione, ad esempioarray[1..4].
-
Operatori primari : accesso ai membri (
-
Aritmetica :
*,/, associare%più strettamente di+e-. La moltiplicazione e la divisione si verificano prima dell'addizione e della sottrazione. -
Operatori di confronto —
<,<=,>,>=,==,!=si legano meno strettamente degli operatori aritmetici, quindi le operazioni aritmetiche vengono eseguite prima del confronto. -
Logico :
&&e||associa meno strettamente gli operatori comuni, quindi i confronti vengono completati prima della combinazione logica.
Questa precedenza indica che l'espressione score + bonus > threshold && attempts < maxAttempts valuta esattamente come si legge: aggiungere score e bonus, confrontare la somma con threshold, confrontare attempts con maxAttempts, quindi combinare i due bool risultati con &&. L'aggiunta di parentesi per rendere esplicito ogni raggruppamento mostra la stessa struttura: ((score + bonus) > threshold) && (attempts < maxAttempts).
Per la gerarchia di precedenza completa che copre ogni operatore, vedere Operatori ed espressioni C#.
Usare le parentesi per chiarire la finalità
Le parentesi sostituiscono la precedenza e documentano contemporaneamente la finalità. Quando l'ordine non è ovvio dai gruppi precedenti, aggiungere parentesi:
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)
Le ultime due righe mostrano che le parentesi possono modificare il risultato, non solo lo stile. Quando && e || appaiono insieme, aggiungere parentesi per specificare quale condizione combina per prima. Un lettore che vede (isAdmin && isOwner) || isSuperUser capisce immediatamente l'intento.
Modalità di valutazione delle espressioni
Comprendere in che modo C# valuta le espressioni combinate è più semplice con un'analogia. Si pensi a un problema matematico complesso con matita e carta: si identifica la sottoespressione più interna o più alta, calcola il valore provvisorio, si scrive il risultato, quindi si ripete con la sottoespressione successiva, continuando fino a raggiungere la risposta finale.
C# segue lo stesso processo, guidato da due regole:
Regola 1: Gli operandi vengono valutati da sinistra a destra. Per qualsiasi espressione binaria, entrambi gli operandi devono essere valutati completamente prima dell'applicazione dell'operatore. C# valuta prima l'operando sinistro, poi quello destro, quindi esegue l'operazione.
Regola 2: Alcuni operatori sono in corto circuito. Alcuni operatori interrompono la valutazione non appena il risultato è determinato, saltando gli eventuali operandi rimanenti:
-
&&(AND condizionale): restituiscefalsenon appena il lato sinistro èfalse. Il lato destro non viene mai valutato. -
||(OR condizionale): restituiscetruenon appena il lato sinistro ètrue. Il lato destro non viene mai valutato. -
?:(condizionale/ternario): valuta solo il ramo che corrisponde alla condizione . L'altro ramo non viene mai valutato. -
?.(accesso condizionale ai membri con null) e?[](accesso condizionale agli elementi con null): si interrompono e restituiscono immediatamentenullquando la parte sinistra ènull, saltando l'accesso al membro o all'indice. -
??=(assegnazione con coalescenza null): assegna il valore di destra solo se il lato sinistro ènull.
Valutazione carta e matita
Si consideri l'espressione 3 + 6 / 2. Anche se l'aggiunta viene visualizzata per prima nell'ordine di lettura, / ha una precedenza superiore a +, quindi 6 / 2 è la sottoespressione che valuta per prima. Lavorare passo per passo - esattamente come si farebbe su carta:
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
Il valore 3 provvisorio prodotto da 6 / 2 diventa l'operando destro di +e il risultato finale è 6. Ogni sottoespressione produce un valore provvisorio; tali valori provvisori alimentano la sottoespressione successiva, fino a quando non rimane un solo valore.
L'associatività è un concetto correlato: quando due operatori hanno la stessa precedenza, l'associatività decide quale va prima. La maggior parte degli operatori C# è associativa a sinistra, ovvero raggruppano da sinistra a destra. Quindi a - b - c è uguale (a - b) - ca , non a - (b - c).
Valutazione a corto circuito in pratica
La valutazione a corto circuito è particolarmente utile per i controlli Null:
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 è sicuro perché la seconda condizione viene eseguita solo quando text non è null. Analogamente, ?. interrompe la valutazione quando incontra un riferimento null, evitando un NullReferenceException senza un controllo esplicito di if.
Per un'analisi più ampia degli operatori null-safe, vedere Operatori Null C#.
Vedere anche
- Operatori ed espressioni C# (riferimento al linguaggio) - tabella di precedenza completa e ogni operatore
- Operatori aritmetici, di confronto, logici e di assegnazione : gli operatori quotidiani in profondità
-
Confronti di uguaglianza — come funzionano
==,!=eEquals -
Operatori Null C# -
?.,??e??= - Operatori logici booleani