2

私はそのようなオブジェクトを持つ既存のアプリケーションを持っています。

class MyObject{
    public MyCollection  TypeOnes;
    public MyCollection  TypeTwos;
    public MyCollection  TypeThrees;

    public MyCollection  All;
}

class MyCollection : Collection{
    public boolean IsLoaded;
}

そして、このようにロードされます。

//using bool array for flag simplicity in example
public void Load(ref MyObject obj, bool[] flags){
    if(flags[0]){
        obj.TypeOnes = LoadOnes();
        obj.TypeOnes.IsLoaded = true;
    }else{
        obj.TypeOnes = new MyCollection();
    }

    if(flags[1]){
        obj.TypeTwos = LoadTwos();
        obj.TypeTwos.IsLoaded = true;
    }else{
        obj.TypeTwos= new MyCollection();
    }

    if(flags[2]){
        obj.TypeThrees = LoadThrees();
        obj.TypeThrees.IsLoaded = true;
    } else {
        obj.TypeThrees = new MyCollection();
    }

    if(flags[3]){
        obj.All = obj.TypeOnes.Clone().AddRange(obj.TypeTwos.Clone()).AddRange(obj.TypeThrees.Clone());
        obj.All.IsLoaded = true;
    } else {
        obj.All = new MyCollection();
    }
}

明らかなように、すべてのタイプがコレクションAllとともに一度にロードされない限り、すべてのタイプを表すはずのコレクションが同期しなくなりますAll

私がやろうとしているのは、すべての型コレクションをロードする単一のフラグを作成することですが、Allすべての型コレクションに一度にアクセスするために使用するコレクションを保持し、制限するためにそれらを同期させたいと考えています。私がしなければならないリファクタリングの量。TypeOnesコレクションに変更を加えるとコレクションに反映され、Allその逆も同様になるように、読み取り/書き込み可能にしたい。

これに使用できる既存の DataType はありますか?
そうでない場合、どのようなデータ構造を構築しようとしていますか?

4

5 に答える 5

4

含まれている3つのコレクションにオブジェクトのクローンを作成する特別な理由がない限り、次のように(または、プレジェネリック.NETを使用している場合はIEnumerable)Allとして実装してみませんか。IEnumerable<T>

// Option: Preserve duplicates between collections
public IEnumerable<T> All()
{
    // Ensure child collections are loaded
    return TypeOnes.Concat(TypeTwos).Concat(TypeThrees);
}

// Option remove duplicates between collections
public IEnumerable<T> All()
{
    // Ensure child collections are loaded
    return TypeOnes.Union(TypeTwos).Union(TypeThrees);
}

これにより、含まれているコレクションに物を追加するための既存のコードコントラクトが維持され、Allそれらのコレクションが古くなったり同期しなくなったりすることがなくなります。

All古いコードコントラクトでは、初期化後に含まれているコレクションと同期しなくなったことに注意してください(子への更新はに反映されなかったためAll)。これは、許容できる場合とできない場合がある動作の変更です。

于 2013-03-05T17:37:36.677 に答える
2

このようなものはどうですか?Concatコレクションをマージし、一度にすべてを返します。

class MyObject
{
    public MyCollection  TypeOnes;
    public MyCollection  TypeTwos;
    public MyCollection  TypeThrees;

    public IEnumerable<T> All
    {
        get { return TypeOnes.Concat(TypeTwos.Concat(TypeThrees));}
        // You can use Union() to handle duplicates as well, but it's slower.
    }
}
于 2013-03-05T17:37:28.947 に答える
2

考えられるアプローチ-「すべて」を公開しIEnumerable<Base_type_for_items_in_other_collections>、他のコレクションを連結してオンデマンドで作成します。つまり、コレクションのリストが少ない場合、基本的なEnumerable.Concatは機能します。

public IEnumerabe<MyObject> All {get
{
   return TypeOnes.Concat(TypeTwos.Concat(TypeThrees));
}}
于 2013-03-05T17:37:50.447 に答える
0

本当に必要なのは、ユニオン内の他のすべてのコレクションをカバーするICollectionインターフェイスまたはIEnumerableインターフェイスだけです。すべてをロードした後は、Allコレクションにアイテムを追加しないと思います。その場合は、次を試してください。

すべての宣言について:

public IEnumerable<MyBaseType>  All;

すべてを設定するには:

obj.All = System.Linq.Enumerable.Concat<MyBaseType>(
          obj.TypeOnes, obj.TypeTwos).Concat(obj.TypeThrees);

これにより、アイテムを直接追加できない場合でも、Allが他のコレクションの変更を反映できるようになります。

于 2013-03-05T17:48:44.937 に答える
0

アイテムを返すことを検討できるアイテムがたくさんある可能性があるyield returnため、適切な制限に達した/アイテムが見つかったときに呼び出し元がアイテムへのアクセスを停止できるようにします。

public class MyObject
{
    public MyCollection  TypeOnes { get; set;} 
    public MyCollection  TypeTwos { get; set;} 
    public MyCollection  TypeThrees { get; set;} 

    public IEnumerable<string> All
    {
        get
        {
            foreach (var item in TypeOnes.Union(TypeTwos).Union(TypeThrees))
            {
                yield return item;
            }
        }
    }
}

public class MyCollection : Collection<string>
{
    public bool IsLoaded { get; set; }
}
于 2013-03-05T17:45:10.450 に答える