CA1013: オーバーロードする加算および減算で、演算子 equals をオーバーロードします
TypeName |
OverloadOperatorEqualsOnOverloadingAddAndSubtract |
CheckId |
CA1013 |
分類 |
Microsoft.Design |
互換性に影響する変更点 |
なし |
原因
パブリック型またはプロテクト型で、等値演算子を実装しないまま、加算演算子または減算演算子を実装しています。
規則の説明
加算や減算などの演算を使用して型のインスタンスを結合できる場合、同じ構成値を持つ任意の 2 つのインスタンスについて true を返すには、ほぼ常に等値性を定義する必要があります。
等値演算子がオーバーロードされた実装では、既定の等値演算子は使用できません。使用すると、スタック オーバーフローが発生します。等値演算子を実装するには、Object.Equals メソッドを使用します。次の例を参照してください。
If (Object.ReferenceEquals(left, Nothing)) Then
Return Object.ReferenceEquals(right, Nothing)
Else
Return left.Equals(right)
End If
if (Object.ReferenceEquals(left, null))
return Object.ReferenceEquals(right, null);
return left.Equals(right);
違反の修正方法
この規則違反を修正するには、等値演算子を実装して、数学的に加算演算子および減算演算子と合わせます。
警告を抑制する状況
既定の実装の等値演算子でも型が正しく機能する場合は、この規則による警告を抑制しても安全です。
使用例
この規則に違反する型 (BadAddableType) の定義を次の例に示します。この型では、等値演算子を実装し、同じフィールドを持つ任意の 2 つのインスタンスについて、等値性の true をテストする必要があります。型 GoodAddableType は、正しい実装例です。この型では、非等値演算子も実装し、Equals をオーバーライドしている点に注意してください。これは他の規則に適合するためです。実際に使用する場合、GetHashCode も実装します。
using System;
namespace DesignLibrary
{
public class BadAddableType
{
private int a, b;
public BadAddableType(int a, int b)
{
this.a = a;
this.b = b;
}
// Violates rule: OverrideOperatorEqualsOnOverridingAddAndSubtract.
public static BadAddableType operator +(BadAddableType a, BadAddableType b)
{
return new BadAddableType(a.a + b.a, a.b + b.b);
}
// Violates rule: OverrideOperatorEqualsOnOverridingAddAndSubtract.
public static BadAddableType operator -(BadAddableType a, BadAddableType b)
{
return new BadAddableType(a.a - b.a, a.b - b.b);
}
public override string ToString()
{
return String.Format("{{{0},{1}}}", a, b);
}
}
public class GoodAddableType
{
private int a, b;
public GoodAddableType(int a, int b)
{
this.a = a;
this.b = b;
}
// Satisfies rule: OverrideOperatorEqualsOnOverridingAddAndSubtract.
public static bool operator ==(GoodAddableType a, GoodAddableType b)
{
return (a.a == b.a && a.b == b.b);
}
// If you implement ==, you must implement !=.
public static bool operator !=(GoodAddableType a, GoodAddableType b)
{
return !(a==b);
}
// Equals should be consistent with operator ==.
public override bool Equals(Object obj)
{
GoodAddableType good = obj as GoodAddableType;
if (obj == null)
return false;
return this == good;
}
public static GoodAddableType operator +(GoodAddableType a, GoodAddableType b)
{
return new GoodAddableType(a.a + b.a, a.b + b.b);
}
public static GoodAddableType operator -(GoodAddableType a, GoodAddableType b)
{
return new GoodAddableType(a.a - b.a, a.b - b.b);
}
public override string ToString()
{
return String.Format("{{{0},{1}}}", a, b);
}
}
}
次の例では、上記で定義した型のインスタンスを使用して等値性をテストしています。これで、等値演算子の既定の動作と修正後の動作がわかります。
using System;
namespace DesignLibrary
{
public class TestAddableTypes
{
public static void Main()
{
BadAddableType a = new BadAddableType(2,2);
BadAddableType b = new BadAddableType(2,2);
BadAddableType x = new BadAddableType(9,9);
GoodAddableType c = new GoodAddableType(3,3);
GoodAddableType d = new GoodAddableType(3,3);
GoodAddableType y = new GoodAddableType(9,9);
Console.WriteLine("Bad type: {0} {1} are equal? {2}", a,b, a.Equals(b)? "Yes":"No");
Console.WriteLine("Good type: {0} {1} are equal? {2}", c,d, c.Equals(d)? "Yes":"No");
Console.WriteLine("Good type: {0} {1} are == ? {2}", c,d, c==d? "Yes":"No");
Console.WriteLine("Bad type: {0} {1} are equal? {2}", a,x, a.Equals(x)? "Yes":"No");
Console.WriteLine("Good type: {0} {1} are == ? {2}", c,y, c==y? "Yes":"No");
}
}
}
この例を実行すると、次の出力が生成されます。
参照
その他の技術情報
Guidelines for Implementing Equals and the Equality Operator (==)