以下は、==演算子のオーバーロードメソッドで無限再帰を引き起こします
Foo foo1 = null;
Foo foo2 = new Foo();
Assert.IsFalse(foo1 == foo2);
public static bool operator ==(Foo foo1, Foo foo2) {
if (foo1 == null) return foo2 == null;
return foo1.Equals(foo2);
}
Nullをチェックするにはどうすればよいですか?
ReferenceEquals
を使用します:
Foo foo1 = null;
Foo foo2 = new Foo();
Assert.IsFalse(foo1 == foo2);
public static bool operator ==(Foo foo1, Foo foo2) {
if (object.ReferenceEquals(null, foo1))
return object.ReferenceEquals(null, foo2);
return foo1.Equals(foo2);
}
オーバーロードメソッドでオブジェクトにキャストします。
public static bool operator ==(Foo foo1, Foo foo2) {
if ((object) foo1 == null) return (object) foo2 == null;
return foo1.Equals(foo2);
}
ReferenceEquals
を使用します。 MSDNフォーラム から:
public static bool operator ==(Foo foo1, Foo foo2) {
if (ReferenceEquals(foo1, null)) return ReferenceEquals(foo2, null);
if (ReferenceEquals(foo2, null)) return false;
return foo1.field1 == foo2.field2;
}
Object.ReferenceEquals(foo1, null)
を試してください
とにかく、==
operatorをオーバーロードすることはお勧めしません。参照の比較に使用し、「セマンティック」比較にはEquals
を使用する必要があります。
C#7以降を使用している場合は、null定数パターンマッチングを使用できます。
public static bool operator==(Foo foo1, Foo foo2)
{
if (foo1 is null)
return foo2 is null;
return foo1.Equals(foo2);
}
これにより、オブジェクトを呼び出すものよりも少しすっきりとしたコードが得られます。ReferenceEquals(foo1、null)
bool Equals(object obj)
をオーバーライドし、演算子_==
_とFoo.Equals(object obj)
で同じ答えを返したい場合は、通常、次のように_!=
_演算子を実装します。
_public static bool operator ==(Foo foo1, Foo foo2) {
return object.Equals(foo1, foo2);
}
public static bool operator !=(Foo foo1, Foo foo2) {
return !object.Equals(foo1, foo2);
}
_
演算子_==
_は、すべてのnullチェックを実行した後、2つが等しい場合に実際のチェックを実行するためにオーバーライドしたfoo1.Equals(foo2)
を呼び出すことになります。
この場合、実際にはnull
に対してチェックするより簡単な方法があります。
if (foo is null)
それでおしまい!
この機能はC#7で導入されました
私のアプローチはすることです
_(object)item == null
_
私はobject
自身の等式演算子に頼っています。これは間違いありません。またはカスタム拡張メソッド(およびオーバーロード):
_public static bool IsNull<T>(this T obj) where T : class
{
return (object)obj == null;
}
public static bool IsNull<T>(this T? obj) where T : struct
{
return !obj.HasValue;
}
_
または、より多くのケースを処理するには、次のようになります。
_public static bool IsNull<T>(this T obj) where T : class
{
return (object)obj == null || obj == DBNull.Value;
}
_
制約は、値型のIsNull
を防ぎます。今では呼び出すのと同じくらい甘い
_object obj = new object();
Guid? guid = null;
bool b = obj.IsNull(); // false
b = guid.IsNull(); // true
2.IsNull(); // error
_
つまり、全体を通してnullをチェックする一貫した/エラーが発生しにくいスタイルが1つあります。私はまた、 _(object)item == null
_はObject.ReferenceEquals(item, null)
よりも非常にわずかに速いことを発見しましたが、それが重要な場合に限ります(私は現在、マイクロ化する必要がある何かに取り組んでいます-すべてを最適化してください!)。
等価性チェックの実装に関する完全なガイドを参照するには、 参照型の2つのインスタンスを比較するための「ベストプラクティス」とは何ですか? を参照してください。
もっと返信する nullと比較する方法をオーバーライドする演算子 ここで重複としてリダイレクトします。
値オブジェクトをサポートするためにこれが行われている場合、私は新しい表記法が便利であると感じ、比較が行われる場所が1つだけであることを確認したいと思います。また、Object.Equals(A、B)を利用すると、ヌルチェックが簡素化されます。
これにより、==、!=、Equals、およびGetHashCodeがオーバーロードされます
public static bool operator !=(ValueObject self, ValueObject other) => !Equals(self, other);
public static bool operator ==(ValueObject self, ValueObject other) => Equals(self, other);
public override bool Equals(object other) => Equals(other as ValueObject );
public bool Equals(ValueObject other) {
return !(other is null) &&
// Value comparisons
_value == other._value;
}
public override int GetHashCode() => _value.GetHashCode();
より複雑なオブジェクトの場合は、Equalsとより豊富なGetHashCodeに比較を追加します。
現代的で凝縮された構文の場合:
public static bool operator ==(Foo x, Foo y)
{
return x is null ? y is null : x.Equals(y);
}
public static bool operator !=(Foo x, Foo y)
{
return x is null ? !(y is null) : !x.Equals(y);
}
静的Equals(Object, Object)
メソッド は、2つのオブジェクトobjA
とobjB
が等しいかどうかを示します。また、値がnull
であるオブジェクトが等しいかどうかをテストすることもできます。次のように、objA
とobjB
が等しいかどうかを比較します。
true
を返します。このテストは、ReferenceEquals
メソッドを呼び出すのと同じです。さらに、objA
とobjB
の両方がnull
の場合、メソッドはtrue
を返します。objA
またはobjB
のいずれかがnull
であるかどうかを判別します。その場合、false
を返します。 2つのオブジェクトが同じオブジェクト参照を表しておらず、どちらもnull
でない場合、objA.Equals(objB)
を呼び出して、結果を返します。これは、objA
がObject.Equals(Object)
メソッドをオーバーライドする場合、このオーバーライドが呼び出されることを意味します。。
public static bool operator ==(Foo objA, Foo objB) {
return Object.Equals(objA, objB);
}