重载或用户定义的运算符声明的错误和警告

声明重载运算符时有几个错误。 重载运算符也称为用户定义的运算符

  • CS0056可访问性不一致:返回类型"type"的可访问性低于运算符"operator"
  • CS0057不一致的可访问性:参数类型“type”的可访问性低于运算符“operator”
  • CS0215运算符 True 或 False 的返回类型必须为布尔值
  • CS0216运算符“operator”需要同时定义匹配的运算符“missing_operator”
  • CS0217为了作为短路运算符适用,用户定义的逻辑运算符('operator')必须具有与其 2 个参数的类型相同的返回类型。
  • CS0218类型('type')必须包含运算符 true 和运算符 false 的声明
  • CS0448运算符++--的返回类型必须为包含类型或派生自包含类型
  • CS0552“转换例程”:用户定义的到/从接口转换
  • CS0553“转换例程”:用户定义的到基类/从基类转换
  • CS0554“转换例程”:用户定义的到派生类/从派生类转换
  • CS0555用户定义的运算符不能接受封闭类型的对象并转换为封闭类型的对象
  • CS0556用户定义的转换必须转换为封闭类型或从封闭类型转换
  • CS0557类型中重复用户定义转换
  • CS0558用户定义的运算符必须声明为静态和公共运算符
  • CS0559++--运算符的参数类型必须是包含类型
  • CS0562一元运算符的参数必须是包含类型
  • CS0563二进制运算符的参数之一必须是包含类型
  • CS0564重载移位运算符的第一个作数必须与包含类型具有相同的类型,并且第二个作数的类型必须为 int
  • CS0567接口不能包含运算符
  • CS0590用户定义的运算符无法返回 void
  • CS0660类型定义 operator ==operator != 未重写 Object.Equals(object o)
  • CS0661类型定义了 operator ==operator != 但未重写 Object.GetHashCode()
  • CS0715静态类不能包含用户定义的运算符
  • CS1037应有可重载运算符
  • CS1553声明无效;应使用“modifier 运算符 <dest-type> (...)”而不是当前形式
  • CS8930:用户定义的 运算符的显式实现必须是静态的。
  • CS8931显式实现必须声明为公共实现,才能在类型中实现接口成员。
  • CS9023操作符无法设为检查状态。
  • CS9024运算符无法标记为不受检查。
  • CS9025操作员需要声明匹配的非检查版本。
  • CS9308用户定义的运算符必须声明为公共运算符。
  • CS9310此运算符的返回类型必须为 void。
  • CS9311类型不实现接口成员。类型无法实现成员,因为它们之一不是运算符。
  • CS9312类型无法替代继承的成员,因为其中一个成员不是操作员。
  • CS9313重载复合赋值运算符采用一个参数。

以下部分提供了常见问题的示例以及如何解决这些问题。

操作员签名要求

  • CS0448++--运算符的返回类型必须是包含类型或派生自包含类型的类型。
  • CS0559++-- 运算符的参数类型必须是其所属类型。
  • CS0562一元运算符的参数必须是包含类型。
  • CS0563二进制运算符的参数之一必须是包含类型。
  • CS0564重载移位运算符的第一个操作数必须与包含类型相同,并且第二个操作数的类型必须为 int。
  • CS0567接口不能包含运算符。
  • CS0590用户定义的运算符不能返回 void。
  • CS9310此运算符的返回类型必须为 void。

当运算符声明不遵循所需的签名规则时,会发生这些错误。 每个运算符类型都有参数类型和返回类型的特定要求。

重要

静态二进制运算符和相应的实例复合赋值运算符的签名要求不同。 确保签名与所需的声明匹配。

有关详细信息,请参阅 运算符重载。 以下示例演示了以下错误:

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
}

若要修复这些错误,请确保操作员声明遵循重载的特定运算符类型的签名要求。

运算符声明要求

  • CS0558用户定义的运算符必须声明为静态和公共运算符。
  • CS0715静态类不能包含用户定义的运算符。
  • CS1037: 需要可重载的运算符。
  • CS1553声明无效,应使用“modifier 运算符 <dest-type> (...”。
  • CS8930:用户定义的 运算符的显式实现必须是静态的。
  • CS8931显式实现必须声明为公共实现,才能在类型中实现接口成员。
  • CS9308用户定义的运算符必须声明为公共运算符。

当运算符声明不使用所需的修饰符或语法时,会发生这些错误。 大多数用户定义的运算符必须同时具有 staticpublic并且转换运算符需要特定的语法。 有关详细信息,请参阅 运算符重载用户定义的转换运算符。 以下代码演示了以下错误:

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
}

若要修复这些错误,请确保运算符声明包括必需 staticpublic 修饰符,遵循转换运算符的正确语法,并且不要在静态类中声明运算符。

可访问性不一致

  • CS0056不一致的可访问性:返回类型“type”的可访问性低于运算符“operator”的可访问性。
  • CS0057不一致性:参数类型“type”的可访问性低于运算符“operator”。

当你声明一个公共运算符并且其返回类型或参数类型的可访问性比运算符本身更为严格时,就会出现这些错误。 所有公共构造都必须对其参数和返回值使用可公开访问的类型。 有关详细信息,请参阅 访问修饰符

以下代码片段演示了以下错误:

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
}

若要解决这些错误,请确保公共运算符声明中使用的所有类型也可供公开访问。

用户定义的转换限制

  • CS0552用户定义到/从接口转换。
  • CS0553用户定义的到/从基类的转换。
  • CS0554从派生类到/从派生类进行用户定义的转换。
  • CS0555用户定义的运算符不能采用封闭类型的对象并转换为封闭类型的对象。
  • CS0556用户定义的转换必须转换为封闭类型或从封闭类型转换。
  • CS0557类型中重复用户定义转换。

尝试创建无效的用户定义转换运算符时,会发生这些错误。 转换运算符在可以互相转换的类型之间存在特定的限制。 有关详细信息,请参阅用户定义转换运算符。 以下代码演示了前面的错误:

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

若要修复这些错误,请删除无效的转换运算符或重构类型层次结构,以避免受限的转换模式。

布尔运算符和短路运算符

  • CS0215运算符 true 或 false 的返回类型必须为布尔值。
  • CS0216该运算符需要同时定义匹配的运算符。
  • CS0217为了作为短路运算符适用,用户定义的逻辑运算符必须与其 2 个参数的类型具有相同的返回类型。
  • CS0218类型必须包含运算符 true 和运算符 false 的声明。

错误地定义逻辑运算符时,会发生这些错误。 某些运算符必须成对定义,短路运算符具有特定的签名要求。 有关详细信息,请参阅 true 和 false 运算符布尔逻辑运算符用户定义的条件逻辑运算符。 以下代码演示了以下错误:

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

若要修复这些错误,请确保定义所需的配对运算符,并遵循逻辑运算符的正确签名模式。

选中的运算符

  • CS9023无法检查操作员
  • CS9024运算符无法设为未检查状态
  • CS9025已检查的操作员需要声明匹配的非检查版本

当错误地将 checkedunchecked 关键字用于运算符声明时,会发生这些错误。 并非所有运算符都支持已检查/未检查的变体,在支持这些变体时,必须满足某些要求。 有关详细信息,请参阅 算术运算符用户定义的检查运算符

若要修复这些错误,请从不支持它的运算符中删除 checkedunchecked 关键字,或确保在需要时同时提供已检查版本和非检查版本。

接口和继承要求

  • CS9311类型不实现接口成员。类型无法实现成员,因为其中一个不是运算符
  • CS9312类型无法替代继承的成员,因为其中一个不是操作员
  • CS9313重载复合赋值运算符接受一个参数

当运算符声明与接口实现或继承关系不匹配时,会发生这些错误。 运算符具有接口实现和重写的特定规则。 有关详细信息,请参阅 运算符重载接口

若要修复这些错误,请确保运算符声明正确匹配接口要求,并遵循运算符重写和复合赋值运算符的规则。

相等运算符

  • CS0660类型定义运算符 == 或运算符 != 但不会重写 Object.Equals(object o)
  • CS0661类型定义运算符 == 或运算符 != 但不会重写 Object.GetHashCode()

定义相等运算符或不相等运算符时,如果未重写相应的方法Object,则会出现这些警告。 定义自定义相等比较时,还应重写 Object.EqualsObject.GetHashCode 以确保行为一致。 有关详细信息,请参阅如何为类型定义值相等相等运算符

若要修复这些警告,请在定义自定义相等运算符时,同时重写EqualsGetHashCode