公共方法的自定义集合与通用集合

时间:2009-10-09 16:25:05

标签: c# .net collections api-design

用于公开自定义集合与通用集合的框架设计指南是什么? e.g

public class ImageCollection : Collection<Image>
{
     ...
}

public class Product
{
   public ImageCollection {get; set;}
}

VS

public class Product
{
   public Collection<Image> Images{get; set;}
}

6 个答案:

答案 0 :(得分:13)

如果您正在构建公共API,请考虑使用自定义集合以获得以下优势。

  • 可扩展性 - 您可以在以后向自定义集合中添加功能,而无需更改API。

  • 向后兼容性 - 您可以随意更改集合类的内部,而不会破坏客户端针对集合编程的现有代码。

  • 以较小的影响进行潜在的破坏变更也更容易。也许以后您决定不希望它是Collection<Image>,而是一个不同的集合类型 - 您可以定制您的ImageCollection类,使其具有与以前相同的方法,但继承自不同的东西 - 和客户端代码不太可能破解。

如果它仅用于内部使用代码,则决定不一定重要,您可以选择“更简单更好”。

我最喜欢的一个例子是来自ESRI的ArcGIS Server API - 他们在API中使用自定义集合。我们也在API中使用自定义集合,主要是出于这些原因。

答案 1 :(得分:9)

通常,最好公开其中一个接口,例如IEnumerable<T>ICollection<T>IList<T>,而不是具体的类。

这为您在更改内部API方面提供了更大的灵活性。特别是IEnumerable<T>允许您稍后修改内部结构以允许结果流式传输,因此最灵活。

如果您知道“集合”的预期使用模式,则应该公开适当的API,以便将来对您提供最少的约束。例如,如果您知道人们只需要迭代您的结果,那么就公开IEnumerable<T>,这样您就可以在以后更改为ANY集合,甚至可以直接切换到仅使用yield return。

答案 2 :(得分:5)

我会选择第二个。无论如何,客户端代码必须知道Image类型。

第一个只意味着更多的代码。

答案 3 :(得分:5)

我能想到的主要原因是你可能想要一些特定于对该集合本身进行操作的图像集合的方法。然后我将使用ImageCollection类来包含这些方法。经典封装。

另外,除此之外,您应该只为该集合公开一个getter,并使用实际集合初始化一个只读的后备字段。您可能希望人们在集合中添加/删除项目,而不是替换整个项目:

class Product {
    private readonly Collection<Image> _images;
    public Product() { _images = new Collection<Image>(); }
    public Collection<Image> Images { get { return _images; } }
}

-Oisin

答案 4 :(得分:1)

使用Collection<T>的唯一原因是,如果要挂入虚拟方法集,可以查看基础列表中的所有突变。这允许您执行诸如响应删除,实现事件等操作...

如果您对回复或观看这些收藏修改不感兴趣,那么List<T>是更合适的类型。

答案 5 :(得分:1)

我更喜欢使用公共通用属性来使内部可扩展,但私有字段将是具有实际功能的自定义字段。

通常看起来像这样:

public interface IProduct
{
     ICollection<Image> Images { get; }
}

public class Product : IProduct
{
   private class ImageCollection : Collection<Image>
   {
      // override InsertItem, RemoveItem, etc.
   }

   private readonly ImageCollection _images;
   public ICollection<Image> Images
   {
      get { return _images; }
   }
}

我还经常将自定义集合类嵌套在另一个类中,这允许我在添加/删除期间修改父类的一些私有成员。

相关问题