Compartir vía


Resolución de errores y advertencias en declaraciones de operador definidas por el usuario

En este artículo se tratan los siguientes errores del compilador:

  • CS0056: Accesibilidad incoherente: el tipo de valor devuelto 'type' es menos accesible que el operador 'operator'
  • CS0057: Accesibilidad incoherente: el tipo de parámetro 'type' es menos accesible que el operador 'operator'
  • CS0215: el tipo de valor devuelto del operador True o False debe ser bool.
  • CS0216: el operador 'operator' requiere que también se defina un operador coincidente 'missing_operator'
  • CS0217: para que sea aplicable como operador de cortocircuito, un operador lógico definido por el usuario ('operator') debe tener el mismo tipo de valor devuelto que el tipo de sus 2 parámetros.
  • CS0218: el tipo ('type') debe contener declaraciones del operador true y el operador false
  • CS0448: El tipo de retorno del operador ++ o -- debe ser el tipo contenedor o estar derivado del tipo contenedor.
  • CS0552: "rutina de conversión" : conversión definida por el usuario a o desde la interfaz
  • CS0553: "rutina de conversión" : conversión definida por el usuario a o desde la clase base
  • CS0554: "rutina de conversión" : conversión definida por el usuario a o desde la clase derivada
  • CS0555: El operador definido por el usuario no puede tomar un objeto del tipo envolvente ni convertirlo en un objeto del tipo envolvente
  • CS0556: La conversión definida por el usuario debe convertir a o desde el tipo que lo contiene
  • CS0557: Conversión duplicada definida por el usuario en el tipo
  • CS0558: El operador definido por el usuario debe declararse estático y público
  • CS0559: El tipo de parámetro para el operador ++ o -- debe ser el tipo que lo contiene
  • CS0562: el parámetro de un operador unario debe ser el tipo contenedor.
  • CS0563: uno de los parámetros de un operador binario debe ser el tipo contenedor.
  • CS0564: El primer operando de un operador de desplazamiento sobrecargado debe tener el mismo tipo que aquel que lo contiene, y el tipo del segundo operando debe ser int.
  • CS0567: Las interfaces no pueden contener operadores
  • CS0590: Los operadores definidos por el usuario no pueden devolver void
  • CS0660: el tipo define operator == o operator != pero no invalida Object.Equals(object o)
  • CS0661: El tipo define operator == o operator != pero no invalida Object.GetHashCode()
  • CS0715: Las clases estáticas no pueden contener operadores definidos por el usuario
  • CS1037: Se esperaba un operador sobrecargable
  • CS1553: La declaración no es válida; use 'operador modificador <dest-type> (...' en lugar de
  • CS8930: la implementación explícita de un operador definido por el usuario debe ser estática.
  • CS8931: la implementación explícita debe declararse pública para implementar el miembro de interfaz en el tipo .
  • CS9023: El operador no puede ser comprobado.
  • CS9024: No se puede poner al operador en estado no comprobado.
  • CS9025: el operador requiere que también se declare una versión no comprobada coincidente.
  • CS9308: el operador definido por el usuario debe declararse público.
  • CS9310: el tipo de valor devuelto para este operador debe ser nulo.
  • CS9311: El tipo no implementa el miembro de interfaz. El tipo no puede implementar miembro porque uno de ellos no es un operador.
  • CS9312: El tipo no puede invalidar el miembro heredado porque uno de ellos no es un operador.
  • CS9313: El operador de asignación compuesta sobrecargado toma un parámetro.
  • CS9340: el operador no se puede aplicar a los operandos. Se muestra el candidato inaplicable más cercano.
  • CS9341: el operador no se puede aplicar al operando. Se muestra el candidato inaplicable más cercano.
  • CS9342: la resolución del operador es ambigua entre los siguientes miembros.

Requisitos de firma de operador

  • CS0448: El tipo de valor devuelto para el operador ++ o -- debe ser el tipo contenedor o derivado del tipo contenedor.
  • CS0559: el tipo de parámetro para ++ o -- el operador debe ser el tipo contenedor.
  • CS0562: el parámetro de un operador unario debe ser el tipo contenedor.
  • CS0563: uno de los parámetros de un operador binario debe ser el tipo contenedor.
  • CS0564: El primer operando de un operador de desplazamiento sobrecargado debe tener el mismo tipo que el tipo contenedor, y el tipo del segundo operando debe ser int.
  • CS0567: Las interfaces no pueden contener operadores.
  • CS0590: los operadores definidos por el usuario no pueden devolver void.
  • CS9310: el tipo de valor devuelto para este operador debe ser nulo.
  • CS9340: el operador no se puede aplicar a los operandos. Se muestra el candidato inaplicable más cercano.
  • CS9341: el operador no se puede aplicar al operando. Se muestra el candidato inaplicable más cercano.
  • CS9342: la resolución del operador es ambigua entre los siguientes miembros.

Para declarar operadores con firmas correctas, siga estos requisitos para el tipo de operador específico. Para obtener más información, consulte Sobrecarga del operador.

  • Devuelve el tipo contenedor (o un tipo derivado) desde los operadores ++ y -- (CS0448).
  • Use el tipo contenedor como parámetro para los operadores ++ y -- (CS0559).
  • Use el tipo contenedor como parámetro para operadores unarios (CS0562).
  • Incluya el tipo contenedor como al menos un parámetro en operadores binarios (CS0563).
  • Use el tipo de contención como primer parámetro y el int como segundo parámetro para los operadores de desplazamiento (CS0564).
  • No declare operadores en interfaces (CS0567). Las interfaces no pueden contener implementaciones de operador.
  • Devuelve un tipo no nulo de la mayoría de los operadores (CS0590), excepto los operadores específicos que requieren void devoluciones (CS9310).
  • Proporcione sobrecargas de operador que acepten los tipos de parámetro correctos para evitar errores de resolución (CS9340, CS9341).
  • Desambiguar las llamadas de operador mediante conversiones explícitas o proporcionando sobrecargas más específicas (CS9342).

Importante

Los requisitos de firma para los operadores binarios estáticos y los operadores de asignación compuesta de instancia correspondientes son diferentes. Asegúrese de que la firma coincide con la declaración que desee.

En el ejemplo siguiente se muestran errores de 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
}

Requisitos de declaración de operador

  • CS0558: el operador definido por el usuario debe declararse estático y público.
  • CS0715: las clases estáticas no pueden contener operadores definidos por el usuario.
  • CS1037: se esperaba un operador sobrecargable.
  • CS1553: La declaración no es válida; use 'modificador operator <dest-type> (...' en su lugar.
  • CS8930: la implementación explícita de un operador definido por el usuario debe ser estática.
  • CS8931: la implementación explícita debe declararse pública para implementar el miembro de interfaz en el tipo .
  • CS9308: el operador definido por el usuario debe declararse público.

Para declarar los operadores correctamente, siga estos requisitos para los modificadores y los tipos contenedores. Para obtener más información, consulte Sobrecarga de operadores y operadores de conversión definidos por el usuario.

  • Declare operadores con modificadores static y public (CS0558, CS9308).
  • No declare operadores en clases estáticas (CS0715). Use clases o estructuras normales.
  • Use símbolos de operador válidos y sobrecargables (CS1037).
  • Siga la sintaxis correcta para los operadores de conversión: public static implicit/explicit operator <dest-type>(<source-type> parameter) (CS1553).
  • Asegúrese de que las implementaciones de interfaz explícitas de los operadores son static (CS8930) y public (CS8931).

En el ejemplo siguiente se muestran errores de declaración:

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
}

Accesibilidad incoherente

  • CS0056: Accesibilidad incoherente: el tipo de valor devuelto 'type' es menos accesible que el operador 'operator'.
  • CS0057: Accesibilidad incoherente: el tipo de parámetro 'type' es menos accesible que el operador 'operator'.

Para garantizar una accesibilidad coherente en las declaraciones de operador, haga que todos los tipos usados en los operadores públicos sean accesibles públicamente. Para obtener más información, vea Modificadores de acceso.

  • Asegúrese de que los tipos de valor devuelto tengan al menos la misma accesibilidad que el operador (CS0056).
  • Asegúrese de que los tipos de parámetro tienen al menos la misma accesibilidad que el operador (CS0057).

Al declarar un public operador, todos los tipos usados como parámetros o valores devueltos también deben ser accesibles públicamente.

En el ejemplo siguiente se muestran errores de accesibilidad:

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
}

Restricciones de conversión definidas por el usuario

  • CS0552: conversión definida por el usuario a o desde la interfaz.
  • CS0553: conversión definida por el usuario a o desde la clase base.
  • CS0554: conversión definida por el usuario a o desde la clase derivada.
  • CS0555: El operador definido por el usuario no puede tomar un objeto del tipo envolvente y convertirlo en un objeto del tipo envolvente.
  • CS0556: La conversión definida por el usuario debe convertir hacia o desde el tipo envolvente.
  • CS0557: Conversión duplicada definida por el usuario en el tipo .

Para crear operadores de conversión definidos por el usuario válidos, siga estas restricciones. Para obtener más información, vea Operadores de conversión definidos por el usuario.

  • No defina conversiones a o desde interfaces (CS0552). Use implementaciones de interfaz explícitas en su lugar.
  • No defina conversiones a clases base (CS0553) ni desde estas. La conversión ya existe a través de la herencia.
  • No defina conversiones a o desde clases derivadas (CS0554). La conversión ya existe a través de la herencia.
  • No defina conversiones del tipo envolvente a sí mismo (CS0555). Esta conversión es implícita.
  • Asegúrese de que al menos un tipo en la conversión sea el tipo contenedor (CS0556). No se pueden definir conversiones entre dos tipos externos.
  • No defina conversiones duplicadas (CS0557). Cada operador de conversión debe ser único.

En el ejemplo siguiente se muestran los errores de restricción de conversión:

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 y de cortocircuito

  • CS0215: el tipo de valor devuelto del operador true o false debe ser bool.
  • CS0216: el operador requiere que también se defina un operador coincidente.
  • CS0217: para poder aplicarse como operador de cortocircuito, un operador lógico definido por el usuario debe tener el mismo tipo de valor devuelto que el tipo de sus 2 parámetros.
  • CS0218: el tipo debe contener declaraciones del operador true y el operador false.

Para definir los operadores lógicos correctamente, siga estos requisitos de emparejamiento y firma. Para obtener más información, vea operadores true y false, operadores lógicos booleanos y operadores lógicos condicionales definidos por el usuario.

  • Devuelve bool de operator true y operator false (CS0215).
  • Definir operadores emparejados necesarios (CS0216):
    • operator == Requiere operator !=
    • operator < Requiere operator >
    • operator <= Requiere operator >=
    • operator true Requiere operator false
  • Empareja el tipo de valor devuelto con los tipos de parámetro para operadores de cortocircuito (& y |) que funcionan con tipos personalizados CS0217.
  • Implemente tanto operator true como operator false cuando use tipos personalizados en contextos booleanos como && y || (CS0218).

En el ejemplo siguiente se muestran errores 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 comprobados

  • CS9023: No se puede comprobar el operador
  • CS9024: El operador no se puede desactivar
  • CS9025: El operador Checked requiere que también se declare una versión no comprobada coincidente.

Para utilizar correctamente los operadores comprobados, siga estos requisitos. Para obtener más información, consulte Operadores aritméticos y Operadores comprobados definidos por el usuario.

  • Aplique checked palabras clave o unchecked solo a operadores aritméticos admitidos: +, -, */, ++, , --y conversiones explícitas (CS9023, CS9024).
  • Proporcione las versiones activadas y desactivadas al declarar un operador comprobado (CS9025). El compilador necesita manejar ambos para controlar diferentes contextos.

Requisitos de interfaz y herencia

  • CS9311: El tipo no implementa el miembro de interfaz. El tipo no puede implementar un miembro porque uno de ellos no es un operador
  • CS9312: El tipo no puede invalidar el miembro heredado porque uno de ellos no es un operador
  • CS9313: El operador de asignación compuesta sobrecargado toma un parámetro

Para implementar e invalidar correctamente los operadores, siga estos requisitos. Para obtener más información, consulte Sobrecarga de operadores e interfaces.

  • Asegúrese de que las declaraciones de operador coinciden con la firma y el tipo de miembros de interfaz (CS9311). Un operador no puede implementar un miembro que no sea operador.
  • Compruebe que los miembros heredados que se invalidan también son operadores (CS9312). Un operador no puede invalidar un miembro no operador.
  • Definir operadores de asignación compuestos con un parámetro (CS9313). El operando izquierdo es implícitamente this.

Operadores de igualdad

  • CS0660: El tipo define el operador == o el operador != pero no invalida Object.Equals(object o)
  • CS0661: El tipo define el operador == o el operador != pero no invalida Object.GetHashCode()

Para implementar la igualdad correctamente, invalide los métodos correspondientes Object al definir operadores de igualdad personalizados. Para obtener más información, vea Cómo definir la igualdad de valores para un tipo y operadores de igualdad.

Sobrescribir estos métodos garantiza un comportamiento de igualdad coherente en diferentes APIs y tipos de colección.