Errori e avvisi associati a parametri per riferimento, variabili e valori restituiti
Quando si utilizzano variabili di riferimento, è possibile che vengano generati gli errori seguenti:
- CS0192: un campo
readonly
non può essere usato come valoreref
oout
(tranne che in un costruttore). - CS0199: un campo
static readonly
non può essere usato come valoreref
oout
(tranne che in un costruttore statico). - CS0206: una proprietà o un indicizzatore che non restituisce ref non può essere usato come valore
out
oref
. - CS0631:
ref
eout
non sono validi in questo contesto. - CS0767: non è possibile ereditare l'interfaccia con i parametri di tipo specificati perché in tal caso il metodo conterrebbe overload diversi solo per
ref
eout
. - CS1510: un valore
ref
oout
deve essere una variabile assegnabile. - CS1605: non è possibile usare una variabile come valore
ref
oout
perché è di sola lettura. - CS1623: gli iteratori non possono avere i parametri
ref
,in
oout
. - CS1649: i membri di un campo
readonly
non possono essere usati come valoreref
oout
(tranne che in un costruttore). - CS1651: i campi di un campo static readonly non possono essere usati come valore
ref
oout
(tranne che in un costruttore statico). - CS1655: non è possibile usare campi di tipo come valore
ref
oout
. - CS1657: non è possibile usare una variabile come valore
ref
oout
. - CS1741: un parametro
ref
oout
non può avere un valore predefinito. - CS1939: non è possibile passare la variabile di intervallo come parametro
out
oref
. - CS1988: i metodi asincroni non possono avere i parametri
ref
,in
oout
. - CS7084: un evento Windows Runtime non può essere passato come parametro
out
oref
. - CS8166: non è possibile restituire un parametro per riferimento perché non è un parametro
ref
. - CS8167: non è possibile restituire per riferimento un membro del parametro perché non è un parametro
ref
oout
. - CS8168: non è possibile restituire una variabile locale per riferimento perché non è una variabile locale ref.
- CS8169: non è possibile restituire un membro della variabile locale per riferimento perché non è una variabile locale ref.
- CS8196: nello stesso elenco di argomenti non è consentito il riferimento a una variabile out tipizzata in modo implicito.
- CS8325: non è possibile usare '
await
' in un'espressione contenente un operatore condizionaleref
. - CS8326: entrambi i valori dell'operatore condizionale devono essere valori ref, altrimenti nessuno dei due può esserlo.
- CS8327: l'espressione deve essere di tipo corretto per essere uguale al valore ref alternativo.
- CS8329: non è possibile usare una variabile come valore
ref
oout
perché è una variabile readonly. - CS8330: i membri della variabile non possono essere usati come valore
ref
oout
perché è una variabile readonly. - CS8331: non è possibile assegnarla a una variabile o usarla come valore di destra di un'assegnazione
ref
perché è una variabile readonly. - CS8332: non è possibile assegnarla a un membro della variabile o usarla come valore di destra di un'assegnazione
ref
perché è una variabile readonly. - CS8337: il primo parametro di un metodo di estensione '
ref
' deve essere un tipo valore o un tipo generico vincolato a struct. - CS8338: il primo parametro '
in
' o 'ref readonly
' del metodo di estensione deve essere un tipo valore concreto (non generico). - CS8351: i rami di un operatore condizionale
ref
non possono fare riferimento a variabili con ambiti di dichiarazione incompatibili. - CS8373: il valore di sinistra di un'assegnazione
ref
deve essere una variabile ref. - CS8374: non è possibile assegnare un valore ref perché l'origine ha un ambito di escape più ristretto rispetto a quello di destinazione.
- CS8388: non è possibile dichiarare una variabile
out
come variabile locale ref. - CS8977: non è possibile usare '
ref
', 'in
' o 'out
' nella firma di un metodo con l'attributo 'UnmanagedCallersOnly'. - CS9072: una variabile di decostruzione non può essere dichiarata come variabile locale ref.
- CS9077: non è possibile restituire un parametro per riferimento tramite un parametro
ref
. Può essere restituito solo in un'istruzione return. - CS9078: non è possibile restituire per riferimento un membro del parametro tramite un parametro
ref
. Può essere restituito solo in un'istruzione return. - CS9079: non è possibile assegnare un valore ref perché l'origine può eseguire l'escape solo del metodo corrente tramite un'istruzione return.
- CS9096: non è possibile assegnare un valore ref perché l'origine ha un ambito di escape del valore più ampio rispetto a quello di destinazione consentendo l'assegnazione tramite l'origine di valori con ambiti di escape più ristretti rispetto a quelli di destinazione.
- CS9101: UnscopedRefAttribute può essere applicato solo ai metodi e alle proprietà dell'istanza dell'interfaccia virtuale o struct e non può essere applicato a costruttori o membri solo init.
- CS9102: UnscopedRefAttribute non può essere applicato a un'implementazione dell'interfaccia perché il membro implementato non ha questo attributo.
- CS9104: una risorsa di istruzione
using
di tipo non può essere usata in metodi asincroni o espressioni lambda asincrone. - CS9190: il modificatore
readonly
deve essere specificato doporef
. - CS9199: un parametro
ref readonly
non può avere l'attributo Out.
Gli avvisi seguenti vengono generati quando le variabili di riferimento vengono usate in modo non corretto:
- CS9085: assegna alla variabile un valore ref ma la destinazione ha un ambito di escape più ristretto rispetto a quello di origine.
- CS9086: i rami dell'operatore condizionale
ref
fanno riferimento a variabili con ambiti di dichiarazione incompatibili. - CS9087: restituisce un parametro per riferimento, ma non è un parametro
ref
. - CS9089: restituisce per riferimento un membro del parametro che non è un parametro
ref
oout
. - CS9091: restituisce una variabile locale per riferimento, ma non è una variabile locale ref.
- CS9092: restituisce un membro della variabile locale per riferimento, ma non è una variabile locale ref.
- CS9093: assegna un valore ref ma l'origine può eseguire l'escape solo del metodo corrente tramite un'istruzione return.
- CS9094: restituisce un parametro per riferimento tramite un parametro
ref
, ma può essere restituito in modo sicuro solo in un'istruzione return. - CS9095: restituisce per riferimento un membro del parametro tramite un parametro
ref
, ma può essere restituito in modo sicuro solo in un'istruzione return. - CS9097: assegna un valore ref ma l'origine ha un ambito di escape del valore più ampio rispetto a quello di destinazione consentendo l'assegnazione tramite la destinazione di valori con ambiti di escape più ristretti rispetto a quelli di origine.
- CS9191: il modificatore
ref
per l'argomento corrispondente al parametroin
equivale ain
. In alternativa, provare a usarein
. - CS9192: l'argomento deve essere passato con la parola chiave
ref
oin
. - CS9193: l'argomento deve essere una variabile perché viene passato a un parametro
ref readonly
. - CS9195: l'argomento deve essere passato con la parola chiave
in
. - CS9196: il modificatore del tipo di riferimento del parametro non corrisponde al parametro corrispondente nel membro sottoposto a override o implementato.
- CS9197: il modificatore del tipo di riferimento del parametro non corrisponde al parametro corrispondente nel membro nascosto.
- CS9198: il modificatore del tipo di riferimento del parametro non corrisponde al parametro corrispondente nella destinazione.
- CS9200: viene specificato un valore predefinito per il parametro
ref readonly
, maref readonly
deve essere usato solo per i riferimenti. Provare a dichiarare il parametro comein
. - CS9201: il valore ref deve essere assegnato al campo ref prima dell'uso.
- CS9265: il campo non viene mai assegnato a riferimento e avrà sempre il valore predefinito (riferimento Null)
Questi errori e avvisi seguono questi temi:
- Sintassi non corretta: la sintassi della dichiarazione o dell'utilizzo non è valida.
- Costrutti di linguaggio in cui le variabili
ref
non sono valide: alcuni idiomi C# non consentono variabili. In genere ciò è dovuto al fatto che l'analisi della sicurezza delle variabili ref non può essere eseguita in modo affidabile. - Espressione valore usata quando è necessaria una variabile di riferimento: l'espressione usata come variabile di riferimento deve essere una variabile, non un'espressione valore.
- Variabili di riferimento scrivibili che fanno riferimento a variabili readonly: un riferimento a una variabile readonly non può essere passato per riferimento scrivibile.
- Violazioni di sicurezza delle variabili ref: una variabile di riferimento non può fare riferimento a una variabile con un contesto più ristretto. Ciò significa che la variabile di riferimento potrebbe fare riferimento a una memoria non valida.
Questo articolo usa il termine variabile di riferimento come termine generale per un parametro dichiarato con uno dei modificatori in
, ref readonly
, ref
o out
o una variabile locale ref
, un campo ref
in un oggetto ref struct
o un valore restituito ref
. Una variabile di riferimento fa riferimento a un'altra variabile, denominata referente.
Sintassi non corretta
Questi errori indicano che si sta usando una sintassi non corretta relativa alle variabili di riferimento:
- CS8373: il valore di sinistra di un'assegnazione
ref
deve essere una variabile ref. - CS8388: non è possibile dichiarare una variabile
out
come variabile locale ref. - CS9190: il modificatore
readonly
deve essere specificato doporef
.
È possibile correggere l'errore con una delle modifiche seguenti:
- L'operando sinistro di un operatore
= ref
deve essere una variabile di riferimento. Per altre informazioni sulla sintassi corretta, vedere Variabili di riferimento. - Il modificatore di parametro
ref readonly
deve essere in questo ordine.readonly ref
non è un modificatore di parametro valido. Cambiare l'ordine delle parole. - Una variabile locale non può essere dichiarata come
out
. Per dichiarare una variabile di riferimento locale, usareref
.
Restrizioni delle variabili di riferimento
Gli errori seguenti indicano che non è possibile usare una variabile di riferimento quando ne esiste una:
- CS0631:
ref
eout
non sono validi in questo contesto. - CS0767: non è possibile ereditare l'interfaccia con i parametri di tipo specificati perché in tal caso il metodo conterrebbe overload diversi solo per
ref
eout
. - CS1623: gli iteratori non possono avere i parametri
ref
,in
oout
. - CS1741: un parametro
ref
oout
non può avere un valore predefinito. - CS1939: non è possibile passare la variabile di intervallo come parametro
out
oref
. - CS1988: i metodi asincroni non possono avere i parametri
ref
,in
oout
. - CS7084: un evento Windows Runtime non può essere passato come parametro
out
oref
. - CS8196: nello stesso elenco di argomenti non è consentito il riferimento a una variabile
out
tipizzata in modo implicito. - CS8325: non è possibile usare 'await' in un'espressione contenente un operatore condizionale
ref
. - CS8326: entrambi i valori dell'operatore condizionale devono essere valori ref, altrimenti nessuno dei due può esserlo.
- CS8327: l'espressione deve essere di tipo corretto per essere uguale al valore ref alternativo.
- CS8337: il primo parametro di un metodo di estensione '
ref
' deve essere un tipo valore o un tipo generico vincolato a struct. - CS8338: il primo parametro '
in
' o 'ref readonly
' del metodo di estensione deve essere un tipo valore concreto (non generico). - CS8977: non è possibile usare '
ref
', 'in
' o 'out
' nella firma di un metodo con l'attributo 'UnmanagedCallersOnly'. - CS9072: una variabile di decostruzione non può essere dichiarata come variabile locale ref.
- CS9104: una risorsa di istruzione
using
di tipo non può essere usata in metodi asincroni o espressioni lambda asincrone. - CS9199: un parametro
ref readonly
non può avere l'attributo Out.
Gli avvisi seguenti indicano che una variabile di riferimento non deve essere usata e potrebbe non essere sicura:
- CS9196: il modificatore del tipo di riferimento del parametro non corrisponde al parametro corrispondente nel membro sottoposto a override o implementato.
- CS9197: il modificatore del tipo di riferimento del parametro non corrisponde al parametro corrispondente nel membro nascosto.
- CS9198: il modificatore del tipo di riferimento del parametro non corrisponde al parametro corrispondente nella destinazione.
- CS9200: viene specificato un valore predefinito per il parametro
ref readonly
, maref readonly
deve essere usato solo per i riferimenti. Provare a dichiarare il parametro comein
. - CS9201: il valore ref deve essere assegnato al campo ref prima dell'uso.
- CS9265: il campo non viene mai assegnato a riferimento e avrà sempre il valore predefinito (riferimento Null)
Per correggere l'errore, rimuovere la variabile di riferimento dove non è consentita:
- Rimuovere i parametri
in
,ref
eout
da indicizzatori, iteratori e metodi asincroni. - Rimuovere le espressioni condizionali ref (
? :
) che includono un operatore await. - Rimuovere il modificatore
ref
dal primo parametro di un metodo di estensione se il tipo non è un tipo valore o un tipo generico vincolato come tipo valore. - Entrambe o nessuna delle due [espressioni dell'operatore condizionale] devono essere variabili
ref
. Rimuovereref
da un'espressione o aggiungerla all'altra. Se si tratta di un'espressione condizionaleref
, entrambe le espressioni devono essere dello stesso tipo. - I parametri
ref
eout
non possono avere valori predefiniti. Rimuovere il modificatoreref
oout
oppure rimuovere il valore predefinito. - Una dichiarazione di variabile
out
tipizzata in modo implicito non può essere presente anche altrove nello stesso elenco di argomenti. - Non è possibile inserire variabili di riferimento in un'istruzione
using
nelle espressioni lambda dei metodiasync
. - La variabile di intervallo in un'espressione di query LINQ non può essere passata per riferimento.
- Non è possibile decostruire un oggetto in variabili di riferimento. Sostituire le variabili di riferimento con variabili di valore.
- Non è possibile implementare più interfacce in cui gli overload dei metodi differiscono solo per
ref
eout
. Ad esempio, un'interfaccia dichiaravoid M(ref int i)
e un'altra interfaccia dichiaravoid M(out int i)
. Una classe non può implementare entrambe le interfacce perché i metodi non sono distinguibili. È possibile implementare solo una di queste interfacce. - I metodi con l'attributo System.Runtime.InteropServices.UnmanagedCallersOnlyAttribute non possono usare parametri per riferimento.
- Un evento Windows Runtime non può essere passato come variabile di riferimento.
- Non è possibile applicare l'attributo System.Runtime.InteropServices.OutAttribute a un parametro
ref readonly
nell'API di comunicazione remota. - Inizializzare un
ref
campo nel costruttore o come inizializzatore di campo.
Restrizioni di unscoped ref
Il qualificatore unscoped
per i parametri ref
non è consentito in alcune posizioni:
- CS9101: UnscopedRefAttribute può essere applicato solo ai metodi e alle proprietà dell'istanza dell'interfaccia virtuale o struct e non può essere applicato a costruttori o membri solo init.
- CS9102: UnscopedRefAttribute non può essere applicato a un'implementazione dell'interfaccia perché il membro implementato non ha questo attributo.
È necessario rimuovere il modificatore unscoped
dalla dichiarazione del parametro che ha causato l'errore.
Le variabili di riferimento richiedono un referente
È necessario fornire una variabile come argomento a un parametro per riferimento, a un valore restituito di riferimento o a un'assegnazione della variabile locale ref:
- CS0206: una proprietà o un indicizzatore che non restituisce ref non può essere usato come valore
out
oref
. - CS1510: un valore
ref
oout
deve essere una variabile assegnabile.
Warnings (Avvisi):
- CS9191: il modificatore
ref
per l'argomento corrispondente al parametroin
equivale ain
. In alternativa, provare a usarein
. - CS9192: l'argomento deve essere passato con la parola chiave
ref
oin
. - CS9193: l'argomento deve essere una variabile perché viene passato a un parametro
ref readonly
. - CS9195: l'argomento deve essere passato con la parola chiave
in
.
Il compilatore genera questi errori quando si usa un'espressione che calcola un valore in cui deve essere usata una variabile. È necessario archiviare il risultato di tale espressione in una variabile per usarla. Ad esempio, le proprietà e gli indicizzatori restituiscono valori, non variabili. È necessario archiviare il risultato in una variabile e passare un riferimento a tale variabile.
Le variabili di riferimento scrivibili richiedono un referente scrivibile
Una variabile di riferimento scrivibile richiede che anche il referente sia scrivibile. Gli errori seguenti indicano che la variabile non è scrivibile:
- CS0192: un campo
readonly
non può essere usato come valoreref
oout
(tranne che in un costruttore). - CS0199: un campo
static readonly
non può essere usato come valoreref
oout
(tranne che in un costruttore statico). - CS1605: non è possibile usare una variabile come valore
ref
oout
perché è di sola lettura. - CS1649: i membri di un campo
readonly
non possono essere usati come valoreref
oout
(tranne che in un costruttore). - CS1651: i campi di un campo
static readonly
non possono essere usati come valoreref
oout
(tranne che in un costruttore statico). - CS1655: non è possibile usare campi di tipo come valore
ref
oout
. - CS1657: non è possibile usare una variabile come valore
ref
oout
. - CS8329: non è possibile usare una variabile come valore
ref
oout
perché è una variabile readonly. - CS8330: i membri della variabile non possono essere usati come valore
ref
oout
perché è una variabile readonly. - CS8331: non è possibile assegnarla a una variabile o usarla come valore di destra di un'assegnazione
ref
perché è una variabile readonly. - CS8332: non è possibile assegnarla a un membro della variabile o usarla come valore di destra di un'assegnazione
ref
perché è una variabile readonly.
Esempi di variabili non scrivibili sono:
- Campi readonly, sia campi di istanza che statici.
- Membri dei campi
readonly
. - Variabile
this
. - Variabile di iterazione foreach.
- Variabile using o variabile fixed.
È necessario copiare il valore e passare un riferimento alla copia.
Violazioni di sicurezza delle variabili ref
Il compilatore tiene traccia del contesto sicuro dei referenti e delle variabili di riferimento. Il compilatore genera errori o avvisi nel codice non gestito quando una variabile di riferimento fa riferimento a una variabile referente che non è più valida. Il referente deve avere un contesto sicuro ampio almeno quanto il contesto sicuro di riferimento della variabile di riferimento. Se si violano questi controlli di sicurezza, la variabile di riferimento accede alla memoria casuale anziché alla variabile referente.
- CS8166: non è possibile restituire un parametro per riferimento perché non è un parametro
ref
. - CS8167: non è possibile restituire per riferimento un membro del parametro perché non è un parametro
ref
oout
. - CS8168: non è possibile restituire una variabile locale per riferimento perché non è una variabile locale ref.
- CS8169: non è possibile restituire un membro della variabile locale per riferimento perché non è una variabile locale ref.
- CS8345: un campo o una proprietà implementata automaticamente non può essere di tipo a meno che non sia un membro di istanza di un valore
ref struct
. - CS8351: i rami di un operatore condizionale
ref
non possono fare riferimento a variabili con ambiti di dichiarazione incompatibili. - CS8374: non è possibile assegnare un valore ref perché l'origine ha un ambito di escape più ristretto rispetto a quello di destinazione.
- CS9077: non è possibile restituire un parametro per riferimento tramite un parametro
ref
. Può essere restituito solo in un'istruzione return. - CS9078: non è possibile restituire per riferimento un membro del parametro tramite un parametro
ref
. Può essere restituito solo in un'istruzione return. - CS9079: non è possibile assegnare un valore ref dall'origine alla destinazione perché l'origine può eseguire l'escape solo del metodo corrente tramite un'istruzione return.
- CS9096: non è possibile assegnare un valore ref dall'origine alla destinazione perché l'origine ha un ambito di escape del valore più ampio rispetto a quello di destinazione consentendo l'assegnazione tramite la destinazione di valori con ambiti di escape più ristretti rispetto a quelli di origine.
Warnings (Avvisi):
- CS9085: assegna un valore ref dall'origine alla destinazione ma l'origine ha un ambito di escape più ristretto rispetto a quello di destinazione.
- CS9086: i rami dell'operatore condizionale ref fanno riferimento a variabili con ambiti di dichiarazione incompatibili.
- CS9087: restituisce un parametro per riferimento, ma non è un parametro
ref
. - CS9089: restituisce per riferimento un membro del parametro che non è un parametro
ref
oout
. - CS9091: restituisce una variabile locale per riferimento, ma non è una variabile locale ref.
- CS9092: restituisce un membro della variabile locale per riferimento, ma non è una variabile locale ref.
- CS9093: assegna un valore ref dall'origine alla destinazione ma l'origine può eseguire l'escape solo del metodo corrente tramite un'istruzione return.
- CS9094: restituisce un parametro per riferimento tramite un parametro
ref
, ma può essere restituito in modo sicuro solo in un'istruzione return. - CS9095: restituisce per riferimento un membro del parametro tramite un parametro
ref
, ma può essere restituito in modo sicuro solo in un'istruzione return. - CS9097: assegna un valore ref dall'origine alla destinazione ma l'origine ha un ambito di escape del valore più ampio rispetto a quello di destinazione consentendo l'assegnazione tramite la destinazione di valori con ambiti di escape più ristretti rispetto a quelli di origine.
Il compilatore usa l'analisi statica per determinare se il referente è valido in tutti i punti in cui è possibile usare la variabile di riferimento. È necessario effettuare il refactoring del codice in modo che il referente rimanga valido in tutte le posizioni in cui la variabile di riferimento potrebbe farvi riferimento. Per informazioni dettagliate sulle regole per la sicurezza dei riferimenti, vedere lo standard C# nei contesti sicuri di riferimento.