设计公共API时我们应该避免IEnumerable作为输入吗?

问题描述:

考虑下面的例子。设计公共API时我们应该避免IEnumerable作为输入吗?

假设我开发了一个将由第三方使用的库。该库有一个方法,接受IEnumerable,这很好,因为它从传递的集合的实现中抽象出来。但是,当我检索输入参数时会发生懒惰评估。

public interface IStorage<in T> 
{ 
    void Store(IEnumerable<T> values); 
} 

public class FileStorage<T> : IStorage<T> 
{ 
    public void Store(IEnumerable<T> values) 
    { 
    foreach (var value in values) { /*Evaluation of IEnumerable*/} 
    } 
} 

一些客户使用我的图书馆以下列方式:

IEnumerable<int> values; 
    try 
    { 
    values = new[] { "1", "2", "three" }.Select(int.Parse); 
    } 
    catch (Exception) 
    { 
    values = Enumerable.Empty<int>(); 
    } 

    var storage = new FileStorage<int>(); 
    storage.Store(values); 

这将导致Store方法,其中评价发生内部异常。如果我设计Store方法采取List<T>我肯定它是安全枚举集合的Ts。问题是我们应该在设计API时避免IEnumerable,或者我们是否应该在需要时允许并枚举安全上下文,因为它可能会引发异常。

就我个人而言,我看不出您的方法中引发异常的问题。
这个错误,你的API的用户应该知道它。

+0

好,不过我可能需要做一些清理工作(如关闭数据库连接),所以我想知道有什么可以抛出异常 – nan 2012-07-19 18:53:33

+1

@nan:一'using'块是处理这种情况的标准方法。正确使用它将确保任何异常都会导致您的连接关闭。 – Guvante 2012-07-19 18:56:01

+0

它不仅仅是处理它的事实,我需要恢复一些异常状态,我需要了解它们。 – nan 2012-07-19 18:58:32

是的,在库中有最抽象的接口作为参数是一种很好的做法。 您以这种方式定义这些项目的合同。

如果您只需要枚举集合,那么IEnumerable是一个非常好的选择。

如果您希望能够添加,索引等项目,IList是正确的选择。

事实上,您的客户端的代码是越野车不是你的问题。如果他们希望他们的程序能够工作,请告诉他们停止编写错误代码。你无法保护他们免受这些查询被懒惰评估的事实,他们显然不知道这一点。

这是客户的责任来处理,当你枚举集合发生了什么,以及如果他们通过你懒洋洋地评估收集,那么它是他们责任确保这种懒惰的评价不能扔(如果这些是你定义的参数)。打破这个不变是他们的问题。

作为一个方面说明,这里的问题不在于您的API采用IEnumerable。实际的问题是.Select调用。延迟评估是LINQ的一项功能,而不是IEnumerable界面的功能。

所以是的,你应该把一个IEnumerable作为参数。资源的加载和管理完全由客户控制,而不是你的。仅仅因为客户端可能会传入IEnumerable的某些实现,这可能会导致延迟报告异常,因此不会牺牲API的可维护性和灵活性。

根据Krzysztoc Cwalina和Brad Adams编写的框架设计指南

http://blogs.msdn.com/b/kcwalina/archive/2008/01/03/frameworkdesignguidelines2ndedition.aspx

它建议你做...

从252页(8.3.1)的提取

收集参数

DO用最少的专门类型的可能作为参数的类型。大多数 成员以收藏作为参数使用了IEnumerable接口

public void PrintNames(IEnumerable<string> names) { 
     foreach(string name in names) { 
      Console.WriteLine(name); 
     } } 

避免使用的ICollection或ICollection的作为参数只是为了 访问Count属性。

而是考虑了IEnumerable或IEnumerable和动态 检查对象是否实现的ICollection或ICollection的

顺便提一下它的一个伟大的书和一个值得读,现在真的很享受它。 P.S.谁写了这家伙,帮助撰写了.NET框架