IComparableインターフェースは時代遅れ/「有害」ですか?


11

IComparable 一方向にしか機能しない

Employeeクラスがあるとしましょう。1つのビューでは、すべてEmployeesを名前でソートし、別のビューではアドレスでソートして表示します。どうやってそれを達成するつもりですか?ではなくIComparable、少なくとも慣用的な方法ではありません。

IComparable ロジックが間違った場所にある

を呼び出すことにより、インターフェースが使用され.Sort()ます。Customer名前で並べ替えられたビューでは、並べ替え方法を示すコードはまったくありません。
一方、Customerクラスは、どのように使用されるかを想定しています-この場合、名前でソートされたリストで使用されることを想定しています。

IComparable 暗黙的に使用されます

代替と比較して、比較ロジックがどこで使用されているか、またはまったく使用されているかどうかを確認することは非常に困難です。標準IDEを想定し、Customerクラスから始めて、

  1. へのすべての参照を検索 Customer
  2. リストで使用されている参照を見つける
  3. それらのリストが.Sort()それらを呼び出したことがあるかどうかを確認します

さらに悪いことに、IComparableまだ使用されている実装を削除しても、エラーや警告は表示されません。あなたが得る唯一のものはあなたが考えるにはあまりにもあいまいだったすべての場所で間違った行動です。

これらの問題が組み合わさり、要件が変わります

私がこれについて考えるようになったまさにその理由は、それが私にとって間違っていたからです。私はIComparable2年前からアプリケーションで喜んで使用しています。ここで、要件が変更され、物を2つの異なる方法でソートする必要があります。前のセクションで説明した手順を実行するのは面白くないことに気づきました。

質問

これらの問題により、代替手段ではうまく機能しない有効なユースケースが見られないという点で、またはにIComparable劣ると考えるようになります。LINQまたはLINQ を使用する方が常に良いのですか、それとも、ここで見られない利点/ユースケースがありますか?IComparer.OrderBy()
IComparer


2
新しい「2つの異なる方法を並べ替える」要件は、ニシンです。それを解決するには、別のコンパレーターをソート関数に渡すだけです。
ロバートハーベイ

@RobertHarveyそれではIComparable、もう使用しないことになります。
R.シュミッツ

SortedXXXコレクションを使用する場合は、保存された要素が必要であるかIComparableIComparer提供されている必要があることを忘れないでください。また、1つの比較演算子で自然な並べ替え順序を逆にして、すべてのIComparableオブジェクトで機能させることは簡単です。
ベリンロリチュ

2
2つの異なるインターフェイスがあることは問題ではありません。 デフォルトの比較メカニズムIComparableと見なされますIComparerデフォルトの比較メカニズムをオーバーライドする場合に使用されます。
ロバートハーベイ

回答:


14

IComparableあなたが言及した制限があります、それは正しいです。これは、.NET framework 1.0ですでに利用可能なインターフェイスであり、これらの機能的な代替手段とLinqは利用できませんでした。それで、はい、主に後方互換性のために保持されている時代遅れのフレームワーク要素としてそれを見るかもしれません。

ただし、多くの単純なデータ構造では、ソートの1つの方法でおそらく十分または自然です。これらのケースでは、順序関係を実装する標準的な場所を1つ持つことは、コードをDRYに維持するための優れた方法であり、場所を問わずすべての呼び出しで同じロジックを常に繰り返すのではありませんOrderBy

あなたが書いたように、「2年前からアプリケーションでIComparableを喜んで使用している」ので、私には長い間役立ったようです。のすべての呼び出しを検証、変更、およびテストSortする必要がある場合、それは多くの場所で同じ種類のソートロジックを実行していた兆候である可能性がありますが、これはの障害ではありませんIComparable。そのため、このロジックを1か所に集中させて、コードをよりドライにできます。


単純なデータ構造についての良い点。ただし、最後の段落は100%意味がありません。を使用していなかった場合IComparable、既存のすべての並べ替えコードはそれぞれのビューで変更されず、新しいビューに新しい並べ替えコードのみを追加していました。
R.シュミッツ

@ R.Schmitz IComparableあなたが書いた実装がなくても、既存のソートは正しく機能したでしょうか?
ロバートハーヴェイ

3
@ R.Schmitz:確かに、しかし今は常にコンパレーターを提供することにコミットしています(もちろん、OrderByを使用している場合を除きます)。を使用IComparableすると、デフォルトの実装を無料で入手でき、場合によってはその実装を作成する必要さえありません。
ロバートハーヴェイ

2
@ R.Schmitz:あなたの最後のコメントは、ポイントをうまくまとめています。しかし、私はもう少し先に行きます。のような数値型があるとしますBigInteger。比較演算子/インターフェイスを実装していなかった場合、自分でIComparerをどのように実装しますか?内部データ構造にアクセスして、効率的に、またはまったくそれを行う必要があります。Customerのようなタイプがあるとします。並べ替えたいパブリックプロパティには比較演算子あります。私にとってそれは違いです:呼び出し元が比較器を実装することを期待IComparable<T>するのが不合理である場合に実装します。
エリックリッパー

1
If I hadn't used IComparable, all the pre-existing sorting code would have been left untouched in their respective views, while I'd only add new sorting code for the new view.理由だけIComparableだった、より良い解決策時点で、それはある意味ではありません最善のソリューション今日。ここでの最初のコメントは、「IComparable or nothing」であり、これは真実ではなく、問題はさまざまな方法で解決できたことを意味します。アプリケーションのサイズ/スケールは拡大する可能性があり、以前は適切に見えていたものでも、アプリケーションの増大する要求に対応できない場合があります。
18年

1

についてのあなたの感情に同意します IComparable

上のコメントを見てください Array.Sort()

  • 配列の各要素は、配列IComparable内の他のすべての要素と比較できるようにインターフェースを実装する必要があります。(または例外がスローされます)
  • ソートが正常に完了しない場合、結果は未定義です。

おそらく今はモチベーションにならないでしょう。しかし!object.Equals()オブジェクトを互いに比較して「同じ」かどうかを確認できるメソッドをすべてのオブジェクトで検討する

既にそこにありArray.Sort()ますが、追加が必要な場合があります。object.Compare(object)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.