【问题标题】:IEnumerable vs Ilist - IsNullOrEmpty extension methodIEnumerable vs Ilist - IsNullOrEmpty 扩展方法
【发布时间】:2015-04-01 07:56:01
【问题描述】:

我有一个自定义集合IList<user>作为用户。当我尝试检查users是否为空或为空时,我没有得到任何智能帮助(如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&lt;T&gt; 没有IsNullOrEmpty 方法,它是您在上面编写的扩展;)如果您调用它,您将得到一个StackOverflowException
  • @TimSchmelter :D 谢谢
  • 附注:IEnumerable&lt;T&gt; 不应该被认为是可重复的;测试一个序列是否为空的唯一方法是开始迭代它:如果你开始迭代它,它可能会死、完成、消失、完成,再也见不到了
  • @MarcGravell 你能解释一下可重复的意思吗?
  • @Tech repatable === 你可以多次查询数据(得到同样的结果);如果该数据是网络套接字上的开放流,例如:您只能读取一次 - 一旦您读取它:它已经消失了。另一个简单的例子是:我可以写一个IEnumerable&lt;T&gt;,它产生基于加密种子的随机数:完全不可重复。

标签: c# extension-methods ienumerable ilist isnullorempty


【解决方案1】:

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

你可以这样实现它:

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

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

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

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

【讨论】:

    【解决方案2】:

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

    public static bool IsNullOrEmpty<T>(this IList<T> source)
    {
        return source == null || source.Count == 0;
    }
    

    【讨论】:

    • 我希望 C# 和 VB.NET 有“foreach”结构,可以接受枚举器模式的东西,而不是只能接受 GetEnumerator 方法的东西。只能读取一次的东西应该是枚举器而不是枚举器。由于语言无法与前者合作,他们不得不假装是后者。
    猜你喜欢
    • 1970-01-01
    • 2011-01-01
    • 2013-06-24
    • 2019-03-17
    • 2011-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-23
    相关资源
    最近更新 更多