Teilen über


Beheben von Fehlern und Warnungen in benutzerdefinierten Operatordeklarationen

In diesem Artikel werden die folgenden Compilerfehler behandelt:

  • CS0056: Inkonsistente Zugänglichkeit: Rückgabetyp 'type' ist weniger zugänglich als Operator 'operator'
  • CS0057: Inkonsistente Barrierefreiheit: Parametertyp "type" ist weniger zugänglich als operator "operator"
  • CS0215: Der Rückgabetyp des Operators "True" oder "False" muss bool sein.
  • CS0216: Der Operator "operator" erfordert, dass auch ein übereinstimmende Operator "missing_operator" definiert werden muss.
  • CS0217: Um als Kurzschlussoperator anwendbar zu sein, muss ein benutzerdefinierter logischer Operator ('Operator') den gleichen Rückgabetyp aufweisen wie der Typ seiner 2 Parameter.
  • CS0218: Der Typ ("Typ") muss Deklarationen des Operators "true" und "operator false" enthalten.
  • CS0448: Der Rückgabetyp für ++ oder -- Operator muss der enthaltende Typ oder vom enthaltenden Typ abgeleitet sein.
  • CS0552: "Konvertierungsroutine" : benutzerdefinierte Konvertierung in/von der Schnittstelle
  • CS0553: "Konvertierungsroutine" : benutzerdefinierte Konvertierung in/von der Basisklasse
  • CS0554: "Konvertierungsroutine" : benutzerdefinierte Konvertierung in/von abgeleiteter Klasse
  • CS0555: Benutzerdefinierter Operator kann kein Objekt des eingeschlossenen Typs übernehmen und in ein Objekt des eingeschlossenen Typs konvertieren.
  • CS0556: Benutzerdefinierte Konvertierung muss von oder zu dem umschließenden Typ erfolgen.
  • CS0557: Doppelte benutzerdefinierte Konvertierung im Typ
  • CS0558: Benutzerdefinierter Operator muss statisch und öffentlich deklariert werden.
  • CS0559: Der Parametertyp für ++ oder -- Operator muss der enthaltende Typ sein.
  • CS0562: Der Parameter eines unären Operators muss der enthaltende Typ sein.
  • CS0563: Einer der Parameter eines binären Operators muss der enthaltende Typ sein.
  • CS0564: Der erste Operand eines überladenen Schichtoperators muss den gleichen Typ wie der enthaltende Typ aufweisen, und der Typ des zweiten Operanden muss int sein.
  • CS0567: Schnittstellen dürfen keine Operatoren enthalten
  • CS0590: Benutzerdefinierte Operatoren können keine void zurückgeben
  • CS0660: Typ definiert operator == oder operator !=, überschreibt jedoch nicht Object.Equals(object o)
  • CS0661: Typ definiert entweder operator == oder operator !=, überschreibt jedoch nicht Object.GetHashCode()
  • CS0715: Statische Klassen dürfen keine benutzerdefinierten Operatoren enthalten.
  • CS1037: Überlastbarer Operator erwartet
  • CS1553: Die Deklaration ist ungültig; verwenden Sie "Modifiziereroperator <dest-type> (...' stattdessen
  • CS8930: Die explizite Implementierung eines benutzerdefinierten Operators muss statisch sein.
  • CS8931: Explizite Implementierung muss öffentlich deklariert werden, um Schnittstellenmitglied in Typ zu implementieren.
  • CS9023: Der Operator kann nicht überprüft werden.
  • CS9024: Der Operator kann nicht deaktiviert werden.
  • CS9025: Der Operator erfordert, dass auch eine übereinstimmende, nicht überprüfte Version deklariert wird.
  • CS9308: Benutzerdefinierter Operator muss öffentlich deklariert werden.
  • CS9310: Der Rückgabetyp für diesen Operator muss ungültig sein.
  • CS9311: Der Typ implementiert kein Schnittstellenmitglied. Der Typ kann das Mitglied nicht implementieren, da einer von ihnen kein Operator ist.
  • CS9312: Der Typ kann das geerbte Element nicht außer Kraft setzen, da einer davon kein Operator ist.
  • CS9313: Der überladene zusammengesetzte Zuweisungsoperator verwendet einen Parameter.
  • CS9340: Der Operator kann nicht auf Operanden angewendet werden. Der nächstgelegene nicht anwendbare Kandidat wird angezeigt.
  • CS9341: Der Operator kann nicht auf den Operanden angewendet werden. Es wird der nächstgelegene ungeeignete Kandidat angezeigt.
  • CS9342: Die Operatorauflösung ist zwischen den folgenden Membern mehrdeutig.

Anforderungen an die Operatorsignatur

  • CS0448: Der Rückgabetyp für ++ oder -- Operator muss der enthaltende Typ oder vom enthaltenden Typ abgeleitet sein.
  • CS0559: Der Parametertyp für ++ oder -- Operator muss der enthaltende Typ sein.
  • CS0562: Der Parameter eines unären Operators muss der enthaltende Typ sein.
  • CS0563: Einer der Parameter eines binären Operators muss der enthaltende Typ sein.
  • CS0564: Der erste Operand eines überladenen Schichtoperators muss den gleichen Typ wie der enthaltende Typ aufweisen, und der Typ des zweiten Operanden muss int sein.
  • CS0567: Schnittstellen dürfen keine Operatoren enthalten.
  • CS0590: Benutzerdefinierte Operatoren können keine void zurückgeben.
  • CS9310: Der Rückgabetyp für diesen Operator muss ungültig sein.
  • CS9340: Der Operator kann nicht auf die Operanden angewendet werden. Der am nächsten liegende nicht anwendbare Kandidat wird angezeigt.
  • CS9341: Der Operator kann nicht auf den Operanden angewendet werden. Der nächste ungeeignete Kandidat wird angezeigt.
  • CS9342: Die Operatorauflösung ist zwischen den folgenden Membern mehrdeutig.

Um Operatoren mit korrekten Signaturen zu deklarieren, befolgen Sie diese Anforderungen für den jeweiligen Operatortyp. Weitere Informationen finden Sie unter Operatorüberladung.

  • Gibt den umschließenden Typ (oder einen abgeleiteten Typ) von ++- und ---Operatoren (CS0448) zurück.
  • Verwenden Sie den enthaltenden Typ als Parameter für ++ und -- Operatoren (CS0559).
  • Verwenden Sie den enthaltenden Typ als Parameter für unäre Operatoren (CS0562).
  • Fügen Sie den enthaltenden Typ als mindestens einen Parameter in binäre Operatoren (CS0563) ein.
  • Verwenden Sie den enthaltenden Typ als ersten Parameter und int als zweiten Parameter für Schichtoperatoren (CS0564).
  • Deklarieren Sie operatoren nicht in Schnittstellen (CS0567). Schnittstellen können keine Operatorimplementierungen enthalten.
  • Gibt einen Nicht-void-Typ von den meisten Operatoren (CS0590) zurück, mit Ausnahme bestimmter Operatoren, die void Rückgaben erfordern (CS9310).
  • Stellen Sie Operatorüberladungen bereit, die die richtigen Parametertypen akzeptieren, um Lösungsfehler zu vermeiden (CS9340, CS9341).
  • Mehrdeutigkeit bei Operatoraufrufen mithilfe expliziter Umwandlungen beseitigen oder spezifischere Überladungen anbieten (CS9342).

Von Bedeutung

Die Signaturanforderungen für statische binäre Operatoren und die entsprechenden Verbundzuordnungsoperatoren der Instanz unterscheiden sich. Stellen Sie sicher, dass die Signatur der gewünschten Deklaration entspricht.

Im folgenden Beispiel werden Signaturfehler veranschaulicht:

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
}

Anforderungen an die Operatordeklaration

  • CS0558: Benutzerdefinierter Operator muss statisch und öffentlich deklariert werden.
  • CS0715: Statische Klassen dürfen keine benutzerdefinierten Operatoren enthalten.
  • CS1037: Überlastbarer Operator erwartet.
  • CS1553: Die Deklaration ist ungültig; verwenden Sie den Modifiziereroperator <dest-type> (...) stattdessen.
  • CS8930: Die explizite Implementierung eines benutzerdefinierten Operators muss statisch sein.
  • CS8931: Die explizite Implementierung muss als 'public' deklariert werden, um ein Schnittstellenmitglied im Typ zu implementieren.
  • CS9308: Benutzerdefinierter Operator muss öffentlich deklariert werden.

Um Operatoren richtig zu deklarieren, befolgen Sie diese Anforderungen für Modifizierer und enthaltende Typen. Weitere Informationen finden Sie unter Operatorüberladungen und benutzerdefinierte Konvertierungsoperatoren.

  • Deklarieren Sie Operatoren mit beiden static und public Modifizierern (CS0558, CS9308).
  • Deklarieren Sie operatoren nicht in statischen Klassen (CS0715). Verwenden Sie reguläre Klassen oder Strukturen.
  • Verwenden Sie gültige, überladene Operatorsymbole (CS1037).
  • Befolgen Sie die richtige Syntax für Konvertierungsoperatoren: public static implicit/explicit operator <dest-type>(<source-type> parameter) (CS1553).
  • Stellen Sie sicher, dass die expliziten Schnittstellenimplementierungen von Operatoren static (CS8930) und public (CS8931) sind.

Im folgenden Beispiel werden Deklarationsfehler veranschaulicht:

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
}

Inkonsistente Barrierefreiheit

  • CS0056: Inkonsistente Zugänglichkeit: Der Rückgabetyp 'Typ' ist weniger zugänglich als der Operator 'Operator'.
  • CS0057: Inkonsistente Barrierefreiheit: Der Parametertyp "type" ist weniger zugänglich als der Operator "operator".

Um eine konsistente Zugänglichkeit in Operatordeklarationen sicherzustellen, machen Sie alle in öffentlichen Operatoren verwendeten Typen öffentlich zugänglich. Weitere Informationen finden Sie unter Zugriffsmodifikatoren.

  • Stellen Sie sicher, dass Rückgabetypen mindestens die gleiche Zugriffsebene wie der Operator (CS0056) haben.
  • Stellen Sie sicher, dass Parametertypen mindestens die gleiche Barrierefreiheit wie der Operator (CS0057) aufweisen.

Wenn Sie einen public Operator deklarieren, müssen auch alle typen, die als Parameter oder Rückgabewerte verwendet werden, öffentlich zugänglich sein.

Im folgenden Beispiel werden Barrierefreiheitsfehler veranschaulicht:

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
}

Benutzerdefinierte Konvertierungseinschränkungen

  • CS0552: Benutzerdefinierte Konvertierung in/von der Schnittstelle.
  • CS0553: Benutzerdefinierte Konvertierung in/von Basisklasse.
  • CS0554: Benutzerdefinierte Konvertierung in/von abgeleiteter Klasse.
  • CS0555: Benutzerdefinierter Operator kann kein Objekt des eingeschlossenen Typs übernehmen und in ein Objekt des eingeschlossenen Typs konvertieren.
  • CS0556: Benutzerdefinierte Konvertierung muss in oder aus dem eingeschlossenen Typ konvertiert werden.
  • CS0557: Doppelte benutzerdefinierte Konvertierung im Typ.

Um gültige benutzerdefinierte Konvertierungsoperatoren zu erstellen, befolgen Sie diese Einschränkungen. Weitere Informationen finden Sie unter Benutzerdefinierte Konvertierungsoperatoren.

  • Definieren Sie keine Konvertierungen in oder von Schnittstellen (CS0552). Verwenden Sie stattdessen explizite Schnittstellenimplementierungen.
  • Definieren Sie keine Konvertierungen in oder aus Basisklassen (CS0553). Die Konvertierung ist bereits durch Vererbung vorhanden.
  • Definieren Sie keine Konvertierungen in oder aus abgeleiteten Klassen (CS0554). Die Konvertierung besteht bereits durch Vererbung.
  • Definieren Sie keine Konvertierungen vom eingeschlossenen Typ in sich selbst (CS0555). Diese Konvertierung ist implizit.
  • Stellen Sie sicher, dass mindestens ein Typ in der Konvertierung der eingeschlossene Typ (CS0556) ist. Konvertierungen zwischen zwei externen Typen können nicht definiert werden.
  • Definieren Sie keine doppelten Konvertierungen (CS0557). Jeder Konvertierungsoperator muss eindeutig sein.

Im folgenden Beispiel werden Konvertierungseinschränkungsfehler veranschaulicht:

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;
}

Boolesche und Kurzschlussoperatoren

  • CS0215: Der Rückgabetyp des Operators "true" oder "false" muss bool sein.
  • CS0216: Der Operator erfordert auch die Definition eines übereinstimmenden Operators.
  • CS0217: Um als Kurzschlussoperator anwendbar zu sein, muss ein benutzerdefinierter logischer Operator den gleichen Rückgabetyp aufweisen wie der Typ seiner 2 Parameter.
  • CS0218: Der Typ muss Deklarationen des Operators "true" und "operator false" enthalten.

Um logische Operatoren richtig zu definieren, befolgen Sie diese Kopplungs- und Signaturanforderungen. Weitere Informationen finden Sie unter "true"- und "false"-Operatoren, booleschen logischen Operatoren und benutzerdefinierten logischen Operatoren.

  • Rückgabe bool von operator true und operator false (CS0215).
  • Definieren erforderlicher gekoppelter Operatoren (CS0216):
    • operator == erfordert operator !=
    • operator < erfordert operator >
    • operator <= erfordert operator >=
    • operator true erfordert operator false
  • Stimmen Sie den Rückgabetyp mit den Parametertypen für Kurzschlussoperatoren (& und |) überein, die mit benutzerdefinierten Typen (CS0217) funktionieren.
  • Implementieren Sie sowohl beide operator true als auch operator false bei Verwendung benutzerdefinierter Typen in booleschen Kontexten wie in && oder in || (CS0218).

Im folgenden Beispiel werden logische Operatorfehler veranschaulicht:

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
    }
}

Überprüfte Operatoren

  • CS9023: Der Operator kann nicht überprüft werden.
  • CS9024: Operator kann nicht deaktiviert werden
  • CS9025: Der überprüfte Operator erfordert, dass auch eine übereinstimmende, nicht überprüfte Version deklariert wird.

Um überprüfte Operatoren ordnungsgemäß zu verwenden, befolgen Sie diese Anforderungen. Weitere Informationen finden Sie unter arithmetischen Operatoren und benutzerdefinierten überprüften Operatoren.

  • Anwenden checked oder unchecked Schlüsselwörter nur auf unterstützte arithmetische Operatoren: +, , -, *, /, ++, --, und explizite Konvertierungen (CS9023, CS9024).
  • Stellen Sie beim Deklarieren eines aktivierten Operators (CS9025) sowohl aktivierte als auch deaktivierte Versionen bereit. Der Compiler benötigt beide, um unterschiedliche Kontexte zu verarbeiten.

Anforderungen an Schnittstellen und Vererbung

  • CS9311: Der Typ implementiert kein Schnittstellenmitglied. Der Typ kann das Mitglied nicht implementieren, weil eines von ihnen kein Operator ist.
  • CS9312: Typ kann geerbtes Element nicht außer Kraft setzen, da einer davon kein Operator ist.
  • CS9313: Überladener Verbundzuordnungsoperator akzeptiert einen Parameter.

Um Operatoren ordnungsgemäß zu implementieren und außer Kraft zu setzen, befolgen Sie diese Anforderungen. Weitere Informationen finden Sie unter Operatorüberladungen und Schnittstellen.

  • Stellen Sie sicher, dass Operatordeklarationen mit der Signatur und dem Typ der Schnittstellenmber (CS9311) übereinstimmen. Ein Operator kann kein Nicht-Operator-Mitglied implementieren.
  • Stellen Sie sicher, dass die geerbten Mitglieder, die überschrieben werden, auch Operatoren sind (CS9312). Ein Operator kann ein Nicht-Operatormitglied nicht außer Kraft setzen.
  • Deklarieren sie zusammengesetzte Zuordnungsoperatoren mit einem Parameter (CS9313). Der linke Operand ist implizit this.

Gleichheitsoperatoren

  • CS0660: Der Typ definiert den Operator == oder den Operator !=, überschreibt jedoch nicht Objekt.Equals(Objekt o)
  • CS0661: Type definiert den Operator == oder Operator != aber überschreibt Object.GetHashCode() nicht.

Um die Gleichheit richtig zu implementieren, überschreiben Sie die entsprechenden Object Methoden beim Definieren von benutzerdefinierten Gleichheitsoperatoren. Weitere Informationen finden Sie unter Definieren der Wertgleichstellung für einen Typ - und Gleichheitsoperatoren.

  • Überschreiben Sie Object.Equals, wenn Sie operator == oder operator != definieren (CS0660).
  • Überschreiben Sie Object.GetHashCode, wenn Sie operator == oder operator != definieren (CS0661).

Durch das Überschreiben dieser Methoden wird ein einheitliches Gleichheitsverhalten für verschiedene APIs und Sammlungstypen sichergestellt.