12

公开自定义集合与通用集合的框架设计指南是什么?例如

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

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

VS

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

6 回答 6

13

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

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

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

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

如果它只是用于内部使用的代码,那么这个决定并不一定那么重要,你可能会决定“越简单越好”。

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

于 2009-10-09T16:28:39.493 回答
9

通常,最好公开其中一个接口,例如IEnumerable<T>ICollection<T>或者IList<T>代替具体的类。

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

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

于 2009-10-09T16:44:58.263 回答
5

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

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

于 2009-10-09T16:26:15.693 回答
5

我能想到的主要原因是您可能希望有一些特定于图像集合的方法,这些方法可以在该集合本身上运行。然后我会使用 ImageCollection 类来包含这些方法。经典封装。

另外,顺便说一句,您实际上应该只为该集合公开一个 getter,并使用实际集合初始化一个只读支持字段。您可能希望人们向集合中添加/删除项目,而不是替换整个项目:

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

-Oisin

于 2009-10-09T16:29:16.843 回答
1

使用的唯一原因Collection<T>是,如果您想挂接到一组虚拟方法中,它允许您查看底层列表的所有突变。这允许您执行诸如响应删除、实现事件等操作...

如果您对响应或观看这些集合修改不感兴趣,那么 aList<T>是更合适的类型。

于 2009-10-09T16:27:48.557 回答
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; }
   }
}

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

于 2009-10-09T16:46:27.413 回答