Partilhar via


Resolver erros e avisos em declarações de operador definidas pelo usuário

Este artigo aborda os seguintes erros do compilador:

  • CS0056: Acessibilidade inconsistente: o tipo de retorno 'tipo' é menos acessível do que o operador 'operador'
  • CS0057: Acessibilidade inconsistente: o tipo de parâmetro 'tipo' é menos acessível do que o operador 'operador'
  • CS0215: O tipo de retorno do operador True ou False deve ser bool
  • CS0216: O operador «operador» requer também a definição de um operador correspondente «missing_operator»
  • CS0217: Para ser aplicável como operador de curto-circuito, um operador lógico definido pelo utilizador («operador») deve ter o mesmo tipo de retorno que o tipo dos seus 2 parâmetros.
  • CS0218: O tipo («tipo») deve conter declarações de operador verdadeiro e operador falso
  • CS0448: O tipo de retorno para o operador ++ ou -- deve ser o tipo que o contém ou derivado do tipo que o contém
  • CS0552: 'rotina de conversão' : conversão definida pelo usuário para/da interface
  • CS0553: 'rotina de conversão' : conversão definida pelo usuário de/para a classe base
  • CS0554: 'rotina de conversão' : conversão definida pelo usuário de/para classe derivada
  • CS0555: O operador definido pelo usuário não pode pegar um objeto do tipo de delimitação e converter em um objeto do tipo de delimitação
  • CS0556: A conversão definida pelo usuário deve ser convertida para ou a partir do tipo envolvente
  • CS0557: Duplicar a conversão definida pelo usuário no tipo
  • CS0558: O operador definido pelo usuário deve ser declarado estático e público
  • CS0559: O tipo de parâmetro para o operador ++ ou -- deve ser o tipo que o contém
  • CS0562: O parâmetro de um operador unário deve ser o tipo que contém
  • CS0563: Um dos parâmetros de um operador binário deve ser o tipo que contém
  • CS0564: O primeiro operando de um operador de turno sobrecarregado deve ter o mesmo tipo que o tipo que o contém, e o tipo do segundo operando deve ser int
  • CS0567: As interfaces não podem conter operadores
  • CS0590: Operadores definidos pelo usuário não podem retornar void
  • CS0660: Tipo define operator == ou operator != mas não substitui Object.Equals(object o)
  • CS0661: Tipo define operator == ou operator != mas não substitui Object.GetHashCode()
  • CS0715: Classes estáticas não podem conter operadores definidos pelo usuário
  • CS1037: Operador sobrecarregável esperado
  • CS1553: A declaração não é válida; use 'modificador operador <dest-type> (...' em vez disso,
  • CS8930: A implementação explícita de um operador definido pelo usuário deve ser estática.
  • CS8931: A implementação explícita deve ser declarada pública para implementar o membro da interface em tipo.
  • CS9023: O operador não pode ser verificado.
  • CS9024: O operador não pode ser inalterável.
  • CS9025: O operador requer que também seja declarada uma versão não verificada correspondente.
  • CS9308: O operador definido pelo usuário deve ser declarado público.
  • CS9310: O tipo de retorno para este operador deve ser nulo.
  • CS9311: O tipo não implementa o membro da interface. O tipo não pode implementar membro porque um deles não é um operador.
  • CS9312: O tipo não pode substituir o membro herdado porque um deles não é um operador.
  • CS9313: O operador de atribuição composto sobrecarregado usa um parâmetro.
  • CS9340: O operador não pode ser aplicado a operandos. É indicado o candidato inaplicável mais próximo.
  • CS9341: O operador não pode ser aplicado ao operando. É indicado o candidato inaplicável mais próximo.
  • CS9342: A resolução do operador é ambígua entre os seguintes membros.

Requisitos de assinatura do operador

  • CS0448: O tipo de retorno para o operador ++ ou -- deve ser o tipo que encapsula ou derivado do tipo que encapsula.
  • CS0559: O tipo de parâmetro para o operador ++ ou -- deve ser o tipo que o contém.
  • CS0562: O parâmetro de um operador unário deve ser o tipo que o contém.
  • CS0563: Um dos parâmetros de um operador binário deve ser o tipo que contém.
  • CS0564: O primeiro operando de um operador de turno sobrecarregado deve ter o mesmo tipo que o tipo que o contém, e o tipo do segundo operando deve ser int.
  • CS0567: As interfaces não podem conter operadores.
  • CS0590: Os operadores definidos pelo usuário não podem retornar void.
  • CS9310: O tipo de retorno para este operador deve ser nulo.
  • CS9340: O operador não pode ser aplicado a operandos. É indicado o candidato inaplicável mais próximo.
  • CS9341: O operador não pode ser aplicado ao operando. É indicado o candidato inaplicável mais próximo.
  • CS9342: A definição do operador é ambígua entre os seguintes membros.

Para declarar operadores com assinaturas corretas, siga estes requisitos para o tipo de operador específico. Para obter mais informações, consulte Sobrecarga do operador.

  • Retornar o tipo que contém (ou um tipo derivado) dos operadores ++ e -- (CS0448).
  • Use o tipo contido como parâmetro dos operadores ++ e -- (CS0559).
  • Use o tipo contendo como parâmetro para operadores unários (CS0562).
  • Inclua o tipo contendo como pelo menos um parâmetro em operadores binários (CS0563).
  • Use o tipo contendo como o primeiro parâmetro e int como o segundo parâmetro para operadores de turno (CS0564).
  • Não declare operadores em interfaces (CS0567). As interfaces não podem conter implementações de operadores.
  • Retornar um tipo não nulo da maioria dos operadores (CS0590), exceto para operadores específicos que exigem void retornos (CS9310).
  • Forneça sobrecargas do operador que aceitem os tipos de parâmetros corretos para evitar falhas de resolução (CS9340, CS9341).
  • Desambiguar chamadas de operador usando transmissões explícitas ou fornecendo sobrecargas mais específicas (CS9342).

Importante

Os requisitos de assinatura para operadores binários estáticos e os operadores de atribuição compostos de instância correspondentes são diferentes. Certifique-se de que a assinatura corresponde à declaração pretendida.

O exemplo a seguir demonstra erros de assinatura:

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
}

Requisitos em matéria de declaração do operador

  • CS0558: O operador definido pelo usuário deve ser declarado estático e público.
  • CS0715: As classes estáticas não podem conter operadores definidos pelo usuário.
  • CS1037: Operador sobrecarregado esperado.
  • CS1553: Declaração não é válida; use 'modificador operador <dest-type> (...' em vez disso.
  • CS8930: A implementação explícita de um operador definido pelo usuário deve ser estática.
  • CS8931: A implementação explícita deve ser declarada pública para implementar um membro da interface em um tipo.
  • CS9308: O operador definido pelo usuário deve ser declarado público.

Para declarar operadores corretamente, siga estes requisitos para modificadores e tipos de contenção. Para obter mais informações, consulte Sobrecarga do operador e Operadores de conversão definidos pelo usuário.

  • Declare operadores com os modificadores static e public (CS0558, CS9308).
  • Não declare operadores em classes estáticas (CS0715). Use classes ou estruturas regulares.
  • Use símbolos de operador válidos e sobrecarregáveis (CS1037).
  • Siga a sintaxe correta para operadores de conversão: public static implicit/explicit operator <dest-type>(<source-type> parameter) (CS1553).
  • Garantir que as implementações de interface explícitas dos operadores sejam static (CS8930) e public (CS8931).

O exemplo a seguir demonstra erros de declaração:

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
}

Acessibilidade inconsistente

  • CS0056: Acessibilidade inconsistente: o tipo de retorno 'tipo' é menos acessível do que o operador 'operador'.
  • CS0057: Acessibilidade inconsistente: o tipo de parâmetro «tipo» é menos acessível do que o operador «operador».

Para garantir uma acessibilidade coerente nas declarações dos operadores, tornar acessíveis ao público todos os tipos utilizados nos operadores públicos. Para obter mais informações, consulte Modificadores de acesso.

  • Assegure que os tipos de retorno tenham pelo menos a mesma acessibilidade que o operador (CS0056).
  • Certifique-se de que os tipos de parâmetros tenham pelo menos a mesma acessibilidade que o operador (CS0057).

Quando você declara um public operador, todos os tipos usados como parâmetros ou valores de retorno também devem ser acessíveis publicamente.

O exemplo a seguir demonstra erros de acessibilidade:

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
}

Restrições de conversão definidas pelo usuário

  • CS0552: Conversão definida pelo usuário para/da interface.
  • CS0553: Conversão definida pelo usuário de/para a classe base.
  • CS0554: Conversão definida pelo usuário para/da classe derivada.
  • CS0555: O operador definido pelo utilizador não pode aceitar um objeto do tipo envolvente e converter para um objeto do tipo envolvente.
  • CS0556: A conversão definida pelo usuário deve ser convertida de ou para o tipo de anexo.
  • CS0557: Duplicar a conversão definida pelo usuário no tipo.

Para criar operadores de conversão válidos definidos pelo usuário, siga estas restrições. Para obter mais informações, consulte Operadores de conversão definidos pelo usuário.

  • Não defina conversões de ou para interfaces (CS0552). Em vez disso, use implementações de interface explícitas.
  • Não defina conversões de ou para classes base (CS0553). A conversão já existe por herança.
  • Não defina conversões de ou para classes derivadas (CS0554). A conversão já existe por herança.
  • Não defina conversões do tipo envolvente para o próprio tipo (CS0555). Esta conversão está implícita.
  • Certifique-se de que pelo menos um tipo na conversão é o tipo envolvente (CS0556). Não é possível definir conversões entre dois tipos externos.
  • Não defina conversões duplicadas (CS0557). Cada operador de conversão deve ser único.

O exemplo a seguir demonstra erros de restrição de conversão:

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

Operadores booleanos e de curto-circuito

  • CS0215: O tipo de retorno do operador true ou false deve ser bool.
  • CS0216: O operador requer que um operador correspondente também seja definido.
  • CS0217: Para ser aplicável como um operador de curto-circuito, um operador lógico definido pelo usuário deve ter o mesmo tipo de retorno que o tipo de seus 2 parâmetros.
  • CS0218: O tipo deve conter declarações de operador true e operador false.

Para definir operadores lógicos corretamente, siga estes requisitos de emparelhamento e assinatura. Para obter mais informações, consulte operadores true e false, operadores lógicos booleanos e operadores lógicos condicionais definidos pelo usuário.

  • Retorno bool de operator true e operator false (CS0215).
  • Defina os operadores emparelhados necessários (CS0216):
    • operator == requer operator !=
    • operator < requer operator >
    • operator <= requer operator >=
    • operator true requer operator false
  • Combine o tipo de retorno com os tipos de parâmetros para operadores de curto-circuito (& e |) que trabalham com tipos personalizados (CS0217).
  • Implemente ambos operator true e operator false ao usar tipos personalizados em contextos booleanos como && e || (CS0218).

O exemplo a seguir demonstra erros de operador lógico:

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

Operadores controlados

  • CS9023: O operador não pode ser verificado
  • CS9024: O operador não pode ser desmarcado
  • CS9025: O operador verificado requer que uma versão correspondente não verificada também seja declarada

Para usar os operadores verificados corretamente, siga estes requisitos. Para obter mais informações, consulte Operadores aritméticos e Operadores verificados definidos pelo usuário.

  • Aplique as palavras-chave checked ou unchecked somente a operadores aritméticos suportados: +, -, *, /, ++, -- e conversões explícitas (CS9023, CS9024).
  • Forneça versões verificadas e não verificadas ao declarar um operador verificado (CS9025). O compilador precisa de ambos para lidar com contextos diferentes.

Requisitos de interface e herança

  • CS9311: O tipo não implementa o membro da interface. O tipo não pode implementar membro porque um deles não é um operador
  • CS9312: Tipo não pode substituir membro herdado porque um deles não é um operador
  • CS9313: Operador de atribuição composto sobrecarregado recebe um parâmetro

Para implementar e substituir operadores corretamente, siga estes requisitos. Para obter mais informações, consulte Sobrecarga do operador e interfaces.

  • Verifique se as declarações do operador correspondem à assinatura e ao tipo de membros da interface (CS9311). Um operador não pode implementar um membro não operador.
  • Verifique se os membros herdados que estão sendo substituídos também são operadores (CS9312). Um operador não pode substituir um membro que não seja operador.
  • Declare operadores de atribuição compostos com um parâmetro (CS9313). O operando da esquerda é implicitamente this.

Operadores de igualdade

  • CS0660: O tipo define o operador == ou o operador != mas não substitui Object.Equals(objeto o)
  • CS0661: Type define operador == ou operador != mas não substitui Object.GetHashCode()

Para implementar a igualdade corretamente, substitua os métodos correspondentes Object ao definir operadores de igualdade personalizados. Para obter mais informações, consulte Como definir igualdade de valor para um tipo e Operadores de igualdade.

  • Substituir Object.Equals quando se define operator == ou operator != (CS0660).
  • Substitua Object.GetHashCode ao definir operator == ou operator != (CS0661).

A substituição desses métodos garante um comportamento de igualdade consistente em diferentes APIs e tipos de coleção.