Risolvere gli errori e gli avvisi nei costrutti di codice non sicuri

Questo articolo illustra la diagnostica del compilatore seguente:

  • CS0193: l'operatore * o -> deve essere applicato a un puntatore
  • CS0196: un puntatore deve essere indicizzato da un solo valore
  • CS0208: Impossibile ottenere l'indirizzo, le dimensioni o dichiarare un puntatore a un tipo gestito ('tipo')
  • CS0209: Il tipo di una variabile locale dichiarata in un'istruzione fixed deve essere un tipo puntatore
  • CS0210: è necessario fornire un inizializzatore in una dichiarazione di istruzione fixed o using
  • CS0211: Impossibile accettare l'indirizzo dell'espressione specificata
  • CS0212: è possibile accettare solo l'indirizzo di un'espressione senza prefisso all'interno di un inizializzatore di istruzione fixed
  • CS0213: non è possibile usare l'istruzione fixed per ottenere l'indirizzo di un'espressione già fissata
  • CS0214: i puntatori e i buffer a dimensione fissa possono essere usati solo in un contesto non sicuro
  • CS0227: il codice unsafe può essere visualizzato solo se viene compilato con /unsafe
  • CS0233: 'identifier' non ha una dimensione predefinita, pertanto sizeof può essere usato solo in un contesto non sicuro
  • CS0242: l'operazione in questione non è definita sui puntatori void
  • CS0244: né 'is' né 'as' sono validi per i tipi di puntatore
  • CS0254: il lato destro di un'assegnazione di istruzione fissa potrebbe non essere un'espressione cast
  • CS0459: Impossibile accettare l'indirizzo di una variabile locale di sola lettura
  • CS0821: Non è possibile correggere variabili locali tipizzate in modo implicito
  • CS1641: un campo buffer a dimensione fissa deve avere l'identificatore delle dimensioni della matrice dopo il nome del campo
  • CS1642: i campi del buffer a dimensione fissa possono essere solo membri di struct.
  • CS1656: Impossibile assegnare a 'variable' perché è un tipo di variabile di sola lettura
  • CS1663: il tipo di buffer a dimensione fissa deve essere uno dei seguenti: bool, byteshortintlong, char, sbyteushortuintulong, o floatdouble
  • CS1665: i buffer a dimensione fissa devono avere una lunghezza maggiore di zero
  • CS1666: non è possibile usare buffer a dimensione fissa contenuti in espressioni senza prefisso. Provare a usare l'istruzione fixed.
  • CS1708: è possibile accedere ai buffer a dimensione fissa solo tramite variabili locali o campi
  • CS1716: non usare l'attributo 'System.Runtime.CompilerServices.FixedBuffer'. Usare invece il modificatore di campo 'fixed'.
  • CS1919: impossibile usare il tipo non sicuro 'type name' nella creazione di oggetti.
  • CS4004: Impossibile await in un contesto non sicuro
  • CS7092: un buffer fisso può avere una sola dimensione.
  • CS8372: Non usare l'attributo 'System.Runtime.CompilerServices.FixedBuffer' in una proprietà
  • CS8812: impossibile convertire il gruppo di metodi 'method' in un tipo di puntatore non funzione 'type'.
  • CS9049: un campo fisso non deve essere un campo di riferimento.
  • CS9123: l'operatore '&' non deve essere usato nei parametri o nelle variabili locali nei metodi asincroni.
  • CS9360: questa operazione può essere usata solo in un contesto non sicuro
  • CS9361: stackalloc l'espressione senza un inizializzatore all'interno SkipLocalsInit può essere usata solo in un contesto non sicuro
  • CS9362: 'member' deve essere usato in un contesto non sicuro perché è contrassegnato come 'RequiresUnsafe' o 'extern'
  • CS9363: 'member' deve essere usato in un contesto non sicuro perché include puntatori nella firma
  • CS9364: il membro non sicuro 'member' non può eseguire l'override del membro sicuro 'member'
  • CS9365: un membro non sicuro 'member' non può implementare in modo implicito il membro sicuro 'member'
  • CS9366: Il membro insicuro 'member' non può implementare il membro sicuro 'member'
  • CS9367: RequiresUnsafeAttribute non può essere applicato a questo simbolo.
  • CS9368: RequiresUnsafeAttribute è valido solo nelle regole di sicurezza della memoria aggiornate.
  • CS9376: È richiesto un contesto unsafe per il costruttore contrassegnato come 'RequiresUnsafe' o 'extern' per soddisfare il vincolo 'new()' del parametro di tipo 'parametro di tipo' nel tipo o metodo generico
  • CS9377: il modificatore 'unsafe' non ha alcun effetto nelle regole di sicurezza della memoria correnti.

Operazioni del puntatore e dereferenziazione

  • CS0193: l'operatore * or -> deve essere applicato a un puntatore
  • CS0196: un puntatore deve essere indicizzato da un solo valore
  • CS0242: l'operazione in questione non è definita sui puntatori void

Per usare correttamente le operazioni del puntatore, seguire le regole per la dereferenziazione, l'indicizzazione e le operazioni aritmetiche. Per altre informazioni, vedere Tipi di puntatore e puntatori a funzione.

  • Applicare l'operatore * o -> solo ai puntatori dati (CS0193). Non usare questi operatori con tipi non puntatore o con puntatori a funzione. A differenza di C/C++, non è possibile dereferenziare i puntatori di funzione in C#.
  • Puntatori all'indice con un solo valore (CS0196). L'indicizzazione multidimensionale non è supportata nei puntatori.
  • Evitare operazioni non predefinite sui puntatori void (CS0242). Ad esempio, non incrementare un puntatore void perché il compilatore non conosce la dimensione dei dati a cui punta.

Tipi di puntatore e tipi gestiti

  • CS0208: impossibile accettare l'indirizzo di , ottenere le dimensioni o dichiarare un puntatore a un tipo gestito ('type')
  • CS0233: 'identifier' non ha una dimensione predefinita, pertanto sizeof può essere usato solo in un contesto non sicuro

Per usare correttamente i puntatori e l'operatore sizeof , usare tipi non gestiti e contesti appropriati. Per altre informazioni, vedere Tipi non gestiti e l'operatoresizeof .

  • Usare puntatori solo con tipi non gestiti (CS0208). Non prendere l'indirizzo di, non calcolare le dimensioni di, o dichiarare puntatori ai tipi gestiti. I tipi gestiti includono tipi di riferimento e struct che contengono campi o proprietà di tipo riferimento.
  • Usare l'operatore sizeof all'interno di un unsafe contesto quando si usano tipi le cui dimensioni non sono una costante in fase di compilazione (CS0233).

Utilizzo predefinito delle istruzioni

  • CS0209: il tipo di una variabile locale dichiarata in un'istruzione 'fixed' deve essere un tipo di puntatore
  • CS0210: è necessario fornire un inizializzatore in una dichiarazione fissa o using di istruzione
  • CS0211: Impossibile accettare l'indirizzo dell'espressione specificata
  • CS0212: è possibile accettare solo l'indirizzo di un'espressione senza prefisso all'interno di un inizializzatore di istruzioni fisse
  • CS0213: Non è possibile usare l'istruzione fixed per prendere l'indirizzo di un'espressione già fissata
  • CS0254: il lato destro di un'assegnazione di istruzione fissa potrebbe non essere un'espressione cast
  • CS0459: Impossibile accettare l'indirizzo di una variabile locale di sola lettura
  • CS0821: Non è possibile correggere variabili locali tipizzate in modo implicito
  • CS1656: Impossibile assegnare a 'variable' perché è un tipo di variabile di sola lettura

Questi errori si verificano quando si usa l'istruzionefixed in modo non corretto. L'istruzione fixed impedisce al Garbage Collector di spostare una variabile mobile e dichiara un puntatore a tale variabile. Per altre informazioni, vedere Codice e puntatori unsafe.

Per usare correttamente l'istruzione fixed :

  • Dichiarare la variabile come tipo di puntatore (CS0209).
  • Specificare un inizializzatore nella dichiarazione dell'istruzione fixed (CS0210).
  • Prendere l'indirizzo solo per espressioni valide: campi, variabili locali e indirezione del puntatore (CS0211). Non prendere l'indirizzo delle espressioni calcolate come la somma di due variabili.
  • Usare l'operatore address-of su espressioni non fisse solo all'interno dell'inizializzatore di dichiarazione fixed (CS0212).
  • Non usare un'istruzione fixed nelle espressioni già fisse (CS0213). Le variabili e i parametri locali in un unsafe metodo sono già fissi nello stack.
  • Non usare espressioni di cast sul lato destro di un'assegnazione di istruzione fixed (CS0254).
  • Non prendere l'indirizzo delle variabili locali a sola lettura (CS0459). Le variabili nei foreach cicli, nelle using istruzioni e nelle fixed istruzioni sono di sola lettura. Questo errore non viene più generato dalle versioni correnti del compilatore.
  • Usare tipi espliciti anziché var in fixed istruzioni (CS0821).
  • Non attribuire a variabili in contesti di sola lettura come foreach cicli, using dichiarazioni o fixed istruzioni (CS1656).

Requisiti di contesto non sicuri

  • CS0214: i puntatori e i buffer a dimensione fissa possono essere usati solo in un contesto non sicuro
  • CS0227: Il codice unsafe può essere visualizzato solo se viene compilato con /unsafe
  • CS0244: né 'is' né 'as' sono validi per i tipi di puntatore
  • CS1919: Impossibile usare il tipo non sicuro 'type name' nella creazione di oggetti
  • CS4004: Impossibile await in un contesto non sicuro
  • CS9123: L'operatore '&' non deve essere usato nei parametri o nelle variabili locali nei metodi asincroni
  • CS9360: questa operazione può essere usata solo in un contesto non sicuro
  • CS9361: stackalloc l'espressione senza un inizializzatore all'interno SkipLocalsInit può essere usata solo in un contesto non sicuro
  • CS9362: 'member' deve essere usato in un contesto non sicuro perché è contrassegnato come 'RequiresUnsafe' o 'extern'
  • CS9363: 'member' deve essere usato in un contesto non sicuro perché include puntatori nella firma
  • CS9376: È necessario un contesto non sicuro per il costruttore 'constructor' contrassegnato come 'RequiresUnsafe' o 'extern' per soddisfare il vincolo 'new()' del parametro di tipo 'type parameter' in 'generic type or method'

Questa diagnostica si verifica quando si usano costrutti di codice non sicuri senza il contesto richiesto unsafe o quando si tentano operazioni non consentite con tipi non sicuri. Per ulteriori informazioni, vedere Codice unsafe e puntatori e la unsafe parola chiave.

  • Contrassegnare metodi, tipi o blocchi di codice che usano puntatori o buffer a dimensione fissa con la unsafe parola chiave (CS0214). Il compilatore richiede un contesto non sicuro esplicito per qualsiasi codice che funziona con i tipi di puntatore o i campi del buffer a dimensione fissa.
  • Abilitare l'opzione del compilatore AllowUnsafeBlocks nelle impostazioni del progetto (CS0227). Senza questa opzione, il compilatore rifiuta tutti i unsafe blocchi anche se il codice è altrimenti corretto.
  • Non usare gli operatori is o as con tipi di puntatore (CS0244). Questi operatori di test dei tipi non sono validi per i puntatori perché i puntatori non partecipano alla gerarchia dei tipi.
  • Non usare l'operatore new per creare istanze del tipo di puntatore (CS1919). Per creare oggetti in memoria non gestita, usare l'interoperabilità per chiamare metodi nativi che restituiscono puntatori.
  • Mantenere il codice unsafe separato dal codice asincrono (CS4004). Il compilatore non consente l'uso di espressioni await all'interno del blocco unsafe perché il runtime non può garantire la validità del puntatore tra i punti di sospensione. Creare metodi separati per le operazioni non sicure e chiamarli da metodi asincroni.
  • Non usare l'operatore address-of (&) nei parametri o nelle variabili locali nei metodi asincroni (CS9123). La variabile potrebbe non esistere nello stack quando l'operazione asincrona riprende dopo un punto di sospensione.
  • Contrassegnare le operazioni che comportano costrutti non sicuri (come la dereferenziazione del puntatore, l'uso dell'operatore di indirizzo o l'impiego di sizeof sui tipi non gestiti) con la parola chiave unsafe(CS9360). Nelle regole di sicurezza della memoria aggiornate di C# 15, il compilatore identifica le singole operazioni che richiedono un contesto non sicuro.
  • Usare la keyword unsafe per espressioni stackalloc senza inizializzatori quando viene applicato l'attributo SkipLocalsInit (CS9361). Senza un inizializzatore, la memoria allocata dallo stack contiene dati non inizializzati, ovvero un'operazione non sicura.
  • Usare un unsafe contesto quando si chiamano membri contrassegnati con RequiresUnsafe o extern (CS9362), o membri che hanno puntatori nelle loro firme (CS9363). Il compilatore C# 15 tiene traccia dell'utilizzo di membri non sicuri nel sito di chiamata, non solo nella dichiarazione.
  • Usare un unsafe contesto quando un new() vincolo richiede la chiamata di un costruttore contrassegnato con RequiresUnsafe o extern (CS9376). La creazione di istanze generiche chiama il costruttore in modo implicito, pertanto il contesto chiamante deve essere non sicuro.

Contratti di sicurezza dei membri non sicuri

  • CS9364: il membro non sicuro 'member' non può eseguire l'override del membro sicuro 'member'
  • CS9365: Il membro non sicuro 'member' non può implementare implicitamente il membro sicuro 'member'
  • CS9366: Il membro non sicuro 'member' non può implementare il membro sicuro 'member'
  • CS9367: RequiresUnsafeAttribute non può essere applicato a questo simbolo.
  • CS9368: RequiresUnsafeAttribute è valido solo nelle regole di sicurezza della memoria aggiornate.
  • CS9377: il modificatore 'unsafe' non ha alcun effetto nelle regole di sicurezza della memoria correnti.

Questa diagnostica applica le regole del contratto di sicurezza C# 15 per i membri contrassegnati come non sicuri. Il compilatore garantisce che i membri non sicuri non violano le aspettative di sicurezza stabilite dalle classi e dalle interfacce di base. Per ulteriori informazioni, vedere Codice unsafe e puntatori e la unsafe parola chiave.

  • Non eseguire l'override di un membro di base sicuro con un membro non sicuro (CS9364). Un'estensione deve preservare il contratto di sicurezza del membro di base. Se il membro di base è sicuro, l'override deve anche essere sicuro. Rimuovere il unsafe modificatore o RequiresUnsafeAttribute dal membro sovrascrivente oppure contrassegnare il membro di base come non sicuro.
  • Non implementare in modo implicito un membro di interfaccia sicura con un membro non sicuro (CS9365). Quando un tipo implementa in modo implicito un membro di interfaccia, i chiamanti tramite l'interfaccia prevedono un'operazione sicura. Rimuovere la designazione non sicura dal membro di implementazione o usare l'implementazione esplicita dell'interfaccia.
  • Non implementare in modo esplicito un membro di interfaccia sicura con un membro non sicuro (CS9366). Anche con l'implementazione esplicita, è necessario conservare il contratto di sicurezza del membro dell'interfaccia.
  • Si applica RequiresUnsafeAttribute solo ai tipi di simboli supportati (CS9367). Questo attributo può essere applicato a metodi, proprietà, eventi, costruttori e tipi, ma non tutti i tipi di simboli lo supportano.
  • Abilitare le regole aggiornate di sicurezza della memoria per usare RequiresUnsafeAttribute (CS9368). Questo attributo fa parte del modello di sicurezza della memoria perfezionato di C# 15 e non è riconosciuto nelle regole legacy. Verificare che il progetto sia destinato a una versione del linguaggio che supporti le regole aggiornate.
  • Rimuovere il unsafe modificatore quando non ha alcun effetto (CS9377). In base alle regole di sicurezza della memoria correnti, alcuni contesti non richiedono o traggono vantaggio dal unsafe modificatore. Il compilatore avvisa quando il modificatore non è significativo in modo da poter pulire le annotazioni non necessarie.

Buffer a dimensione fissa

  • CS1641: un campo buffer a dimensione fissa deve avere l'identificatore delle dimensioni della matrice dopo il nome del campo
  • CS1642: i campi del buffer a dimensione fissa possono essere solo membri di struct
  • CS1663: il tipo di buffer a dimensione fissa deve essere uno dei seguenti: bool, byteshortintlong, char, sbyteushortuintulong, o floatdouble
  • CS1665: i buffer a dimensione fissa devono avere una lunghezza maggiore di zero
  • CS1666: non è possibile usare buffer a dimensione fissa contenuti in espressioni senza prefisso. Provare a usare l'istruzione fixed
  • CS1708: è possibile accedere ai buffer a dimensione fissa solo tramite variabili locali o campi
  • CS1716: non usare l'attributo 'System.Runtime.CompilerServices.FixedBuffer'. Usare invece il modificatore di campo 'fixed'
  • CS7092: un buffer fisso può avere una sola dimensione.
  • CS8372: Non usare l'attributo 'System.Runtime.CompilerServices.FixedBuffer' in una proprietà
  • CS9049: un campo fisso non deve essere un campo di riferimento

Questi errori si verificano quando si lavora con buffer a dimensione fissa. I buffer a dimensione fissa sono matrici incorporate direttamente negli struct e vengono usate principalmente per gli scenari di interoperabilità. Per altre informazioni, vedere Buffer a dimensione fissa.

Per dichiarare e usare correttamente buffer a dimensione fissa:

  • Specificare le dimensioni della matrice dopo il nome del campo usando una costante integer positivo (CS1641, CS1665).
  • Dichiarare buffer a dimensione fissa solo in struct, non nelle classi (CS1642). Usare un array regolare se è necessario il campo in una classe.
  • Usare uno dei tipi di elemento supportati: bool, byteshort, , int, long, charsbyteushortuintulongfloat, o double (CS1663).
  • Usare un'istruzione fixed per fissare la struct contenitore prima di accedere al buffer (CS1666).
  • Accedere ai buffer a dimensione fissa solo tramite variabili locali o campi, non tramite espressioni intermedie (CS1708).
  • Usare il fixed modificatore di campo anziché l'attributo System.Runtime.CompilerServices.FixedBuffer (CS1716). Non applicare questo attributo alle proprietà (CS8372).
  • Dichiarare buffer fissi con una sola dimensione (CS7092). I buffer fissi multidimensionali non sono supportati.
  • Non dichiarare campi come buffer a dimensione fissa (ref) (CS9049). I buffer a dimensione fissa devono essere campi valore.

Puntatori di funzione

  • CS8812: impossibile convertire il gruppo di metodi 'method' in un tipo di puntatore non funzione 'type'.

Per ottenere un puntatore a funzione, usare l'operatore address-of con un cast esplicito del tipo di puntatore a funzione. Non utilizzare l'operatore address-of & per assegnare gruppi di metodi a void* o ad altri tipi che non siano puntatori a funzione. Per altre informazioni, vedere Puntatori a funzioni.