Condividi tramite


Risolvere gli errori e gli avvisi nelle dichiarazioni di operatore definite dall'utente

Questo articolo illustra gli errori del compilatore seguenti:

  • CS0056: accessibilità incoerente: il tipo restituito 'type' è meno accessibile dell'operatore 'operator'
  • CS0057: accessibilità incoerente: il tipo di parametro 'type' è meno accessibile dell'operatore 'operator'
  • CS0215: il tipo restituito di operatore True o False deve essere bool
  • CS0216: l'operatore 'operator' richiede anche la definizione di un operatore corrispondente 'missing_operator'
  • CS0217: per essere applicabile come operatore a corto circuito, un operatore logico definito dall'utente ('operator') deve avere lo stesso tipo restituito del tipo dei relativi 2 parametri.
  • CS0218: il tipo ('type') deve contenere dichiarazioni di operatore true e operator false
  • CS0448: il tipo restituito per ++ o -- operatore deve essere il tipo contenitore o derivato dal tipo contenitore
  • CS0552: 'routine di conversione': conversione definita dall'utente in/dall'interfaccia
  • CS0553: 'routine di conversione': conversione definita dall'utente in/dalla classe base
  • CS0554: 'conversion routine' : conversione definita dall'utente in/da classe derivata
  • CS0555: l'operatore definito dall'utente non può accettare un oggetto del tipo di inclusione e convertirlo in un oggetto del tipo di inclusione
  • CS0556: la conversione definita dall'utente deve essere verso o da il tipo contenitore
  • CS0557: conversione definita dall'utente duplicata nel tipo
  • CS0558: l'operatore definito dall'utente deve essere dichiarato statico e pubblico
  • CS0559: il tipo di parametro per ++ o -- l'operatore deve essere il tipo contenitore
  • CS0562: il parametro di un operatore unario deve essere il tipo contenitore
  • CS0563: uno dei parametri di un operatore binario deve essere il tipo contenitore
  • CS0564: il primo operando di un operatore di spostamento sovraccarico deve avere lo stesso tipo del tipo contenente e il tipo del secondo operando deve essere int
  • CS0567: Le interfacce non possono contenere operatori
  • CS0590: gli operatori definiti dall'utente non possono restituire void
  • CS0660: il tipo definisce operator == o operator != ma non esegue l'override Object.Equals(object o)
  • CS0661: il tipo definisce operator == o operator != ma non esegue l'override Object.GetHashCode()
  • CS0715: Le classi statiche non possono contenere operatori definiti dall'utente
  • CS1037: Previsto operatore sovraccaricabile
  • CS1553: La dichiarazione non è valida; usare 'modifier operator <dest-type> (...' invece
  • CS8930: l'implementazione esplicita di un operatore definito dall'utente deve essere statica.
  • CS8931: l'implementazione esplicita deve essere dichiarata pubblica per implementare il membro dell'interfaccia nel tipo.
  • CS9023: Impossibile controllare l'operatore.
  • CS9024: L'operatore non può essere reso non verificato.
  • CS9025: l'operatore richiede anche la dichiarazione di una versione non controllata corrispondente.
  • CS9308: l'operatore definito dall'utente deve essere dichiarato pubblico.
  • CS9310: il tipo restituito per questo operatore deve essere void.
  • CS9311: il tipo non implementa il membro dell'interfaccia. Il tipo non può implementare il membro perché uno di essi non è un operatore.
  • CS9312: il tipo non può eseguire l'override del membro ereditato perché uno di essi non è un operatore.
  • CS9313: L'operatore di assegnazione composto sovraccarico accetta un parametro.
  • CS9340: l'operatore non può essere applicato agli operandi. Viene visualizzato il candidato inapplicabile più vicino.
  • CS9341: l'operatore non può essere applicato all'operando. Viene visualizzato il candidato inapplicabile più vicino.
  • CS9342: La risoluzione degli operatori è ambigua tra i membri elencati di seguito.

Requisiti di firma dell'operatore

  • CS0448: il tipo restituito per ++ o -- operatore deve essere il tipo contenitore o derivato dal tipo contenitore.
  • CS0559: il tipo di parametro per ++ o -- operatore deve essere il tipo contenitore.
  • CS0562: il parametro di un operatore unario deve essere il tipo contenitore.
  • CS0563: uno dei parametri di un operatore binario deve essere il tipo contenitore.
  • CS0564: il primo operando di un operatore di spostamento sovraccaricato deve avere lo stesso tipo del tipo che lo contiene e il tipo del secondo operando deve essere int.
  • CS0567: le interfacce non possono contenere operatori.
  • CS0590: gli operatori definiti dall'utente non possono restituire void.
  • CS9310: il tipo restituito per questo operatore deve essere void.
  • CS9340: l'operatore non può essere applicato agli operandi. Viene visualizzato il candidato inapplicabile più vicino.
  • CS9341: l'operatore non può essere applicato all'operando. Viene visualizzato il candidato inapplicabile più vicino.
  • CS9342: La risoluzione dell'operatore è ambigua tra i membri seguenti.

Per dichiarare gli operatori con firme corrette, seguire questi requisiti per il tipo di operatore specifico. Per ulteriori informazioni, vedere Sovraccarico degli operatori.

  • Restituisce il tipo contenitore (o un tipo derivato) dagli operatori ++ e -- (CS0448).
  • Usare il tipo contenitore come parametro per gli operatori ++ e -- (CS0559).
  • Usare il tipo che contiene come parametro per gli operatori unari (CS0562).
  • Includere il tipo contenitore come almeno un parametro negli operatori binari (CS0563).
  • Utilizzare il tipo che contiene come primo parametro e int come secondo per gli operatori shift (CS0564).
  • Non dichiarare gli operatori nelle interfacce (CS0567). Le interfacce non possono contenere implementazioni dell'operatore.
  • Restituisce un tipo non void dalla maggior parte degli operatori (CS0590), ad eccezione di operatori specifici che richiedono void la restituzione (CS9310).
  • Fornire sovraccarichi degli operatori che accettano i tipi di parametri corretti per evitare errori di risoluzione (CS9340, CS9341).
  • Disambiguare le chiamate degli operatori usando cast espliciti o fornendo overload più specifici (CS9342).

Importante

I requisiti di firma per gli operatori binari statici e i corrispondenti operatori di assegnazione composta di istanza sono diversi. Assicurarsi che la firma corrisponda alla dichiarazione desiderata.

L'esempio seguente illustra gli errori di firma:

class C1
{
    public static int operator ++(C1 c) => 0;   // CS0448
    public static C1 operator --(C1 c) => null;   // OK
}
public class C2
{
    public static implicit operator int(C2 x) => 0;
    public static implicit operator C2(int x) => new C2();
    public static int operator ++(int aa) => 0;  // CS0559
}
public class C3
{
    public static implicit operator int(C3 x) => 0;
    public static implicit operator C3(int x) => null;
    public static C3 operator +(int aa) => 0;   // CS0562
}
public class C4
{
    public static implicit operator int(C4 x) => 0;
    public static implicit operator C4(int x) => null;
    public static int operator +(int aa, int bb) => 0;   // CS0563
}
class C5
{
    // To correct, change second operand to int, like so:
    // public static int operator << (C c1, int c2)
    public static int operator <<(C5 c1, C5 c2) => 0; // CS0564
}
interface IA
{
    int operator +(int aa, int bb);   // CS0567
}
public class C6
{
    public static void operator +(C6 A1, C6 A2) { }  // CS0590
}

Requisiti di dichiarazione dell'operatore

  • CS0558: l'operatore definito dall'utente deve essere dichiarato statico e pubblico.
  • CS0715: le classi statiche non possono contenere operatori definiti dall'utente.
  • CS1037: Previsto operatore sovraccaricabile.
  • CS1553: La dichiarazione non è valida; usare 'modifier operator <dest-type> (...' invece.
  • CS8930: l'implementazione esplicita di un operatore definito dall'utente deve essere statica.
  • CS8931: L'implementazione esplicita deve essere dichiarata pubblica per implementare un membro dell'interfaccia di tipo.
  • CS9308: l'operatore definito dall'utente deve essere dichiarato pubblico.

Per dichiarare correttamente gli operatori, seguire questi requisiti per i modificatori e i tipi contenenti. Per altre informazioni, vedere Sovraccarico degli operatori e Operatori di conversione definiti dall'utente.

  • Dichiara gli operatori con sia static sia public come modificatori (CS0558, CS9308).
  • Non dichiarare gli operatori nelle classi statiche (CS0715). Usare classi o struct regolari.
  • Usare simboli di operatore validi e sovraccaricabili (CS1037).
  • Seguire la sintassi corretta per gli operatori di conversione: public static implicit/explicit operator <dest-type>(<source-type> parameter) (CS1553).
  • Assicurarsi che le implementazioni esplicite dell'interfaccia degli operatori siano static (CS8930) e public (CS8931).

L'esempio seguente illustra gli errori di dichiarazione:

public class C
{
    static implicit operator int(C aa) => 0;   // CS0558, add public
}
public static class C1
{
    public static int operator +(C1 c) => 0;  // CS0715
}
class C2
{
    public static int implicit operator (C2 f) => 6;   // CS1553
}

Accessibilità incoerente

  • CS0056: accessibilità incoerente: il tipo restituito 'type' è meno accessibile dell'operatore 'operator'.
  • CS0057: accessibilità incoerente: il tipo di parametro 'type' è meno accessibile dell'operatore 'operator'.

Per garantire un'accessibilità coerente nelle dichiarazioni degli operatori, rendere accessibili pubblicamente tutti i tipi usati negli operatori pubblici. Per altre informazioni, vedere Modificatori di accesso.

  • Assicurarsi che i tipi restituiti abbiano almeno la stessa accessibilità dell'operatore (CS0056).
  • Verificare che i tipi di parametro abbiano almeno la stessa accessibilità dell'operatore (CS0057).

Quando si dichiara un public operatore, anche tutti i tipi usati come parametri o valori restituiti devono essere accessibili pubblicamente.

L'esempio seguente illustra gli errori di accessibilità:

class C { }

public class C2
{
    public static implicit operator C(C2 a) => new C();   // CS0056
}

public class C3
{
    public static implicit operator C3(C c) => new C3();   // CS0057
}

Restrizioni di conversione definite dall'utente

  • CS0552: conversione definita dall'utente in/dall'interfaccia.
  • CS0553: conversione definita dall'utente in/dalla classe di base.
  • CS0554: conversione definita dall'utente in/dalla classe derivata.
  • CS0555: l'operatore definito dall'utente non può accettare un oggetto del tipo di inclusione e convertirlo in un oggetto del tipo di inclusione.
  • CS0556: La conversione definita dall'utente deve essere verso o da il tipo contenitore.
  • CS0557: Conversione definita dall'utente duplicata nel tipo.

Per creare operatori di conversione definiti dall'utente validi, seguire queste restrizioni. Per altre informazioni, vedere Operatori di conversione definiti dall'utente.

  • Non definire conversioni da o verso interfacce (CS0552). Usare invece implementazioni esplicite dell'interfaccia.
  • Non definire conversioni da o verso classi di base (CS0553). La conversione esiste già tramite ereditarietà.
  • Non definire conversioni da o verso classi derivate (CS0554). La conversione esiste già tramite ereditarietà.
  • Non definire conversioni dal tipo di inclusione a se stesso (CS0555). Questa conversione è implicita.
  • Verificare che almeno un tipo nella conversione sia il tipo contenitore (CS0556). Non è possibile definire conversioni tra due tipi esterni.
  • Non definire conversioni duplicate (CS0557). Ogni operatore di conversione deve essere univoco.

L'esempio seguente illustra gli errori di restrizione della conversione:

public interface I
{
}
public class C
{
    public static implicit operator I(C aa) => default;// CS0552
}

public class B
{
}
public class D : B
{
    public static implicit operator B(D aa) => new B();// CS0553
}

public class B2
{
    // delete the conversion routine to resolve CS0554
    public static implicit operator B2(D2 d) => new B2();// CS0554
}
public class D2 : B2 { }

public class C2
{
    public static implicit operator C2(C2 aa) => new C2();   // CS0555
}

public class C3
{
    public static implicit operator int(byte aa) => 0;   // CS0556
}

public class C4
{
    public static implicit operator int(C4 aa) => 0;

    // CS0557, delete duplicate
    public static explicit operator int(C4 aa) => 0;
}

Operatori booleani e a corto circuito

  • CS0215: il tipo restituito di operatore true o false deve essere bool.
  • CS0216: l'operatore richiede anche la definizione di un operatore corrispondente.
  • CS0217: per essere applicabile come operatore a corto circuito, un operatore logico definito dall'utente deve avere lo stesso tipo restituito del tipo dei relativi 2 parametri.
  • CS0218: il tipo deve contenere dichiarazioni di operatore true e operator false.

Per definire correttamente gli operatori logici, seguire questi requisiti di associazione e firma. Per altre informazioni, vedere operatori true e false, operatori logici booleani e operatori logici definiti dall'utente.

  • Restituisce bool da operator true e operator false (CS0215).
  • Definire gli operatori associati obbligatori (CS0216):
    • operator == Richiede operator !=
    • operator < Richiede operator >
    • operator <= Richiede operator >=
    • operator true Richiede operator false
  • Trova la corrispondenza tra il tipo restituito e i tipi di parametro per gli operatori a corto-circuito (& e |) che sono compatibili con tipi personalizzati (CS0217).
  • Implementare sia operator true che operator false quando si utilizzano tipi personalizzati in contesti booleani come && e || (CS0218).

L'esempio seguente illustra gli errori dell'operatore logico:

class C
{
    public static int operator true(C c) => 0;   // CS0215
    public static int operator false(C c) => 0; // CS0215
}

class C2
{
    public static bool operator ==(C2 left, C2 right) => left.Equals(right);   // CS0216

    public override bool Equals(object? o) => base.Equals(o);
    public override int GetHashCode() => base.GetHashCode();
}

public class C3
{
    public static bool operator true(C3 f) => false;
    public static bool operator false(C3 f) => true;
    public static implicit operator int(C3 x) => 0;
    public static int operator &(C3 f1, C3 f2) => new C3();  // CS0217
}

public class C4
{
    public static implicit operator int(C4 x) => 0;
    public static C4 operator &(C4 f1, C4 f2) => new C4();

    public static void Main()
    {
        C4 f = new C4();
        int i = f && f;   // CS0218, requires operators true and false
    }
}

Operatori controllati

  • CS9023: L'operatore non può essere verificato
  • CS9024: L'operatore non può essere reso non controllato
  • CS9025: l'operatore Checked richiede anche la dichiarazione di una versione non controllata corrispondente

Per usare correttamente gli operatori controllati, seguire questi requisiti. Per altre informazioni, vedere Operatori aritmetici e Operatori controllati definiti dall'utente.

  • Applicare checked o unchecked parole chiave solo agli operatori aritmetici supportati: +, , -*, /++, --, , e conversioni esplicite (CS9023, CS9024).
  • Specificare le versioni verificate e non verificate quando si dichiara un operatore verificato (CS9025). Il compilatore deve gestire entrambi contesti diversi.

Requisiti di interfaccia e ereditarietà

  • CS9311: il tipo non implementa il membro dell'interfaccia. Il tipo non può implementare il membro perché uno di essi non è un operatore
  • CS9312: Il tipo non può eseguire l'override del membro ereditato perché uno di essi non è un operatore
  • CS9313: L'operatore di assegnazione composta in overload accetta un parametro

Per implementare ed eseguire correttamente l'override degli operatori, seguire questi requisiti. Per ulteriori informazioni, vedere Sovraccarico degli operatori e Interfacce.

  • Verificare che le dichiarazioni degli operatori corrispondano alla firma e al tipo di membri dell'interfaccia (CS9311). Un operatore non può implementare un membro non operatore.
  • Verificare che i membri ereditati che vengono sottoposti a override siano anche operatori (CS9312). Un operatore non può eseguire l'override di un membro non operatore.
  • Dichiarare operatori di assegnazione composti con un parametro (CS9313). L'operando sinistro è implicitamente this.

Operatori di uguaglianza

  • CS0660: il tipo definisce l'operatore == o l'operatore != ma non esegue l'override di Object.Equals(object o)
  • CS0661: il tipo definisce l'operatore == o l'operatore != ma non esegue l'override di Object.GetHashCode()

Per implementare correttamente l'uguaglianza, eseguire l'override dei metodi corrispondenti Object quando si definiscono operatori di uguaglianza personalizzati. Per altre informazioni, vedere Come definire l'uguaglianza dei valori per un tipo e operatori di uguaglianza.

  • Eseguire l'override Object.Equals quando si definisce operator == o operator != (CS0660).
  • Eseguire l'override Object.GetHashCode quando si definisce operator == o operator != (CS0661).

L'override di questi metodi garantisce un comportamento di uguaglianza coerente tra API e tipi di raccolta diversi.