Edit

Share via


Errors and warnings for overloaded, or user-defined operator declarations

There are several errors related to declaring overloaded operators. Overloaded operators are also referred to as user-defined operators

  • CS0056: Inconsistent accessibility: return type 'type' is less accessible than operator 'operator'
  • CS0057: Inconsistent accessibility: parameter type 'type' is less accessible than operator 'operator'
  • CS0215: The return type of operator True or False must be bool
  • CS0216: The operator 'operator' requires a matching operator 'missing_operator' to also be defined
  • CS0217: In order to be applicable as a short circuit operator a user-defined logical operator ('operator') must have the same return type as the type of its 2 parameters.
  • CS0218: The type ('type') must contain declarations of operator true and operator false
  • CS0448: The return type for ++ or -- operator must be the containing type or derived from the containing type
  • CS0552: 'conversion routine' : user defined conversion to/from interface
  • CS0553: 'conversion routine' : user defined conversion to/from base class
  • CS0554: 'conversion routine' : user defined conversion to/from derived class
  • CS0555: User-defined operator cannot take an object of the enclosing type and convert to an object of the enclosing type
  • CS0556: User-defined conversion must convert to or from the enclosing type
  • CS0557: Duplicate user-defined conversion in type
  • CS0558: User-defined operator must be declared static and public
  • CS0559: The parameter type for ++ or -- operator must be the containing type
  • CS0562: The parameter of a unary operator must be the containing type
  • CS0563: One of the parameters of a binary operator must be the containing type
  • CS0564: The first operand of an overloaded shift operator must have the same type as the containing type, and the type of the second operand must be int
  • CS0567: Interfaces cannot contain operators
  • CS0590: User-defined operators cannot return void
  • CS0660: Type defines operator == or operator != but does not override Object.Equals(object o)
  • CS0661: Type defines operator == or operator != but does not override Object.GetHashCode()
  • CS0715: Static classes cannot contain user-defined operators
  • CS1037: Overloadable operator expected
  • CS1553: Declaration is not valid; use 'modifier operator <dest-type> (...' instead
  • CS8930: Explicit implementation of a user-defined operator must be static.
  • CS8931: Explicit implementation must be declared public to implement interface member in type.
  • CS9023: Operator cannot be made checked.
  • CS9024: Operator cannot be made unchecked.
  • CS9025: Operator requires a matching non-checked version to also be declared.
  • CS9308: User-defined operator must be declared public.
  • CS9310: The return type for this operator must be void.
  • CS9311: Type does not implement interface member. The type cannot implement member because one of them is not an operator.
  • CS9312: Type cannot override inherited member because one of them is not an operator.
  • CS9313: Overloaded compound assignment operator takes one parameter.

The following sections provide examples of common issues and how to fix them.

Operator signature requirements

  • CS0448: The return type for ++ or -- operator must be the containing type or derived from the containing type.
  • CS0559: The parameter type for ++ or -- operator must be the containing type.
  • CS0562: The parameter of a unary operator must be the containing type.
  • CS0563: One of the parameters of a binary operator must be the containing type.
  • CS0564: The first operand of an overloaded shift operator must have the same type as the containing type, and the type of the second operand must be int.
  • CS0567: Interfaces can't contain operators.
  • CS0590: User-defined operators can't return void.
  • CS9310: The return type for this operator must be void.

These errors occur when operator declarations don't follow the required signature rules. Each operator type has specific requirements for parameter types and return types.

Important

The signature requirements for static binary operators and the corresponding instance compound assignment operators are different. Make sure the signature matches the declaration you want.

For more information, see Operator overloading. The following example demonstrates these errors:

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
}

To fix these errors, ensure your operator declarations follow the signature requirements for the specific operator type you're overloading.

Operator declaration requirements

  • CS0558: User-defined operator must be declared static and public.
  • CS0715: Static classes can't contain user-defined operators.
  • CS1037: Overloadable operator expected.
  • CS1553: Declaration isn't valid; use 'modifier operator <dest-type> (...' instead.
  • CS8930: Explicit implementation of a user-defined operator must be static.
  • CS8931: Explicit implementation must be declared public to implement interface member in type.
  • CS9308: User-defined operator must be declared public.

These errors occur when operator declarations don't use the required modifiers or syntax. Most user-defined operators must be both static and public, and conversion operators require specific syntax. For more information, see Operator overloading and User-defined conversion operators. The following code demonstrates these errors:

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
}

To fix these errors, ensure your operator declarations include the required static and public modifiers, follow the correct syntax for conversion operators, and don't declare operators in static classes.

Inconsistent accessibility

  • CS0056: Inconsistent accessibility: return type 'type' is less accessible than operator 'operator'.
  • CS0057: Inconsistent accessibility: parameter type 'type' is less accessible than operator 'operator'.

These errors occur when you declare a public operator with return types or parameter types that have more restrictive accessibility than the operator itself. All public constructs must use publicly accessible types for their parameters and return values. For more information, see Access Modifiers.

The following code snippets demonstrate these errors:

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
}

To fix these errors, make sure all types used in public operator declarations are also publicly accessible.

User-defined conversion restrictions

  • CS0552: User-defined conversion to/from interface.
  • CS0553: User-defined conversion to/from base class.
  • CS0554: User-defined conversion to/from derived class.
  • CS0555: User-defined operator can't take an object of the enclosing type and convert to an object of the enclosing type.
  • CS0556: User-defined conversion must convert to or from the enclosing type.
  • CS0557: Duplicate user-defined conversion in type.

These errors occur when you attempt to create invalid user-defined conversion operators. Conversion operators have specific restrictions about which types they can convert between. For more information, see User-defined conversion operators. The following code demonstrates the preceding errors:

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

To fix these errors, remove invalid conversion operators or restructure your type hierarchy to avoid the restricted conversion patterns.

Boolean and short-circuit operators

  • CS0215: The return type of operator true or false must be bool.
  • CS0216: The operator requires a matching operator to also be defined.
  • CS0217: In order to be applicable as a short-circuit operator, a user-defined logical operator must have the same return type as the type of its 2 parameters.
  • CS0218: The type must contain declarations of operator true and operator false.

These errors occur when you define logical operators incorrectly. Certain operators must be defined in pairs, and short-circuit operators have specific signature requirements. For more information, see true and false operators, Boolean logical operators, and User-defined conditional logical operators. The following code demonstrates these errors:

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

To fix these errors, ensure you define required paired operators and follow the correct signature patterns for logical operators.

Checked operators

  • CS9023: Operator can't be made checked
  • CS9024: Operator can't be made unchecked
  • CS9025: Checked operator requires a matching non-checked version to also be declared

These errors occur when you incorrectly use the checked or unchecked keywords with operator declarations. Not all operators support checked/unchecked variants, and when they do, certain requirements must be met. For more information, see Arithmetic operators and User-defined checked operators.

To fix these errors, either remove the checked or unchecked keyword from operators that don't support it, or ensure you provide both checked and non-checked versions when required.

Interface and inheritance requirements

  • CS9311: Type doesn't implement interface member. The type can't implement member because one of them isn't an operator
  • CS9312: Type can't override inherited member because one of them isn't an operator
  • CS9313: Overloaded compound assignment operator takes one parameter

These errors occur when there are mismatches between operator declarations and interface implementations or inheritance relationships. Operators have specific rules for interface implementation and overriding. For more information, see Operator overloading and Interfaces.

To fix these errors, ensure that operator declarations correctly match interface requirements and follow the rules for operator overriding and compound assignment operators.

Equality operators

  • CS0660: Type defines operator == or operator != but doesn't override Object.Equals(object o)
  • CS0661: Type defines operator == or operator != but doesn't override Object.GetHashCode()

These warnings occur when you define equality or inequality operators without also overriding the corresponding methods from Object. When you define custom equality comparison, you should also override Object.Equals and Object.GetHashCode to ensure consistent behavior. For more information, see How to define value equality for a type and Equality operators.

To fix these warnings, override both Equals and GetHashCode when you define custom equality operators.