Condividi tramite


Risolvere gli errori e gli avvisi correlati ai parametri di tipo generico e agli argomenti di tipo generico

Questo articolo illustra gli errori del compilatore seguenti:

  • CS0080: i vincoli non sono consentiti nelle dichiarazioni non generiche.
  • CS0081: la dichiarazione del parametro di tipo deve essere un identificatore, non un tipo.
  • CS0224: un metodo con vararg non può essere generico, essere in un tipo generico o avere un parametro params.
  • CS0304: impossibile creare un'istanza del tipo di variabile perché non ha il new() vincolo .
  • CS0305: l'uso del tipo generico richiede argomenti di tipo N.
  • CS0306: il tipo non può essere usato come argomento di tipo.
  • CS0307: l'identificatore non è un metodo generico. Se si intende un elenco di espressioni, usare le parentesi intorno all'espressione.
  • CS0308: Il tipo o metodo non generico non può essere usato con argomenti di tipo.
  • CS0310: il tipo deve essere un tipo non astratto con un costruttore pubblico senza parametri per usarlo come parametro nel tipo o nel metodo generico.
  • CS0311: il tipo non può essere usato come parametro T di tipo nel tipo o nel metodo generico. Non esiste alcuna conversione implicita dei riferimenti da type1 a type2.
  • CS0312: il tipo 'type1' non può essere usato come parametro di tipo nel tipo o nel metodo generico. Il tipo nullable 'type1' non soddisfa il vincolo.
  • CS0313: il tipo 'type1' non può essere usato come parametro di tipo nel tipo o nel metodo generico. Il tipo nullable 'type1' non soddisfa il vincolo. I tipi nullable non possono soddisfare alcun vincolo di interfaccia.
  • CS0314: Il tipo non può essere utilizzato come parametro di tipo nel tipo generico o nel metodo. Non esiste alcuna conversione "boxing" o conversione del parametro di tipo.
  • CS0315: il tipo non può essere usato come parametro T di tipo nel tipo o nel metodo generico. Non esiste alcuna conversione boxing.
  • CS0401: il new() vincolo deve essere l'ultimo vincolo specificato.
  • CS0403: Impossibile convertire null in un parametro di tipo perché potrebbe essere un tipo di valore non annullabile. Prendere in considerazione invece l'uso di default(T).
  • CS0405: vincolo duplicato per il parametro di tipo.
  • CS0412: parametro: un parametro, una variabile locale o una funzione locale non può avere lo stesso nome di un parametro di tipo di metodo.
  • CS0413: il parametro di tipo non può essere usato con l'operatore as perché non dispone di un vincolo di tipo di classe né di un class vincolo.
  • CS0417: Identificatore: non può fornire argomenti durante la creazione di un'istanza di un tipo di variabile.
  • CS0449: i classvincoli , structunmanaged, notnull, e default non possono essere combinati o duplicati e devono essere specificati per primi nell'elenco dei vincoli.
  • Parametro di tipo: non è possibile specificare sia una classe di vincolo che il vincolo class o struct.
  • CS0451: il new() vincolo non può essere usato con il struct vincolo .
  • CS0454: dipendenza del vincolo circolare che include il parametro di tipo 1 e il parametro di tipo 2.
  • CS0455: il parametro di tipo eredita vincoli in conflitto.
  • CS0694: il parametro type ha lo stesso nome del tipo o del metodo contenitore.
  • CS0695: T non può implementare entrambe le interfacce perché possono essere unificate per alcune sostituzioni di parametri di tipo.
  • CS0698: un tipo generico non può derivare dal tipo perché è una classe di attributi.
  • CS0702: Il vincolo non può essere una classe speciale.
  • CS0703: accessibilità incoerente: il tipo di vincolo è meno accessibile rispetto alla dichiarazione.
  • CS0706: tipo di vincolo non valido. Un tipo utilizzato come vincolo deve essere un'interfaccia, una classe non sealed o un parametro di tipo.
  • CS0717: classe statica: le classi statiche non possono essere usate come vincoli.
  • CS1961: varianza non valida: il parametro di tipo deve essere valido in base al tipo.
  • CS7002: uso imprevisto di un nome generico.
  • CS8322: Impossibile passare un argomento di tipo dinamico a una funzione locale generica con argomenti di tipo dedotti.
  • CS9011: La parola chiave delegate non può essere usata come vincolo. Intendevi System.Delegate?
  • CS9012: Parola chiave recordinaspettata. Intendevi record struct o record class?
  • CS9338: accessibilità incoerente: il tipo è meno accessibile rispetto alla classe.

Dichiarazione e denominazione dei parametri di tipo

Gli errori seguenti si riferiscono al modo in cui si dichiarano parametri di tipo e nome in tipi e metodi generici:

  • CS0080: i vincoli non sono consentiti nelle dichiarazioni non generiche.
  • CS0081: la dichiarazione del parametro di tipo deve essere un identificatore, non un tipo.
  • CS0412: parametro: un parametro, una variabile locale o una funzione locale non può avere lo stesso nome di un parametro di tipo di metodo.
  • CS0694: il parametro type ha lo stesso nome del tipo o del metodo contenitore.
  • CS9012: parola chiave recordimprevista. Intendevi record struct o record class?

Per correggere questi errori, assicurarsi di dichiarare parametri di tipo con identificatori validi, applicare clausole di vincolo solo a dichiarazioni generiche ed evitare conflitti di denominazione con altri identificatori nell'ambito:

  • Rimuovere la clausola di vincolo dalle dichiarazioni non generice (CS0080). La where clausola può essere usata solo su tipi e metodi generici che dichiarano parametri di tipo, perché i vincoli definiscono i requisiti che gli argomenti di tipo devono soddisfare. Se è necessario applicare vincoli, aggiungere prima i parametri di tipo alla dichiarazione di tipo o metodo. Puoi ad esempio modificare public class MyClass where MyClass : System.IDisposable in public class MyClass<T> where T : System.IDisposable.
  • Sostituire i nomi dei tipi effettivi con gli identificatori nelle dichiarazioni dei parametri di tipo (CS0081). È necessario dichiarare parametri di tipo usando identificatori (ad esempio T, TKeyo TValue) anziché tipi concreti (ad esempio int o string). Lo scopo di un parametro di tipo è quello di fungere da segnaposto che il compilatore sostituisce con i tipi effettivi quando viene usato il tipo o il metodo generico. Puoi ad esempio modificare public void F<int>() in public void F<T>().
  • Rinominare parametri di tipo, variabili locali o parametri per evitare conflitti di denominazione (CS0412, CS0694). I nomi dei parametri di tipo non possono nascondere gli identificatori nello stesso ambito. Non possono corrispondere al nome del tipo o del metodo contenitore. Tali conflitti creano ambiguità sull'identificatore a cui viene fatto riferimento. Ad esempio, se si dispone di un metodo public void F<T>(), non è possibile dichiarare una variabile double T locale all'interno di tale metodo e non è possibile assegnare un nome a un parametro di tipo uguale al tipo contenitore (class C<C>).
  • Usare la sintassi corretta per la dichiarazione di record (CS9012). Quando si dichiara un tipo di record, è necessario usare record class o record struct (o solo record per un tipo riferimento). La record parola chiave da sola non può essere visualizzata nelle posizioni in cui il compilatore prevede una sintassi di dichiarazione di tipo. Ad esempio, se si intende dichiarare un tipo di record, scrivere record class MyRecord o record struct MyRecord, anziché posizionare record dove è attesa una parola chiave diversa.

Per altre informazioni, vedere Generic Type Parameters and Generics (Parametri di tipo generico e generics).

Dichiarazione e ordinamento dei vincoli

Gli errori seguenti sono correlati alla sintassi e all'ordinamento dei vincoli sui parametri di tipo generico:

  • CS0401: il new() vincolo deve essere l'ultimo vincolo specificato.
  • CS0449: i classvincoli , structunmanaged, notnull, e default non possono essere combinati o duplicati e devono essere specificati per primi nell'elenco dei vincoli.
  • CS0450: Parametro di tipo: non è possibile specificare sia una classe di vincolo che il vincolo class o struct.
  • CS0451: il new() vincolo non può essere usato con il struct vincolo .
  • CS9011: La parola chiave delegate non può essere usata come vincolo. Intendevi System.Delegate?

I vincoli sui parametri di tipo devono seguire un ordine specifico: i vincoli primari (class, , structunmanagednotnull, o default) vengono prima, seguiti da vincoli di interfaccia o di classe e infine il vincolo del new() costruttore. Alcuni vincoli si escludono a vicenda e non possono essere combinati.

Per correggere questi errori:

  • Posizionare il new() vincolo alla fine dell'elenco di vincoli (CS0401). Il new() vincolo deve essere visualizzato dopo tutti gli altri vincoli. Puoi ad esempio modificare where T : new(), IDisposable in where T : IDisposable, new().
  • Inserire prima i vincoli primari e non combinare vincoli che si escludono a vicenda (CS0449). È possibile specificare al massimo uno di class, struct, unmanaged, notnullo defaulte deve essere visualizzato per primo nell'elenco dei vincoli. I vincoli class e struct si escludono reciprocamente, così come class e unmanaged. In un contesto nullable, class implica già notnull, in modo che non possano essere combinati.
  • Non combinare un vincolo di classe specifico con struct (CS0450). Se un parametro di tipo è vincolato a un tipo di classe specifico, è implicitamente un tipo riferimento, che contraddice il struct vincolo. Rimuovere il vincolo della classe o il struct vincolo .
  • Non combinare new() con struct (CS0451). Tutti i tipi valore (struct) in modo implicito hanno un costruttore pubblico senza parametri, quindi il new() vincolo è ridondante se combinato con struct. Rimuovere il new() vincolo quando si usa struct.
  • Sostituire delegate con System.Delegate nelle clausole di vincolo (CS9011). La delegate parola chiave viene usata per dichiarare i tipi delegati, non come vincolo. Per vincolare un parametro di tipo ai tipi delegati, usare System.Delegate come tipo di vincolo. Puoi ad esempio modificare where T : delegate in where T : System.Delegate.

L'esempio seguente mostra l'ordinamento corretto dei vincoli:

using System;

// Primary constraint first, then interface constraints, then new()
class C<T> where T : class, IDisposable, new() { }

// struct doesn't need new() - it's implicit
class D<T> where T : struct, IComparable { }

// Delegate constraint using System.Delegate
class E<T> where T : System.Delegate { }

Per ulteriori informazioni, consultare Vincoli sui parametri di tipo.

Conteggio e utilizzo degli argomenti di tipo

Gli errori seguenti riguardano la corretta specifica del numero e del tipo di argomenti di tipo per tipi e metodi generici:

  • CS0224: un metodo con vararg non può essere generico, essere in un tipo generico o avere un parametro params.
  • CS0305: l'uso del tipo generico richiede argomenti di tipo N.
  • CS0306: il tipo non può essere usato come argomento di tipo.
  • CS0307: l'identificatore non è un metodo generico. Se si intende un elenco di espressioni, usare le parentesi intorno all'espressione.
  • CS0308: Il tipo o metodo non generico non può essere utilizzato con argomenti di tipo.
  • CS7002: uso imprevisto di un nome generico.

Per correggere questi errori, assicurarsi di specificare il numero esatto di argomenti di tipo richiesti dalla dichiarazione generica. Usare solo tipi validi come argomenti di tipo. Non applicare argomenti di tipo a costrutti non generici:

  • Rimuovere i parametri di tipo generico o contenere dichiarazioni di tipo generico dai metodi che usano __arglist (CS0224). La __arglist parola chiave non è compatibile con i generics perché i meccanismi di runtime per la gestione degli elenchi di argomenti delle variabili sono in conflitto con la sostituzione del tipo necessaria per i parametri di tipo generico. Questa restrizione si applica anche alla params parola chiave se usata in combinazione con metodi o metodi generici all'interno di tipi generici.
  • Specificare il numero esatto di argomenti di tipo specificati nella dichiarazione di tipo o metodo generico (CS0305). Ogni parametro di tipo generico dichiarato nella definizione deve avere un argomento di tipo corrispondente quando viene creata un'istanza del tipo generico. Il compilatore deve conoscere il tipo concreto da sostituire per ogni parametro di tipo. Ad esempio, se una classe viene dichiarata come class MyList<T>, è necessario specificare esattamente un argomento di tipo quando lo si usa, ad esempio MyList<int>, non MyList<int, string>.
  • Usare solo tipi validi come argomenti di tipo (CS0306). I tipi puntatore, ad esempio int* o char*, non possono essere usati come argomenti di tipo perché i tipi generici richiedono tipi gestiti che il Garbage Collector può tenere traccia e i tipi di puntatore non sono gestiti. Se è necessario utilizzare puntatori in un contesto generico, considera l'utilizzo di IntPtr oppure la ristrutturazione del codice per evitare di combinare i generici con il codice non sicuro.
  • Rimuovere la sintassi dell'argomento di tipo dai costrutti non generici (CS0307, CS0308). Gli argomenti di tipo racchiusi tra parentesi angolari (ad esempio <int>) possono essere applicati solo a tipi e metodi generici che dichiarano parametri di tipo. È necessario rimuovere completamente gli argomenti di tipo o assicurarsi di importare lo spazio dei nomi contenente la versione generica del tipo. Ad esempio, IEnumerator<T> richiede la using System.Collections.Generic; direttiva , mentre IEnumerator è in System.Collections.
  • Rimuovere i parametri di tipo dalle dichiarazioni che non supportano generics (CS7002). Alcuni costrutti, ad esempio enumerazioni, non possono essere generici. Se è necessario un contenitore generico per i valori di enumerazione, è consigliabile usare invece una classe o uno struct generico.

Per altre informazioni, vedere Generic Type Parameters and Generics (Parametri di tipo generico e generics).

Vincoli del costruttore

Gli errori seguenti sono correlati al new() vincolo sui parametri di tipo generico:

  • CS0304: impossibile creare un'istanza del tipo di variabile perché non ha il new() vincolo .
  • CS0310: il tipo deve essere un tipo non astratto con un costruttore pubblico senza parametri per usarlo come parametro nel tipo o nel metodo generico.
  • CS0417: Identificatore: non può fornire argomenti durante la creazione di un'istanza di un tipo di variabile.

Per correggere questi errori, aggiungere il new() vincolo ai parametri di tipo di cui è necessario creare un'istanza, assicurarsi che gli argomenti di tipo abbiano costruttori pubblici senza parametri ed evitare di passare argomenti durante la costruzione di istanze di parametri di tipo:

  • Aggiungere il new() vincolo alla dichiarazione del parametro di tipo (CS0304). Quando si usa l'operatore per creare un'istanza new di un parametro di tipo all'interno di un tipo o un metodo generico, il compilatore deve essere in grado di garantire che qualsiasi argomento di tipo fornito in fase di esecuzione disponga di un costruttore senza parametri disponibile. Il new() vincolo fornisce questa garanzia in fase di compilazione, consentendo al compilatore di generare il codice di istanziazione appropriato. Ad esempio, se si dispone di class C<T> con un membro T t = new T();, è necessario modificare la dichiarazione in class C<T> where T : new().
  • Assicurarsi che gli argomenti di tipo usati con new() parametri di tipo vincolato abbiano costruttori pubblici senza parametri (CS0310). Quando un tipo o un metodo generico dichiara un new() vincolo su un parametro di tipo, qualsiasi tipo concreto usato come argomento di tipo deve essere non astratto e deve fornire un costruttore pubblico senza parametri. Se un tipo ha solo costruttori non pubblici (ad esempio private o protected costruttori) o ha solo costruttori con parametri, non può soddisfare il new() vincolo. Per correggere questo errore, aggiungere un costruttore pubblico senza parametri al tipo o usare un argomento di tipo diverso che ne ha già uno.
  • Rimuovere gli argomenti del costruttore quando si crea un'istanza dei parametri di tipo (CS0417). Il new() vincolo garantisce solo l'esistenza di un costruttore senza parametri, pertanto non è possibile passare argomenti a new T(arguments) perché il compilatore non è in grado di verificare che un costruttore con tali tipi di parametro specifici esista nei tipi sostituiti da T. Se è necessario costruire istanze con argomenti specifici, è consigliabile usare metodi factory, modelli factory astratti o vincoli di interfaccia o classi di base specifici che definiscono il comportamento di costruzione necessario.

Per altre informazioni, vedere Vincoli per i parametri di tipo e il new() vincolo.

Soddisfazione dei vincoli e trasformazioni

Gli errori seguenti sono correlati agli argomenti di tipo che non soddisfano i vincoli dei parametri di tipo generico:

  • CS0311: il tipo non può essere usato come parametro T di tipo nel tipo o nel metodo generico. Non esiste alcuna conversione implicita dei riferimenti.
  • CS0312: il tipo non può essere usato come parametro di tipo nel tipo o nel metodo generico. Il tipo nullable non soddisfa il vincolo.
  • CS0313: il tipo non può essere usato come parametro di tipo nel tipo o nel metodo generico. Il tipo nullable non soddisfa il vincolo. I tipi nullable non possono soddisfare alcun vincolo di interfaccia.
  • CS0314: il tipo non può essere usato come parametro di tipo nel tipo o nel metodo generico. Non esiste alcuna conversione boxing o conversione di parametri di tipo.
  • CS0315: Il tipo non può essere usato come parametro T di tipo nel tipo o nel metodo generico TypeorMethod<T>. Non esiste alcuna conversione per boxing.

Per correggere questi errori, usare argomenti di tipo che soddisfano tutti i vincoli tramite conversioni appropriate, assicurarsi che le classi derivate ripetano vincoli di classe base e comprendere che i tipi valore nullable hanno requisiti speciali per i vincoli:

  • Modificare l'argomento di tipo in uno che ha una conversione di riferimento implicita verso il tipo di vincolo (CS0311). Quando un parametro di tipo ha un vincolo come where T : BaseType, qualsiasi argomento di tipo deve essere convertibile in BaseType tramite una conversione implicita dei riferimenti o una conversione di identità. L'argomento di tipo deve essere BaseType stesso, derivare da BaseTypeo implementare BaseType se si tratta di un'interfaccia. Le conversioni numeriche implicite (ad esempio da short a int) non soddisfano vincoli di parametro di tipo generico perché queste conversioni sono conversioni di valori, non conversioni di riferimento.
  • Ripetere i vincoli dei parametri di tipo della classe base in qualsiasi dichiarazione di classe derivata (CS0314). Quando una classe generica derivata eredita da una classe generica di base con vincoli sui relativi parametri di tipo, la classe derivata deve dichiarare gli stessi vincoli sui parametri di tipo corrispondenti. È necessario ripetere questi vincoli perché il compilatore deve verificare che gli argomenti di tipo forniti alla classe derivata soddisfino i requisiti della classe base. Ad esempio, se si dispone public class A<T> where T : SomeClassdi , qualsiasi classe derivata da tale classe deve essere dichiarata come public class B<T> : A<T> where T : SomeClass.
  • Usare tipi valore non nullable o modificare il tipo di vincolo (CS0312, CS0313). I tipi valore nullable (ad esempio int?) sono distinti dai tipi valore sottostanti e non soddisfano gli stessi vincoli. Non esiste alcuna conversione implicita tra int? e int, e i tipi di valore nullable non possono soddisfare i vincoli di interfaccia perché lo stesso involucro nullable non implementa l'interfaccia, anche se il tipo di valore sottostante lo fa. Per correggere questi errori, usare la forma non nullable del tipo di valore come argomento di tipo oppure modificare il vincolo in modo da accettare object o un tipo di riferimento nullable, se appropriato.
  • Verificare che gli argomenti di tipo soddisfino i vincoli di tipo riferimento o di classe (CS0315). Quando un parametro di tipo è vincolato a un tipo di classe (ad esempio where T : SomeClass), non è possibile usare un tipo valore (struct) come argomento di tipo perché non esiste alcuna conversione boxing che soddisfa la relazione di vincolo. Il vincolo richiede un tipo riferimento con una relazione di ereditarietà o implementazione con il tipo di vincolo. Per risolvere questo errore, modificare la struct in una classe, se appropriato a livello semantico, o rimuovere il vincolo di classe se il tipo generico può funzionare con i tipi di valore.

Per altre informazioni, vedere Vincoli sui parametri di tipo e conversioni implicite.

Restrizioni di utilizzo dei tipi generici

Gli errori seguenti riguardano le restrizioni relative alla modalità di utilizzo dei tipi generici:

  • CS0403: Impossibile convertire null nel parametro di tipo perché potrebbe essere un tipo di valore che non ammette valori null. Si consideri invece l'utilizzo di default(T).
  • CS0413: il parametro di tipo non può essere usato con l'operatore as perché non dispone di un vincolo di tipo di classe né di un class vincolo.
  • CS0695: Il tipo non può implementare entrambe le interfacce poiché potrebbero unificarsi per alcune sostituzioni di parametri di tipo.
  • CS0698: un tipo generico non può derivare dal tipo perché è una classe di attributi.
  • CS8322: impossibile passare l'argomento con tipo dinamico alla funzione locale generica con argomenti di tipo dedotti.
  • CS9338: accessibilità incoerente: il tipo è meno accessibile rispetto alla classe.

Per correggere questi errori, usare default anziché null per i parametri di tipo non vincolati, aggiungere vincoli di classe quando si usa l'operatore as, evitare conflitti di unificazione dell'interfaccia, non creare classi di attributi generici e assicurarsi che gli argomenti di tipo corrispondano alla visibilità dei membri contenenti.

  • Sostituire null le assegnazioni con default(T) o aggiungere un class vincolo (CS0403). Quando si assegna null a un parametro di tipo non vincolato, il compilatore non può garantire che l'argomento di tipo sia un tipo riferimento che accetta null valori, perché potrebbe essere un tipo di valore come int o struct, che non può essere null. Per risolvere questo errore, usare default(T), che fornisce il valore predefinito appropriato per qualsiasi tipo (null per i tipi riferimento, zero o vuoto per i tipi valore), o aggiungere un vincolo class al parametro di tipo se si necessita specificamente della semantica del tipo di riferimento e si desidera consentire le assegnazioni di null.
  • Aggiungere un vincolo di tipo specifico o un class quando si usa l'operatore as (CS0413). L'operatore as esegue un cast di tipi sicuri che restituisce null se la conversione non riesce, ma questo comportamento non è compatibile con i tipi valore perché i tipi valore non possono essere null. Quando si usa as con un parametro di tipo non vincolato, il compilatore non può garantire che l'argomento di tipo non sia un tipo valore, quindi rifiuta il codice. Per correggere questo errore, aggiungere un class vincolo o un vincolo di tipo riferimento specifico (ad esempio where T : SomeClass) per assicurarsi che il parametro di tipo sia sempre un tipo riferimento in grado di gestire correttamente il null risultato di un cast non riuscito.
  • Evitare di implementare più volte la stessa interfaccia generica con parametri di tipo che potrebbero unificare (CS0695). Quando una classe implementa più volte un'interfaccia generica con parametri di tipo diversi (ad esempio class G<T1, T2> : I<T1>, I<T2>), esiste il rischio che un utente possa crearne un'istanza con lo stesso tipo per entrambi i parametri (G<int, int>), che creerebbe un conflitto perché la classe implementerebbe I<int> due volte. Per risolvere questo errore, implementare l'interfaccia una sola volta, ristrutturare i parametri di tipo per impedire l'unificazione o usare classi non generiche separate per specializzazioni diverse.
  • Rimuovere i parametri di tipo generico dalle classi di attributi (CS0698).

    Annotazioni

    Questo errore non viene generato nelle versioni correnti di C#, perché gli attributi generici sono ora supportati.

  • Specificare in modo esplicito gli argomenti di tipo quando si passano valori dinamici a funzioni locali generiche (CS8322). Quando si passa un dynamic argomento a una funzione locale generica, il compilatore non può dedurre argomenti di tipo perché il tipo effettivo non è noto fino al runtime. Per correggere l'errore, specificare in modo esplicito l'argomento di tipo ( ad esempio , LocalFunc<int>(d)), eseguire il cast del valore dinamico al tipo previsto oppure usare una variabile non dinamica.
  • Verificare che gli argomenti di tipo usati nelle firme pubbliche o protette siano accessibili almeno quanto il membro che li usa (CS9338). Un membro generico pubblico o protetto deve usare argomenti di tipo accessibili pubblicamente. In caso contrario, il codice esterno non è riuscito a fare riferimento correttamente o a usare la firma del membro. Ad esempio, se si ha public class Container<T> dove T è un tipo interno, gli assembly esterni possono visualizzare Container ma non possono funzionare correttamente con esso perché non possono vedere T. Per correggere questo errore, potete rendere pubblico l'argomento di tipo oppure ridurre l'accessibilità del membro che lo utilizza per allinearla all'accessibilità dell'argomento di tipo.

Per altre informazioni, vedere Vincoli sui parametri di tipo, espressioni di valore predefinite e Attributi.

Tipi di vincolo validi

Gli errori seguenti si riferiscono all'uso di tipi non validi come vincoli sui parametri di tipo generico:

  • CS0405: vincolo duplicato per il parametro di tipo.
  • CS0702: Il vincolo non può essere una classe speciale.
  • CS0703: accessibilità incoerente: il tipo di vincolo è meno accessibile rispetto alla dichiarazione.
  • CS0706: tipo di vincolo non valido. Un tipo utilizzato come vincolo deve essere un'interfaccia, una classe non sealed o un parametro di tipo.
  • CS0717: static class: le classi statiche non possono essere usate come vincoli.

Un vincolo deve essere un'interfaccia, una classe non sealed (non sigillata) o un parametro di tipo. Alcuni tipi non sono validi come vincoli a causa del loro significato speciale nel sistema di tipi .NET o perché non possono essere ereditati.

Per correggere questi errori:

  • Rimuovere vincoli duplicati (CS0405). Ogni vincolo può essere visualizzato una sola volta in una clausola di vincolo. Se è presente where T : I, I, rimuovere il duplicato.
  • Non usare classi speciali come vincoli (CS0702). I tipi Object, Arraye ValueType non possono essere usati come vincoli. Ogni tipo deriva già da Object, quindi vincolare a esso non fornisce alcun valore. Array e ValueType sono tipi di base astratti che non possono essere ereditati direttamente. Se è necessario un comportamento simile a una matrice, usare IList<T> o IEnumerable<T> .
  • Assicurarsi che i tipi di vincolo siano accessibili almeno come il tipo generico (CS0703). Un tipo generico pubblico non può avere vincoli usando tipi interni, perché il codice esterno non sarebbe in grado di fornire argomenti di tipo validi. Rendere pubblico il tipo di vincolo o ridurre l'accessibilità del tipo generico.
  • Usare solo interfacce, classi non sigillate o parametri di tipo come vincoli (CS0706). Non è possibile usare matrici, classi sigillate, struct, enumerazioni o altri tipi non validi come vincoli. Se è necessario un comportamento specifico, è consigliabile usare un'interfaccia implementata dai tipi desiderati.
  • Non usare classi statiche come vincoli (CS0717). Le classi statiche non possono essere estese perché contengono solo membri statici. Nessun tipo può esistere che deriva da una classe statica, rendendolo inutile come vincolo. Usare invece una classe o un'interfaccia non statica.

L'esempio seguente mostra i tipi di vincolo validi:

public interface IMyInterface { }
public class MyBaseClass { }

// Valid: interface constraint
class A<T> where T : IMyInterface { }

// Valid: non-sealed class constraint
class B<T> where T : MyBaseClass { }

// Valid: type parameter constraint
class C<T, U> where T : U { }

Per ulteriori informazioni, consultare Vincoli sui parametri di tipo.

Conflitti di vincoli e dipendenze circolari

Gli errori seguenti sono correlati ai conflitti tra vincoli o dipendenze circolari nelle dichiarazioni di vincolo:

  • CS0454: dipendenza del vincolo circolare che include il parametro di tipo 1 e il parametro di tipo 2.
  • CS0455: il parametro di tipo eredita vincoli in conflitto.

I vincoli non possono creare dipendenze circolari e i parametri di tipo non possono ereditare vincoli in conflitto impossibili da soddisfare contemporaneamente.

Per correggere questi errori:

  • Eliminare le dipendenze dei vincoli circolari (CS0454). Un parametro di tipo non può dipendere direttamente o indirettamente da se stesso tramite i relativi vincoli. Ad esempio, where T : U where U : T crea una dipendenza circolare perché T dipende da U e U dipende da T. Interrompere il ciclo rimuovendo uno dei vincoli.
  • Rimuovere vincoli ereditati in conflitto (CS0455). Un parametro di tipo non può essere vincolato a più classi non correlate, perché C# non supporta l'ereditarietà di più classi. Analogamente, non può essere vincolato a entrambi struct e a un tipo di classe, poiché questi vincoli si escludono a vicenda. Ristrutturare la gerarchia dei tipi o rimuovere uno dei vincoli in conflitto.

L'esempio seguente illustra i problemi:

// CS0454: Circular dependency - T depends on U and U depends on T
class Circular<T, U> where T : U where U : T { }

// CS0455: Conflicting constraints - U can't derive from both B and B2
public class B { }
public class B2 { }
public class G<T> where T : B
{
    public class N<U> where U : B2, T { }
}

Per ulteriori informazioni, consultare Vincoli sui parametri di tipo.

Varianza dei parametri di tipo

L'errore seguente è correlato ai modificatori di varianza sui parametri di tipo generico:

  • CS1961: varianza non valida: il parametro di tipo deve essere valido in base al tipo.

I modificatori di varianza (in per controvarianza, out per la covarianza) controllano come si usano i parametri di tipo nelle dichiarazioni di interfaccia e delegato. Un parametro di tipo covariante (out) può essere visualizzato solo nelle posizioni di output (tipi restituiti), mentre un parametro di tipo controvariante (in) può essere visualizzato solo nelle posizioni di input (tipi di parametro).

Per correggere l'errore:

  • Usare out (covariante) per i parametri di tipo visualizzati solo nei tipi restituiti. La Covarianza consente di usare un tipo più derivato in cui è previsto un tipo meno derivato.
  • Usare in (controvariante) per i parametri di tipo visualizzati solo nei tipi di parametro. La controvarianza consente di usare un tipo meno derivato in cui è previsto un tipo più derivato.
  • Rimuovere il modificatore di varianza se il parametro di tipo deve essere visualizzato sia nelle posizioni di input che in quella di output.

L'esempio seguente mostra l'utilizzo corretto e errato della varianza:

// Incorrect: out T can't appear in input position
interface IWrong<out T>
{
    void Method(T arg);  // CS1961
}

// Correct: out T only in output positions
interface ICovariant<out T>
{
    T GetValue();
}

// Correct: in T only in input positions
interface IContravariant<in T>
{
    void Process(T arg);
}

// No modifier needed for both input and output
interface IInvariant<T>
{
    T Transform(T arg);
}

Per ulteriori informazioni, vedere Covarianza e controvarianza nei Generici.