45

C#ジェネリック以前は、IEnumerableを実装したコレクションベースを作成することで、誰もがビジネスオブジェクトのコレクションをコーディングしていました。

IE:

public class CollectionBase : IEnumerable

そして、そこからビジネスオブジェクトコレクションを導き出します。

public class BusinessObjectCollection : CollectionBase

ジェネリックリストクラスを使用して、代わりにそれを使用する人はいますか?私は2つのテクニックの妥協点を使用していることに気づきました。

public class BusinessObjectCollection : List<BusinessObject>

これを行うのは、リストを渡すだけでなく、強く型付けされた名前が好きだからです。

あなたのアプローチは何ですか?

4

18 に答える 18

49

何らかの理由でデータ構造をカプセル化し、その機能の限定されたサブセットを提供する必要がない限り、私は通常、リストを直接使用するという陣営にいます。これは主に、カプセル化の特別な必要性がない場合、それを行うのは時間の無駄だからです。

ただし、C#3.0の集計初期化機能では、カスタマイズされたコレクションクラスを使用することを推奨する新しい状況がいくつかあります。

基本的に、C#3.0ではIEnumerable、Addメソッドを実装し、持つすべてのクラスで、新しい集計初期化子構文を使用できます。たとえば、DictionaryはメソッドAdd(K key、V value)を定義しているため、次の構文を使用してディクショナリを初期化できます。

var d = new Dictionary<string, int>
{
    {"hello", 0},
    {"the answer to life the universe and everything is:", 42}
};

この機能の優れている点は、任意の数の引数を持つaddメソッドで機能することです。たとえば、次のコレクションがあるとします。

class c1 : IEnumerable
{
    void Add(int x1, int x2, int x3)
    {
        //...
    }

    //...
}

次のように初期化することが可能です。

var x = new c1
{
    {1,2,3},
    {4,5,6}
}

これは、複雑なオブジェクトの静的テーブルを作成する必要がある場合に非常に役立ちます。たとえば、使用List<Customer>しているだけで、顧客オブジェクトの静的リストを作成したい場合は、次のように作成する必要があります。

var x = new List<Customer>
{
    new Customer("Scott Wisniewski", "555-555-5555", "Seattle", "WA"),
    new Customer("John Doe", "555-555-1234", "Los Angeles", "CA"),
    new Customer("Michael Scott", "555-555-8769", "Scranton PA"),
    new Customer("Ali G", "", "Staines", "UK")
}

ただし、次のようなカスタマイズされたコレクションを使用する場合:

class CustomerList  : List<Customer>
{
    public void Add(string name, string phoneNumber, string city, string stateOrCountry)
    {
        Add(new Customer(name, phoneNumber, city, stateOrCounter));
    }
}

次に、次の構文を使用してコレクションを初期化できます。

var customers = new CustomerList
{
    {"Scott Wisniewski", "555-555-5555", "Seattle", "WA"},
    {"John Doe", "555-555-1234", "Los Angeles", "CA"},
    {"Michael Scott", "555-555-8769", "Scranton PA"},
    {"Ali G", "", "Staines", "UK"}
}

これには、各要素の要素タイプ名を再入力する必要がないため、入力が簡単で読みやすいという利点があります。要素タイプが長い場合や複雑な場合は、この利点が特に強くなります。

そうは言っても、これは、アプリで定義されたデータの静的コレクションが必要な場合にのみ役立ちます。コンパイラなどの一部の種類のアプリは、常にそれらを使用します。他の、典型的なデータベースアプリのように、データベースからすべてのデータをロードするため、そうではありません。

私のアドバイスは、オブジェクトの静的コレクションを定義する必要がある場合、またはコレクションインターフェイスをカプセル化する必要がある場合は、カスタムコレクションクラスを作成することです。それ以外の場合は、直接使用List<T>します。

于 2008-08-22T04:46:28.433 に答える
14

パブリックAPIでは、List <T>を使用せず、Collection<T>を使用することをお勧めします

あなたがそれから継承しているのなら、あなたは大丈夫なはずです、afaik。

于 2008-08-22T03:39:05.990 に答える
9

私はただ使うのが好きList<BusinessObject>です。タイプデフすると、コードに不要な定型文が追加されるだけです。 List<BusinessObject>は特定の型であり、単なるListオブジェクトではないため、強い型が付けられています。

さらに重要なことに、何かを宣言List<BusinessObject>すると、コードを読んでいるすべての人が、処理しているタイプを簡単に識別できるようになります。aが何であるかを検索してBusinessObjectCollection、それが単なるリストであることを覚えておく必要はありません。タイプデフを使用すると、意味をなすために全員が従わなければならない一貫した(再)命名規則が必要になります。

于 2008-08-22T03:34:18.840 に答える
4

私は2つのオプションを行ったり来たりしています:

public class BusinessObjectCollection : List<BusinessObject> {}

または、次のことを行うメソッド:

public IEnumerable<BusinessObject> GetBusinessObjects();

最初のアプローチの利点は、メソッドのシグネチャをいじることなく、基になるデータストアを変更できることです。残念ながら、前の実装からメソッドを削除するコレクションタイプから継承する場合は、コード全体でこれらの状況に対処する必要があります。

于 2008-08-22T03:31:15.150 に答える
4

List<BusinessObject>それらのリストを宣言する必要があるタイプを使用します。ただし、 のリストを返す場合は、 を返すことを検討BusinessObjectしてください。つまり、クライアントを満たす最も弱いコントラクトを返します。IEnumerable<T>IList<T>ReadOnlyCollection<T>

リストに「カスタム コードを追加」する場合は、リスト タイプの拡張メソッドをコードします。繰り返しますが、これらのメソッドを可能な限り弱いコントラクトにアタッチします。

public static int SomeCount(this IEnumerable<BusinessObject> someList)

もちろん、拡張メソッドで状態を追加することはできませんし、すべきではありません。そのため、新しいプロパティとその背後にフィールドを追加する必要がある場合は、サブクラスまたはより適切なラッパー クラスを使用してこれを格納します。

于 2009-01-27T14:28:20.337 に答える
3

その目的のために独自のコレクションを作成することはおそらく避けてください。リファクタリング中または新しい機能を追加するときに、データ構造のタイプを数回変更することはよくあることです。あなたのアプローチでは、BusinessObjectList、BusinessObjectDictionary、BusinessObjectTreeなどの別のクラスになります。

クラス名が読みやすいという理由だけで、このクラスを作成することに価値はありません。ええ、山かっこ構文はちょっと醜いですが、C ++、C#、Javaでは標準なので、それを使用するコードを書かなくても、いつもそれに遭遇するでしょう。

于 2008-08-22T03:35:09.090 に答える
2

私は通常、「付加価値」が必要な場合にのみ、独自のコレクションクラスを派生させます。たとえば、コレクション自体に「メタデータ」プロパティのタグ付けが必要な場合などです。

于 2008-08-22T03:28:35.267 に答える
2

私はあなたとまったく同じことをしますジョナサン...ただから継承しList<T>ます。あなたは両方の世界の長所を手に入れます。LoadAll()しかし、私は通常、メソッドの追加など、追加する価値がある場合にのみそれを行います。

于 2008-08-22T03:31:48.597 に答える
2

両方を使用できます。怠け者にとって - 私は生産性を意味します - List は非常に便利なクラスであり、「包括的」であり、率直に言って YANGNI メンバーでいっぱいです。List を公開メンバーとして公開することについて既にリンクされているMSDN の記事によって提唱された賢明な議論/推奨事項と相まって、私は「3 番目の」方法を好みます。

個人的には、デコレータ パターンを使用して、リストから必要なものだけを公開します。

public OrderItemCollection : IEnumerable<OrderItem> 
{
    private readonly List<OrderItem> _orderItems = new List<OrderItem>();

    void Add(OrderItem item)
    {
         _orderItems.Add(item)
    }

    //implement only the list members, which are required from your domain. 
    //ie. sum items, calculate weight etc...

    private IEnumerator<string> Enumerator() {
        return _orderItems.GetEnumerator();
    }

    public IEnumerator<string> GetEnumerator() {
        return Enumerator();
    }    
}

さらに、おそらく OrderItemCollection を IOrderItemCollection に抽象化して、将来 IOrderItemCollection の実装を交換できるようにします (コレクションなどの別の内部列挙可能オブジェクトを使用することを好むかもしれません) .

于 2009-01-27T14:07:59.253 に答える
1

私はほとんどすべてのシナリオで汎用リストを使用しています。派生コレクションの使用を検討するのは、コレクション固有のメンバーを追加する場合のみです。ただし、LINQの出現により、その必要性は少なくなりました。

于 2008-08-22T05:02:08.037 に答える
0

他の誰かが指摘したように、リストを公開しないことをお勧めします。公開すると、FxCopはうなり声を上げます。これには、次のようにリストからの継承が含まれます。

public MyTypeCollection : List<MyType>

ほとんどの場合、パブリックAPIは必要に応じてIList(またはICollectionまたはIEnumerable)を公開します。

独自のカスタムコレクションが必要な場合は、ListではなくCollectionから継承することで、FxCopを静かに保つことができます。

于 2008-09-16T18:15:57.470 に答える
0

6 of 1、6ダース

いずれにせよ、同じことです。BusinessObjectCollectionにカスタムコードを追加する理由がある場合にのみ実行します。

ロードメソッドがリストを返す必要がないので、一般的なジェネリッククラスでより多くのコードを記述して、それを正しく機能させることができます。Loadメソッドなど。

于 2008-08-22T03:33:17.253 に答える
0

実際のリストへのアクセスを保護したい場合は、自分のコレクションでそれを行う傾向があります。ビジネスオブジェクトを作成する場合、オブジェクトが追加/削除されているかどうかを知るためのフックが必要になる可能性があります。そのような意味で、BOCollectionの方が適していると思います。それが必要でない場合は、リストの方が軽量です。また、ある種のプロキシが必要な場合は、IListを使用して追加の抽象化インターフェイスを提供することを確認することをお勧めします(たとえば、偽のコレクションがデータベースからの遅延読み込みをトリガーします)

しかし...CastleActiveRecordやその他の成熟したORMフレームワークを検討してみませんか?:)

于 2008-09-18T16:11:12.743 に答える
0

ほとんどの場合、リスト方式を使用します。これは、90%の確率で必要なすべての機能を提供し、「追加」が必要な場合は、それを継承して、その余分なビットをコーディングするためです。 。

于 2008-09-18T16:13:08.933 に答える
0

これを試してください:

System.Collections.ObjectModel.Collection<BusinessObject>

CollectionBase do のような基本的なメソッドを実装する必要がなくなります

于 2008-12-27T09:45:11.740 に答える
0

独自のコレクション クラスを作成することを選択した場合は、System.Collections.ObjectModel Namespaceの型を確認する必要があります。

名前空間は、実装者がカスタム コレクションを簡単に作成できるようにするための基本クラスを定義します。

于 2008-09-18T16:05:46.453 に答える
0

私はこれを行います:

using BusinessObjectCollection = List<BusinessObject>;

これは、まったく新しいタイプではなく、エイリアスを作成するだけです。List<BusinessObject> を直接使用するよりも、コレクションを使用するコードを変更することなく、将来のある時点でコレクションの基になる構造を自由に変更できるため (同じプロパティとメソッドを提供する限り)、それを使用することをお勧めします。

于 2008-10-10T16:07:09.983 に答える
-1

これが方法です:

配列を返し、受け入れるIEnumerable<T>

=)

于 2008-09-04T03:20:19.410 に答える