2011-12-03 50 views
4

就我个人而言,我是C#中IEnumerable/List扩展方法的流畅接口语法的粉丝,作为客户端。也就是说,我更喜欢这样的语法:IEnumerable扩展与无投保证书

public void AddTheseGuysToSomeLocal(IEnumerable<int> values) 
    { 
     values.ToList().ForEach(v => _someLocal += v); 
    } 

而不是像foreach循环那样的控制结构。我发现,一目了然,轻松处理思想。与此问题是,如果客户端传递给我一个空参数,这里我的代码将生成空引用异常。

让我们假设我不想考虑一个空枚举是例外 - 我希望这导致留下一些本地的 - 我会添加一个空警戒。但是,这对我的口味来说有点句法上的嘈杂,如果你将它们连接在一个流畅的界面中,并且中间结果也可以为空,那么噪音就会增加。

因此,我创建了一个名为SafeEnumerableExtensions的类,通过将空值视为空枚举(列表)来提供了一个无投诉保证。示例方法包括:

//null.ToList() returns empty list 
    public static List<T> SafeToList<T>(this IEnumerable<T> source) 
    { 
     return (source ?? new List<T>()).ToList(); 
    } 

    //x.SafeForEach(y) is a no-op for null x or null y 
    //This is a shortcut that should probably go in a class called SafeListExtensions later 
    public static void SafeForEach<T>(this List<T> source, Action<T> action) 
    { 
     var myAction = action ?? new Action<T>(t => { }); 
     var mySource = source ?? new List<T>(); 
     mySource.ForEach(myAction); 
    } 

    public static void SafeForEach<T>(this IEnumerable<T> source, Action<T> action) 
    { 
     SafeToList(source).SafeForEach(action);    
    } 

现在,我原来的方法是漂亮比,如果有一个空卫,但只是作为安全的,因为空结果在无操作:

public void AddTheseGuysToSomeLocal(IEnumerable<int> values) 
    { 
     values.ForEach(v => _someLocal += v); 
    } 

所以,我的问题是双重的。 (1)我假设我并非如此原始,以至成为有史以来第一个想到这一点的人 - 有谁知道是否有现成的图书馆可以做到这一点或类似的东西? (2)有没有人使用过这样的图书馆,或者实施了这样的方案,并且经历了不愉快的后果,否则任何人都可以预见到做这样的事情会产生不愉快的后果?这是个好主意吗?

(我发现this question的重复检查的时候,但我不希望明确做这种检查在客户 - 我想扩展类隐式地做到这一点,而不是用额外的方法调用打扰客户端)

+0

我打算给你一个非常非常长的序列。你会遍历整个序列,所以你可以使用一个方法而不是标准循环?然后*然后*您将再次遍历整个序列以完成实际工作? –

+0

@AnthonyPegram我认为他只是在谈论检查你通过*的列表引用是否为null *而不是引用的列表*是否包含空值* – phoog

+1

@phoog,你没有传递一个列表。你正在传递一个IEnumerable。他调用了ToList,它遍历整个序列,简单地说,他可以使用一种方法,它不仅仅是普通的旧循环,而且(当然)他会再次运行序列(在方法中)。关于空值检查,我从我的评论中删除了这部分内容,但不管怎样,我很清楚他正在谈论序列参考。 –

回答

7

(2)有没有人使用过这样的库或者实现了像这样的方案 ,并且遇到了不愉快的后果,或者任何人都可以预见到 会产生不愉快的后果吗?这是甚至 好主意?

我个人认为这是一个坏主意。在大多数情况下,传递null枚举或null Func可能不是意图。

您正在“修复”可能导致看似无关问题的问题。相反,我宁愿在这种情况下抛出异常,以便在代码早期("Fail fast")中发现此问题。

+0

这是一个很好的观点。在我发布的具体示例方法中,将null传递给该方法没有任何意义。但是,我想知道是否有更多微妙的例子,其中快速失败的概念并不明确。 –

+0

我打算接受这个答案,因为它似乎是我在考虑这种做法时应该考虑的主要问题 - 我是否帮助客户掩盖了问题。感谢您的输入。 –