【问题标题】:Determine sequence contains no element using LINQ [duplicate]使用 LINQ 确定序列不包含任何元素 [重复]
【发布时间】:2012-08-09 13:08:28
【问题描述】:

可能重复:
LINQ: Max or Default?

我有一些 LINQ 来过滤 DateTime 变量。

List<DateTime> lst1 = new List<DateTime>();

 //.... add DataTime here

var d = lst1.Where(q => q <= DateTime.Now).Max();

如果我没有匹配的项目,则会发生异常。

我需要清空d 或至少null,我这里根本不需要例外。

我该如何解决?

谢谢!

【问题讨论】:

标签: c# .net linq


【解决方案1】:

试试

var d = lst1.Where(q => q <= DateTime.Now).DefaultIfEmpty().Max();

如果没有匹配项,您的结果现在将包含 DateTime.MinValue

【讨论】:

  • podiluska,您可能想向 OP 解释为什么您的解决方案现在显示 lst1 的日期值,您的解决方案是完美的,但我不确定他是否会理解原因。
  • 请注意,如果您想要一个属性的最大值关闭 lst1,您需要考虑 null。例如:var maxHeight = lst1.Where(q =&gt; q &lt;= DateTime.Now).DefaultIfEmpty().Max(q =&gt; q?.height ?? 0);
  • 万一有人为 UWP 应用程序执行此操作,如果您尝试在启用 .NET Native 工具链的发布模式下构建应用程序,您将收到关于“多重继承”的非常奇怪的错误.这是由于使用了“DefaultIfEmpty()”,所以我建议只编写一个自定义扩展方法来检查从 Where 返回的内容是否为空或空,如果是,则返回您想要的内容,否则继续使用 agg 函数您想使用 (.Max, .Average) 等。
【解决方案2】:
如果源没有任何元素,

Max() 会抛出 ArgumentNullException。您可以编写一个扩展方法来检查这一点,如果没有任何元素,则返回 null(或任何您想要的)。

public static Nullable<DateTime> MaxOrNull(this IEnumerable<DateTime> source)
{
    if (source.Count() == 0)
        return null;
    else
        return source.Max();
}

【讨论】:

  • 我会使用if (source.Any() == false) 而不是if (source.Count() == 0)。列表是否为空无需计数。
  • 这样会更有效率,因为它会在找到第一个元素时返回 true。返回 source.Any() ? source.Max() : null;
【解决方案3】:

我喜欢:

var d = lst1.Where(q => q <= DateTime.Now).OrderByDescending(q => q.DateField).FirstOrDefault();

如果列表为空,这将返回 null。

【讨论】:

  • 令 N 是 lst1 的长度,那么 Max 需要正好 N 比较,OrderBy 需要 Nlog(N) 在最好的情况下最好的实现,NN/2 in最坏的。或者当然,如果 N 很小,但 N ~1000 会产生很大的不同。
猜你喜欢
  • 2016-12-06
  • 1970-01-01
  • 2012-10-29
  • 1970-01-01
  • 2011-09-01
  • 2012-04-12
  • 1970-01-01
  • 1970-01-01
  • 2015-09-04
相关资源
最近更新 更多