26

Find メソッドを含むカスタム汎用データ構造があります。

public bool Find(TValue value, IEqualityComparer<TValue> comparer)
{
    foreach (var x in items)
    {
        if (comparer.Equals(value, x))
            return true;
    }
    return false;
}

私は最近、あるクライアントから、コレクション内の項目の 1 つが であるNullReferenceException場合valueに等値比較器がスローされるという報告を受けました。nullnull

私の最初の反応は、値IEqualityComparer<T>.Equalsを適切に処理していないため、彼の実装は誤りであるというものでした。nullしかし、明示的に私をバックアップするドキュメントを見つけることができませんでした。私が正しいことを示す証拠はいくつかありますが、明確なものはありません。

まず、単純な呼び出しを次のように変更するのはばかげているようですcomparer.Equals

if (x == null)
{
    if (value == null)
        return true;
}
else if (value != null && comparer.Equals(value, x))
    return true;

第二に、Object.Equalsのドキュメントには、とりわけ次のように書かれています。

  • x.Equals(null)戻りますfalse
  • の実装はEquals例外をスローしてはなりません。

これは、 IEqualityComparer<T>.Equalsが null パラメーターを適切に処理する必要があることの強力な証拠です。

その他の証拠は、IComparer.Compareのドキュメントに次のように記載されていることです。

null を任意の参照型と比較することは許可されており、例外は生成されません。null 参照は、null でない参照よりも小さいと見なされます。

IEqualityComparer<T>.Equals同様に行動することが期待されます。ただし、そのページに示されている例はNullReferenceException、いずれかのパラメーターがnull.

Object.EqualsIEquatable<T>IEqualityComparer<T>、およびのドキュメントとIEqualityComparer、数え切れないほどのブログ投稿、記事、および SO の質問に目を通しました。nullパラメータの処理方法に関する具体的なガイドラインはありません。

そのようなガイドラインは存在しますか?そうでない場合、教祖は何を推奨していますか? またその理由は何ですか?

4

4 に答える 4

26

IEqualityComparer.Equalsすべてのメソッドをモデル化する必要がある .NET フレームワーク自体の最も近いメソッドは、静的Object.Equals(object,object)メソッドです。ドキュメントによると、このメソッドはnulls を適切に処理します。これは、.NET 設計者の意図を十分に示していると思いますIEqualityComparer.Equals。null も処理する必要があり、同様の方法で処理する必要があります (つまり、2 つnullの s を互いに同等に扱う)。

于 2012-12-12T02:25:26.037 に答える
2

FxCop が使用するガイドラインには、パブリック型のすべてのパブリック メソッドが null 引数を処理する必要があるという規定が含まれていますArgumentNullException。あなたの場合、Object.Equalsあなたが指摘したことを考えると、nullテストを実行してfalseを返すだけで済みます-nullのみがnullと等しいためです:)

これはここに文書化されています: http://msdn.microsoft.com/en-us/library/ms182182(v=VS.80).aspx

于 2012-12-12T02:17:25.640 に答える
1

さて、EqualityComparer<T>抽象基本クラス(インターフェースではありませんが、それを実装します)には、そのEqualsメソッドに関するコメントがいくつかあります。

MSDNはEqualityComparer<T>.Equals(T, T)、既知の例外が通常スローされることを述べていません(そして、MSDNは通常、例外の一覧表示についてはかなり優れています)。確かに、任意のクラス(カスタムまたはBCL)を渡し、それをと比較してnullも、例外はスローされません。

http://msdn.microsoft.com/en-us/library/ms132154.aspx

于 2012-12-12T02:40:13.603 に答える
1

の値はnull、他の値と見なす必要があります。2 つのボックスの内容が同一であると見なすべきかどうかを尋ねられた場合、ボックスの一方または両方が空であっても、その質問は完全に有効です。両方のボックスが空の場合、(非) 内容は同じです。一方が空で、もう一方がそうでない場合、それらは明らかに完全に同等ではなく、おそらく同等とは言えませんが、合法的に比較できる場合があります。

Object.Equals(Object)andによって定義されるデフォルトの等価関係IEquatable<T>.Equals(T)(定義されている場合、後者は前者と同じ関係を使用する必要があります) は、基本的にすべての点で同等である場合にのみ、それらを等しいと見なすべきであり、その定義により、null 以外のオブジェクトはできません。 null と同等と見なされます (nullそれ自体を非 null オブジェクトと比較する手段がないため)。一方、 の2 つのインスタンスが明らかに同じではない場合でも、の 2 つのインスタンスをその目的上同等であるIEqualityComparer<T>と定義することはまったく正常です。問題の関数が正当な値と見なされる場合、関数が返す値と同じ値を返す null 以外の値Tnullnullと等しいはずnullです。

于 2012-12-15T21:18:51.777 に答える