Udostępnij za pomocą


Usuwanie błędów i ostrzeżeń w deklaracjach operatorów zdefiniowanych przez użytkownika

W tym artykule opisano następujące błędy kompilatora:

  • CS0056: Niespójna dostępność: typ zwracany "type" jest mniej dostępny niż operator "operator"
  • CS0057: Niespójna dostępność: typ parametru "type" jest mniej dostępny niż operator "operator"
  • CS0215: Zwracany typ operatora Prawda lub Fałsz musi być wartością logiczną
  • CS0216: Operator „operator” wymaga również zdefiniowania odpowiadającego mu operatora „missing_operator”
  • CS0217: Aby był stosowany jako operator krótkiego spięcia, zdefiniowany przez użytkownika operator logiczny („operator”) musi mieć taki sam typ zwracany jak typ jego dwóch parametrów.
  • CS0218: Typ ('type') musi zawierać deklaracje operatora true i operator false
  • CS0448: Typ zwracany dla operatora ++ lub -- musi być typem zawierającym lub pochodnym typu zawierającego
  • CS0552: "procedury konwersji": konwersja zdefiniowana przez użytkownika na/z interfejsu
  • CS0553: "procedury konwersji": konwersja zdefiniowana przez użytkownika na/z klasy bazowej
  • CS0554: "procedury konwersji": konwersja zdefiniowana przez użytkownika na/z klasy pochodnej
  • CS0555: Operator zdefiniowany przez użytkownika nie może przyjąć obiektu otaczającego typu i przekonwertować na obiekt otaczającego typu
  • CS0556: Konwersja zdefiniowana przez użytkownika musi zostać przekonwertowana na lub z otaczającego typu
  • CS0557: Powtarzająca się konwersja zdefiniowana przez użytkownika w typie
  • CS0558: Operator zdefiniowany przez użytkownika musi być zadeklarowany jako statyczny i publiczny
  • CS0559: Typ parametru dla operatora ++ lub -- musi być typem obejmującym
  • CS0562: Parametr operatora jednoargumentowego musi być typem, który go zawiera
  • CS0563: Jeden z parametrów operatora binarnego musi być typem zawierającym
  • CS0564: Pierwszy operand przeciążonego operatora przesunięcia musi mieć ten sam typ co typ zawierający, a typ drugiego operandu musi być int
  • CS0567: Interfejsy nie mogą zawierać operatorów
  • CS0590: Operatory zdefiniowane przez użytkownika nie mogą zwracać wartości void
  • CS0660: Typ definiuje operator == lub operator !=, ale nie zastępuje Object.Equals(object o)
  • CS0661: Typ definiuje operator == lub operator !=, ale nie Object.GetHashCode()zastępuje
  • CS0715: Klasy statyczne nie mogą zawierać operatorów zdefiniowanych przez użytkownika
  • CS1037: Oczekiwano przeciążalnego operatora
  • CS1553: Deklaracja jest nieprawidłowa; użyj operatora <modyfikatora dest-type> (...) zamiast
  • CS8930: Jawna implementacja operatora zdefiniowanego przez użytkownika musi być statyczna.
  • CS8931: Jawna implementacja musi być zadeklarowana publicznie, aby zaimplementować element członkowski interfejsu w typie.
  • CS9023: Nie można sprawdzić operatora.
  • CS9024: Operator nie może być oznaczony jako niekontrolowany.
  • CS9025: Operator wymaga również zadeklarowania zgodnej wersji, która nie jest sprawdzana.
  • CS9308: Operator zdefiniowany przez użytkownika musi być zadeklarowany publicznie.
  • CS9310: Typ zwracany dla tego operatora musi mieć wartość void.
  • CS9311: Typ nie implementuje elementu członkowskiego interfejsu. Typ nie może zaimplementować elementu członkowskiego, ponieważ jeden z nich nie jest operatorem.
  • CS9312: Typ nie może zastąpić dziedziczonego członka, ponieważ jeden z nich nie jest operatorem.
  • CS9313: Przeciążony operator przypisania złożonego przyjmuje jeden parametr.
  • CS9340: Operator nie może być stosowany do operandów. Pokazano najbliższego niedostępnego kandydata.
  • CS9341: Operator nie może być stosowany do operandu. Pokazano najbliższego nieodpowiedniego kandydata.
  • CS9342: Rozpoznawanie operatorów jest niejednoznaczne między następującymi elementami członkowskimi.

Wymagania dotyczące podpisu operatora

  • CS0448: Typ zwracany dla ++ lub -- operatora musi być typem zawierającym lub pochodnym od typu zawierającego.
  • CS0559: Typ parametru dla ++ operatora lub -- musi być typem zawierającym.
  • CS0562: Parametr operatora jednoargumentowego musi być typem zawierającym.
  • CS0563: Jeden z parametrów operatora binarnego musi być typem zawierającym.
  • CS0564: Pierwszy operand przeciążonego operatora przesunięcia musi mieć taki sam typ jak typ klasy zawierającej, a typ drugiego operandu musi być typu int.
  • CS0567: Interfejsy nie mogą zawierać operatorów.
  • CS0590: Operatory zdefiniowane przez użytkownika nie mogą zwracać wartości void.
  • CS9310: Typ zwracany dla tego operatora musi mieć wartość void.
  • CS9340: Operator nie może być zastosowany do operandów. Pokazano najbliższego nieodpowiedniego kandydata.
  • CS9341: Operator nie może być stosowany do operandu. Pokazano najbliższy niewłaściwy kandydat.
  • CS9342: Rozstrzyganie operatorów jest niejednoznaczne między następującymi członkami.

Aby zadeklarować operatory z prawidłowymi podpisami, postępuj zgodnie z tymi wymaganiami dla określonego typu operatora. Aby uzyskać więcej informacji, zobacz Przeciążenie operatora.

  • Zwróć typ zawierający (lub typ pochodny) z operatorów ++ i -- (CS0448).
  • Użyj typu zawierającego jako parametru dla operatorów ++ i -- (CS0559).
  • Użyj typu, który zawiera, jako parametru dla operatorów jednoargumentowych (CS0562).
  • Uwzględnij typ zawierający jako co najmniej jeden parametr w operatorach binarnych (CS0563).
  • Użyj typu zawierającego jako pierwszego parametru i int jako drugiego parametru przy operatorach przesunięcia (CS0564).
  • Nie deklaruj operatorów w interfejsach (CS0567). Interfejsy nie mogą zawierać implementacji operatorów.
  • Zwraca typ niepusty z większości operatorów (CS0590), z wyjątkiem określonych operatorów, które wymagają void zwracania (CS9310).
  • Podaj przeciążenia operatorów, które akceptują poprawne typy parametrów, aby uniknąć błędów rozwiązywania (CS9340, CS9341).
  • Rozwiązywanie niejednoznaczności wywołań operatorów przy użyciu jawnych rzutów lub użycie bardziej szczegółowych przeciążeń (CS9342).

Ważne

Wymagania dotyczące sygnatur dla statycznych operatorów binarnych i odpowiednich operatorów złożonego przypisania instancyjnego są różne. Upewnij się, że podpis jest zgodny z odpowiednią deklaracją.

W poniższym przykładzie przedstawiono błędy podpisu:

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
}

Wymagania dotyczące deklaracji operatora

  • CS0558: Operator zdefiniowany przez użytkownika musi być zadeklarowany jako statyczny i publiczny.
  • CS0715: Klasy statyczne nie mogą zawierać operatorów zdefiniowanych przez użytkownika.
  • CS1037: Oczekiwano operatora przeciążalnego.
  • CS1553: Deklaracja jest nieprawidłowa; użyj operatora <modyfikatora dest-type> (...) zamiast.
  • CS8930: Jawna implementacja operatora zdefiniowanego przez użytkownika musi być statyczna.
  • CS8931: Jawna implementacja musi być zadeklarowana publicznie, aby zaimplementować element członkowski interfejsu w typie.
  • CS9308: Operator zdefiniowany przez użytkownika musi być zadeklarowany publicznie.

Aby poprawnie zadeklarować operatory, postępuj zgodnie z tymi wymaganiami dotyczącymi modyfikatorów i zawierających typy. Aby uzyskać więcej informacji, zobacz Operator przeciążenie i Operatory konwersji zdefiniowane przez użytkownika.

  • Zadeklaruj operatory z modyfikatorami static i public (CS0558, CS9308).
  • Nie deklaruj operatorów w klasach statycznych (CS0715). Użyj zwykłych klas lub struktur.
  • Użyj prawidłowych, przeciążalnych symboli operatorów (CS1037).
  • Postępuj zgodnie z poprawną składnią dla operatorów konwersji: public static implicit/explicit operator <dest-type>(<source-type> parameter) (CS1553).
  • Upewnij się, że jawne implementacje interfejsów operatorów to static (CS8930) i public (CS8931).

W poniższym przykładzie przedstawiono błędy deklaracji:

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
}

Niespójne ułatwienia dostępu

  • CS0056: Niespójna dostępność: typ zwracany "type" jest mniej dostępny niż operator "operator".
  • CS0057: Niespójna dostępność: typ parametru "type" jest mniej dostępny niż operator "operator".

Aby zapewnić spójny dostęp do deklaracji operatorów, upewnij się, że wszystkie typy używane w operatorach publicznych są publicznie dostępne. Aby uzyskać więcej informacji, zobacz Modyfikatory dostępu.

  • Upewnij się, że typy zwracane mają co najmniej taki sam poziom dostępu jak operator (CS0056).
  • Upewnij się, że typy parametrów mają co najmniej taką samą dostępność jak operator (CS0057).

Podczas deklarowania public operatora wszystkie typy używane jako parametry lub wartości zwracane muszą być również publicznie dostępne.

W poniższym przykładzie przedstawiono błędy ułatwień dostępu:

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
}

Ograniczenia konwersji zdefiniowane przez użytkownika

  • CS0552: Konwersja zdefiniowana przez użytkownika na/z interfejsu.
  • CS0553: Konwersja zdefiniowana przez użytkownika do/z klasy bazowej.
  • CS0554: konwersja zdefiniowana przez użytkownika na/z klasy pochodnej.
  • CS0555: Operator zdefiniowany przez użytkownika nie może przyjąć obiektu otaczającego typu i przekonwertować go na obiekt otaczającego typu.
  • CS0556: Konwersja zdefiniowana przez użytkownika musi zostać przekonwertowana na lub z otaczającego typu.
  • CS0557: Zduplikowana konwersja zdefiniowana przez użytkownika w typie.

Aby utworzyć prawidłowe operatory konwersji zdefiniowane przez użytkownika, postępuj zgodnie z tymi ograniczeniami. Aby uzyskać więcej informacji, zobacz Operatory konwersji zdefiniowane przez użytkownika.

  • Nie należy definiować konwersji do lub z interfejsów (CS0552). Zamiast tego należy używać jawnych implementacji interfejsu.
  • Nie należy definiować konwersji do lub z klas bazowych (CS0553). Konwersja już istnieje poprzez dziedziczenie.
  • Nie należy definiować konwersji do lub z klas pochodnych (CS0554). Konwersja już istnieje za pośrednictwem dziedziczenia.
  • Nie należy definiować konwersji z otaczającego typu do samego siebie (CS0555). Ta konwersja jest niejawna.
  • Upewnij się, że co najmniej jeden typ w konwersji jest typem obejmującym (CS0556). Nie można definiować konwersji między dwoma typami zewnętrznymi.
  • Nie należy definiować zduplikowanych konwersji (CS0557). Każdy operator konwersji musi być unikatowy.

W poniższym przykładzie przedstawiono błędy ograniczeń konwersji:

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

Operatory logiczne i zwarciowe

  • CS0215: Zwracany typ operatora true lub false musi być wartością logiczną.
  • CS0216: Operator wymaga również zdefiniowanego operatora dopasowania.
  • CS0217: Aby można było go stosować jako operator zwarć, operator logiczny zdefiniowany przez użytkownika musi mieć ten sam typ zwracany co typ jego 2 parametrów.
  • CS0218: Typ musi zawierać deklaracje operatora true i operator false.

Aby poprawnie zdefiniować operatory logiczne, postępuj zgodnie z tymi wymaganiami dotyczącymi parowania i podpisu. Aby uzyskać więcej informacji, zobacz operatory true i false, operatory logiczne logiczne i warunkowe operatory logiczne zdefiniowane przez użytkownika.

  • Powrót bool z operator true i operator false (CS0215).
  • Zdefiniuj wymagane operatory sparowane (CS0216):
    • operator == Wymaga operator !=
    • operator < Wymaga operator >
    • operator <= Wymaga operator >=
    • operator true Wymaga operator false
  • Dopasuj typ zwracany z typami parametrów dla operatorów zwarciowych (& i |), które działają z typami niestandardowymi (CS0217).
  • Zaimplementuj zarówno operator true, jak i operator false podczas używania typów niestandardowych w kontekstach logicznych, takich jak && i || (CS0218).

W poniższym przykładzie przedstawiono błędy operatora logicznego:

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

Weryfikowane operatory

  • CS9023: Nie można sprawdzić operatora
  • CS9024: Nie można usunąć zaznaczenia operatora
  • CS9025: Sprawdzony operator wymaga również zadeklarowania zgodnej wersji, która nie jest sprawdzana

Aby prawidłowo używać operatorów z weryfikacją, postępuj zgodnie z tymi wymaganiami. Aby uzyskać więcej informacji, zobacz Operatory arytmetyczne i Operatory zaznaczone przez użytkownika.

  • Zastosuj słowa kluczowe checked lub unchecked tylko do obsługiwanych operatorów arytmetycznych: +, -, *, /, ++, -- oraz do jawnych konwersji (CS9023, CS9024).
  • Podaj zarówno zaznaczone, jak i niezaznaczone wersje podczas deklarowania zaznaczonego operatora (CS9025). Kompilator musi obsługiwać różne konteksty.

Wymagania dotyczące interfejsu i dziedziczenia

  • CS9311: Typ nie implementuje elementu członkowskiego interfejsu. Typ nie może zaimplementować elementu członkowskiego, ponieważ jeden z nich nie jest operatorem
  • CS9312: Typ nie może zastąpić dziedziczonego członka, ponieważ jeden z nich nie jest operatorem
  • CS9313: Przeciążony operator przypisania złożonego przyjmuje jeden parametr

Aby poprawnie zaimplementować i nadpisać operatory, postępuj zgodnie z tymi wymaganiami. Aby uzyskać więcej informacji, zobacz Przeciążenie operatorów i Interfejsy.

  • Upewnij się, że deklaracje operatorów są zgodne z sygnaturą i typem elementów członkowskich interfejsu (CS9311). Operator nie może zaimplementować członka, który nie jest operatorem.
  • Zweryfikuj, czy dziedziczeni członkowie, którzy są przesłaniani, są również operatorami (CS9312). Operator nie może zastąpić członka, który nie jest operatorem.
  • Zadeklaruj operatory przypisania złożonego za pomocą jednego parametru (CS9313). Lewy operand jest domyślnie this.

Operatory równości

  • CS0660: Typ definiuje operator == lub operator != ale nie zastępuje object.Equals(object o)
  • CS0661: Typ definiuje operator == lub operator != ale nie zastępuje object.GetHashCode()

Aby poprawnie zaimplementować równość, należy zastąpić odpowiednie Object metody podczas definiowania niestandardowych operatorów równości. Aby uzyskać więcej informacji, zobacz Jak zdefiniować równość wartości dla typu i operatory równości.

  • Zastąp Object.Equals podczas definiowania operator == lub operator != (CS0660).
  • Zastąp Object.GetHashCode podczas definiowania operator == lub operator != (CS0661).

Zastąpienie tych metod zapewnia spójne zachowanie równości w różnych interfejsach API i typach kolekcji.