2013-03-05 84 views
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可以用於此?
如果不是我想要構建什麼樣的數據結構?

回答

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. 
    } 
} 
4

除非你有特殊原因,創建三個包含的集合中的對象的克隆,(如果你使用泛型的預.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中)。這是可能或不可接受的行爲變化。

+0

除非有特殊原因需要刪除重複項,否則'Concat'可以降低速度和內存佔用量。 – Servy 2013-03-05 17:39:58

+0

@Servy:好點。我在過去幾天一直在廣泛使用'HashSet ',並且在他們的腦海中跳舞:-)更新。 – 2013-03-05 17:40:54

+0

+1使用Union而不是'Concat'的好處:如果對象在某個集合中被複制,而Union會產生正確的結果。 – 2013-03-05 17:41:06

2

可能的方法 - 將「all」暴露爲IEnumerable<Base_type_for_items_in_other_collections>並通過連接其他集合按需創建它。即如果你有收藏的小單子基本Enumerable.Concat將工作:

public IEnumerabe<MyObject> All {get 
{ 
    return TypeOnes.Concat(TypeTwos.Concat(TypeThrees)); 
}} 
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; } 
} 
+1

沒有理由迭代你的聯盟。只需返回它。它已經是'IEnumerable '。 – 2013-03-05 17:45:52

+0

收益率回報如何?它一個一個的項目返回 – sll 2013-03-05 17:47:14

+1

你不需要自己做'收益回報'。如果你只是'返回TypeOnes.Union(TypeTwos).Union(TypeThrees)',那麼當yield'迭代'時,「yielding」將由.NET Framework內部完成。 – 2013-03-05 17:49:52

0

您真正需要的是一個ICollection接口或IEnumerable接口,涵蓋在工會所有其他收藏品,對吧?我假設一旦你加載了所有東西,你就不會將項目添加到所有集合中。如果是這樣的情況,請嘗試:

對於所有聲明:

public IEnumerable<MyBaseType> All; 

設置所有:

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

這應該讓即使它不全部反映在其他集合變化不允許你直接添加項目。

相關問題