1

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

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

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

据我所知,再延伸IList,如果是这样的话应该支持。ICollectionIEnumerableIListIsNullOrEmpty

请纠正我错的地方。

4

2 回答 2

4

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

您可以通过以下方式实现它:

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

但重要的是要注意,这种方法不是很有帮助,甚至可能会变得更糟。因为Enumerable.Any会“消耗”查询。因此,如果它不是内存中的集合,它必须调用GetEnumerator并开始枚举它,以便检查是否至少有一个项目。有时,如果对象被枚举(例如在 .NET <= 4 中),对象将被丢弃,如果您稍后再次尝试使用它,File.ReadLines这将导致。ObjectDisposedException

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

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

于 2015-02-02T11:23:24.210 回答
0

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

public static bool IsNullOrEmpty<T>(this IList<T> source)
{
    return source == null || source.Count == 0;
}
于 2015-02-02T11:55:43.733 回答