IEnumerable 与 Ilist - IsNullOrEmpty 扩展方法

问题描述 投票:0回答:2

作为用户,我有一个自定义集合

IList<user>
。当我尝试检查
users
是否为空或为空时,我没有得到任何智能帮助(如
IsNullOrEmpty
),所以我编写了以下扩展方法

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

        return false;
}

令我惊讶的是,我发现

IEnumerable<T>
IsNullOrEmpty()

据我所知,

IList
延伸了
ICollection
,又延伸了
IEnumerable
,如果是这样的话,那么
IList
应该支持
IsNullOrEmpty

有错误的地方请指正。

c# list extension-methods ienumerable isnullorempty
2个回答
4
投票

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

你可以这样实现:

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

但需要注意的是,这种方法的帮助并不大,甚至会变得更糟。因为

Enumerable.Any
会“消耗”查询。因此,如果它不是内存中的集合,则必须调用
GetEnumerator
并开始枚举它,以便检查是否至少有一项。有时,如果对象被枚举,该对象将被释放(例如 .NET 中的
File.ReadLines
<= 4) which willl cause an
ObjectDisposedException
,如果您稍后尝试再次使用它)。

此方法具有不需要的副作用的另一个示例是当序列是过滤的查询时(

...Where(x => Compute(x, random.Next()))
)。此查询每次可能会产生不同的结果。引用 Marc Gravell 的评论:“IEnumerable 不应被假定为可重复的”。

在 Linq-To-Sql 或 Linq-To-Entities 中,您将在每次

IsNullOrEmpty
调用时调用数据库。


0
投票

正如@Marc Gravel 在评论中提到的“

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

public static bool IsNullOrEmpty<T>(this IList<T> source)
{
    return source == null || source.Count == 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.