IEnumerable 与 Ilist - IsNullOrEmpty 扩展方法

IEnumerable vs Ilist - IsNullOrEmpty extension method

我有一个自定义集合 IList<user> 作为用户。当我试图检查 users 是否为 null 或空时,我没有得到任何情报帮助(如 IsNullOrEmpty)所以我写了下面的扩展方法

public static bool IsNullOrEmpty<T>(this IEnumerable<T> source)
    {
        if (source.IsNullOrEmpty())
        {
            return true;
        }
        return false;
    }

令我惊讶的是,我发现 IEnumberable 有 IsNullOrEmpty()。

据我所知,IList 扩展了 ICollection,后者又扩展了 IEnumerable,如果是这样,那么 IList 应该支持 IsNullOrEmpty

不对的地方请指正

IEnumerable<T> 没有 IsNullOrEmpty 方法,它是你上面写的扩展。如果你调用它,你会得到一个 WhosebugException.

你可以这样实现:

public static bool IsNullOrEmpty<T>(this IEnumerable<T> source)
{
    return source == null || !source.Any();
}

但需要注意的是,这种方法并没有多大帮助,甚至可能会变得更糟。因为 Enumerable.Any 将 "consume" 查询。因此,如果它不是内存中的集合,则它必须调用 GetEnumerator 并开始枚举它,以便检查是否至少有一项。有时,如果对象被枚举(如 .NET <= 4 中的 File.ReadLines),该对象将被撤销,如果您稍后再次尝试使用它,将导致 ObjectDisposedException

此方法具有不良副作用的另一个示例是序列是一个过滤查询 (...Where(x => Compute(x, random.Next())))。此查询可能每次都会产生不同的结果。引用 Marc Gravell 的评论:“IEnumerable 不应被假定为可重复的”。

在 Linq-To-Sql 或 Linq-To-Entities 中,您将在每次 IsNullOrEmpty 调用时调用数据库。

正如@Marc Gravel 在评论中提到的“IEnumerable<T> 不应假定为可重复的”。假设您的源 IEnumerable 是从数据读取器创建的。你只有一次机会迭代它。如果您消耗那唯一的机会只是为了查看它是否为空,您将无法再次访问记录。也许您想为 IList 而不是 IEnumerable.

编写扩展方法(如果需要)
public static bool IsNullOrEmpty<T>(this IList<T> source)
{
    return source == null || source.Count == 0;
}