代表多个集合的数据结构是什么?
本文关键字:数据结构 是什么 集合 | 更新日期: 2023-09-27 18:02:15
我有一个包含如下对象的现有应用程序。
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
集合中,反之亦然。
是否有一个现有的数据类型,我可以使用这个?
如果不是,我希望构建什么样的数据结构?
除非您有特定的理由创建三个包含集合中的对象的克隆,否则为什么不将All
实现为IEnumerable<T>
(或IEnumerable,如果您使用的是前泛型。net),例如:
// 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
中)。这是一种行为上的改变,可能是也可能是不可接受的。
这样怎么样?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.
}
}
可能的方法-将"all"公开为IEnumerable<Base_type_for_items_in_other_collections>
,并根据需要通过连接其他集合来创建它。例如,如果你有一个小的集合列表,基本的Enumerable。Concat可以工作:
public IEnumerabe<MyObject> All {get
{
return TypeOnes.Concat(TypeTwos.Concat(TypeThrees));
}}
您真正需要的是一个ICollection接口或IEnumerable接口,它涵盖了联合中的所有其他集合,对吗?我想在加载完所有内容后,您不会再向All集合添加项目了。如果是这种情况,请尝试:
对于All的声明:
public IEnumerable<MyBaseType> All;
设置All:
obj.All = System.Linq.Enumerable.Concat<MyBaseType>(
obj.TypeOnes, obj.TypeTwos).Concat(obj.TypeThrees);
这应该允许All反映其他集合中的更改,即使它不允许您直接向其添加项目。
由于可能有很多项目,您可以考虑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; }
}