KeyValuePairのような事前に構築された構造に対して2プロパティクラスを使用する必要があるのはいつですか?


31

a KeyValuePairやa などの事前に構築された汎用構造を使用する代わりに、いつ独自のクラスにデータのキー/値型を配置する必要がありますTupleか?

たとえば、私が作成するほとんどのComboBoxには、DisplayNameとValueが含まれています。これは、新しいクラスをいつ追加し、いつKeyValuePairを使用するかを決定しようとしている種類のデータです。

私は現在iCalendar、を使用するものに取り組んでおり、選択したユーザーのデータは最終的key1=value1;key2=value2;に文字列のタイプに結合されます。最初にデータをaに入れることから始めましたKeyValuePair<string,string>が、今ではそれが代わりに独自のクラスであるのか疑問に思っています。

全体として、KeyValuePair2プロパティオブジェクトのような既存の構造/クラスを使用することを決定する際にどのガイドラインが使用されるか、また、どのような状況で他のオブジェクトを使用するかを知ることに興味があります。


3
何語?Pythonでは、tuple型があるため、このジレンマはありません。
S.Lott

3
@ S.Lott-.NET BCLにはv 4.0以降のタプルがあります。
-Oded

1
.NET 4にはタプル型もあります。msdn.microsoft.com/en-us/library/system.tuple.aspx
Dave Nay

1
この場合@Oded、私がして何かを構築していますiCalendarし、私はのためのオブジェクトを望んでいたBYDAYBYSETPOS。彼らは、コンボボックスに表示され、実際のデータがある繰り返し規則文字列に結合されているkey=value;文字列の種類
レイチェル

4
@レイチェル:質問をより具体的に更新してください。たくさんのコメントは物事を明確にする最良の方法ではありません。
-S.ロット

回答:


26

通常、ほとんどの場合、KeyValuePairやTupleではなくオブジェクトを使用します。まず、変更を加えるために6か月後に来た場合、何が意図Tuple tで、なぜ面白い値を持っているのかを考えるよりも、以前の意図を理解する方が簡単です。第二に、物事が成長し変化するにつれて、必要に応じて簡単なデータ転送オブジェクトの動作を簡単に与えることができます。2つの名前形式が必要ですか?簡単で、適切なToString()オーバーロードを追加するだけです。何らかのインターフェースを実装するために必要ですか?問題ない。最後に、特に自動プロパティとコード補完を使用して、単純なオブジェクトを作成するオーバーヘッドはほとんどゼロです。

ボーナスのヒント:これらのオブジェクトが名前空間を汚染しないようにしたい場合、クラス内にプライベートクラスを作成すると、物事をラップして奇妙な依存関係を防ぐことができます。


1
DTO = データ転送オブジェクト?-私はTLAが嫌いです;-)
ベン

3
@Ben-TFTFY 。。
ワイアットバーネット

7

新しいクラスを定義するためのルールは簡単です。「Occam's Razor」で要約されています。

http://c2.com/cgi/wiki?OccamsRazor

正当な理由なしに新しいクラスを導入しないでください。または、事前に構築されたクラスを可能な限り使用します。または、できるだけ少ない発明。ただし、コードの記述は少なくて済みます。

オブジェクトに一意の責任を割り当てる必要があり、その責任が事前に作成されたクラスで定義されていない場合、事前に作成されたクラスを使用することはできません。多くの場合、これはユニークな方法です。

A tuple又はKeyValuePair好ましいです。

まで。

A tupleまたはの一部ではない機能が必要KeyValuePairです。次に、独自のクラスを定義する必要があります。


3
あなたが盗むことができるものを設計しないでください」は、これを表現する私のお気に入りの方法についてです。
-SingleNegationElimination

1
セマンティクスを「tupleまたはの一部ではない機能」と見なしKeyValuePairますか?KeyValuePairには少なくともいくつかのセマンティクスの制限された形式がありますが、タプルがめったに(コンテキストに応じて可能になる可能性があります)ありません。新しいクラスを導入すると、当然のことながら明確なセマンティクスが得られます。
マルロス

+1プラグに適合する場合は、ボートの全体にダクトテープを貼らないでください。
エヴァンプライス

4
これは、Occamのカミソリの誤った使い方だと思います。次に、変数に含まれる情報を知ることが重要です。-1。
ベント

4

独自のクラスを作成する場合、2つの値が何であるかに関するドキュメントを置く明確な場所があります。特に、2つの文字列は明確な定義ではありません。ただし、次のように書くことができます

 public class MyPair : Tuple<string, string>

MyPairTupleの値とその用途を定義するため、これが気に入っています。
IAbstract

2
しかし、その後、プロパティが呼び出されItem1Item2!クラス全体を定義するのと同じくらい簡単ではありませんか?public class SideStrings { public string Left { get; set; } public string Right { get; set; } }
コンフィギュレー

@configuratorそれへの応答を書いていて、Tupleが読み取り専用であることに気づいたので、私はそれが全体を台無しにすると思うことに同意します。タプルをラップして、必要な値を指定できますが。
サイン

2
@Sign:しかし、ポイントは何ですか?独自のクラスを作成する方が、タプルをラップするよりも作業少なくなります。
コンフィギュレー

2
@configuratorを使用すると、カスタムオブジェクトよりも優れた同等性と比較機能が得られますが、設定が必要な場合、タプルは間違いなく間違った方法です。
サイン

4

S.Lottが書いた

正当な理由なしに新しいクラスを導入しないでください。または、事前に構築されたクラスを可能な限り使用します。可能な限り少ない発明。

事前に構築されたクラスで定義されていないオブジェクトに何らかの固有の責任を割り当てる必要がある場合、事前に構築されたクラスを使用することはできません。

なぜ私がこれに関して深刻な問題を抱えているのかをお話ししましょう。以来

KeyValuePair [string、string]

大丈夫なようです.... KeyValue [string、KeyValue [string、KeyValuePair [string、string]]]も大丈夫ですか?S.Lottがこれに対して何と言うかわかりませんが、上司はそれ大丈夫だと考えています。

私は反対します。その理由は次のとおりです。これにより、後に続くコードの可読性が低下します。そのようなデータ構造を埋める関数は、はるかに複雑で、エラー(エラー..例外)が発生しやすくなります(少なくともいくつかのビジネスロジックも同様に想像してください)。私は上司とあまり議論しませんでしたが、私はそれをここで言います:可読性はわずかなスペース節約に勝ります(これは彼の議論でし)。そのため、いくつかのフィールドがあるクラスオブジェクトはありません。しかし、いくつかは空のままになりますか?

PS私はUltra_Noobなので、間違っているかどうか教えてください。


2
KeyValuePair<string,string>投入されたものが実際にキーと値であると仮定すると、それは問題ないと思います。ここで、既存のクラスを再利用することは、コードを書くことを節約し、相互運用性を得るため、勝利ですOTOH、KeyValuePair<string,KeyValuePair<string,string>>ほとんどの場合複雑なものを使用しているため、実用的ではありません。追加の機能が不要な場合、意味が明らかな場合、および他のクラスとうまく機能する場合は、正しい場合があります。YMMV、これは単に賛否両論を重視しています。
-maaartinus

C#を使用している場合、TupleとKeyValuePairのパフォーマンスは次のとおりです。上司と共有したいことはありますか?
ベン

3

キーと値のペアを言うとき、私は通常、ハッシュテーブル、または連想配列、または単にKeyValuePairオブジェクトを考えます。私はそれらをすべて使用しますが、どちらを使用するかに違いはありません。

キーと値のペアのリストで最も重要なことは、キーは一意である必要があることです(結局キーであるため)。前述の構造はすべて、その機能を本当に提供します。

それ以外は、キーで検索するか、プッシュやポップなどのリスト(配列)スタイルのアクションを実行します。

したがって、私の答えはNOであり、キー/値のペアに対して明示的にオブジェクトを作成しません。多くの組み込み構造がすでにそれを行っているからです。


3

Clean Codeの第6章には、データ構造とクラスをいつ使用するかについての適切な説明があります。簡単に言えば、そのデータを操作するための新しい関数を追加することを主に予想するとき、データ構造を使用します。クラスを使用するのは、既存の関数によって操作される新しいデータ型を追加することを主に予想する場合です。ComboBoxは後者の例です。多くの異なるデータ型(異なるウィジェットの異なる種類のデータ)で動作する1つの関数セット(ComboBox実装)があります。


2

私はおそらくここWildingに同意するでしょうが、それから私はこの種のことでも少し初心者です。

組み込み型は多くの場合メカニズムオブジェクトであることをお勧めします。たとえば、KeyValuePairは、ディクショナリとハッシュテーブルのメカニズムの一部であり、一意のキーを確保するのに役立ち、メカニズム自体のコンテキスト内で意味のある名前を持つプロパティがあります。

一方、カスタムメイドのデータオブジェクトを使用すると、データの表現が向上し、読みやすさや拡張性などの多くの利点が得られます。Signが示唆するように、カスタムビルドオブジェクトの既存のコードの再利用を止めることは何もありませんが、ラップされたクラスを非表示にし、抽象化の漏れを回避して、コードの残りに影響を与えずに後の時点で基になる実装を変更できるようにします。

本当の質問:データを表現していますか、それともメカニズムでデータを使用していますか?(そして、これらの概念を一緒に混ぜることはお勧めしません)。

私の経験では、メソッドに渡されるTuple [string、string]を見て、Item1とItem2が何であるかをすぐに知る方法がないということは、それほど悪いことではありません。メソッド内で、またはクラスのプライベートメンバーとしてのみタプルを使用するのが最適です。

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