【问题标题】:Count users where subscription end within month Linq c#计算订阅在一个月内结束的用户 Linq c#
【发布时间】:2017-06-13 07:29:45
【问题描述】:

我只想计算订阅结束日期在下个月内的用户:

int Count = oUsers
            .Where(x =>
            0 < x.SubscriptionEnddate.Value.Subtract(DateTime.Now).Days < 30)
            .Count();

但它不起作用。

我想做的是0 。

【问题讨论】:

  • 为什么要排除 &amp;&amp; - 它是迄今为止最易读的解决方案?
  • 听起来像是 x y 问题。你真正想达到什么目标? meta.stackexchange.com/questions/66377/what-is-the-xy-problem/…
  • 我会完全重构它,预先将边界计算为局部变量,然后使用int count = oUsers.Count(x =&gt; x.SubscriptionEnddate &gt;= lowerBound &amp;&amp; x.SubscriptionEnddate &lt; upperBound);
  • 我还敦促您考虑时区。您的数据存储在哪个时区?它与您使用DateTime.Now 的机器相同吗?你确定不想要DateTime.UtcNow 或类似的吗?
  • 不带 && 运算符:!(Value &lt;= 0 || 30 &lt;= Value) 按要求解决

标签: c# .net linq


【解决方案1】:

使用&amp;&amp;。时期。这是它的设计目的。

您可以通过创建 Between 扩展方法来规避此问题,或者连接两个 Where 子句,但实际上,为什么要在 &amp;&amp; 上进行交易。但如果你坚持:

int c = oUsers
        .Select(x=> x.SubscriptionEnddate.Value.Subtract(DateTime.Now.AddDays(30)).Days)
        .Where(d => 0 < d)
        .Where(d => d < 30)
        .Count();

【讨论】:

  • @Govind:需要更多帮助吗?还有什么?
【解决方案2】:

你可以试试这样的

int count = oUsers.Where(x=> x.Days > 0).Count(x => x.Days < 30);

【讨论】:

    【解决方案3】:

    我会这样做以保持可读性:

    int Count =
        oUsers
            .Select(u => new
            {
                u,
                days = u.SubscriptionEnddate.Value.Subtract(DateTime.Now.AddDays(30)).Days,
            })
            .Where(x => x.days > 0 && x.days < 30)
            .Select(x => x.u)
            .Count();
    

    这显然使用了&amp;&amp;,但它消除了我认为您真正想要避免的代码重复。

    最后使用.Count() 消除了跟踪原始值的需要,因此,正如帕特里克已经发布的那样,这就足够了:

    int Count =
        oUsers
            .Select(u => u.SubscriptionEnddate.Value.Subtract(DateTime.Now.AddDays(30)).Days)
            .Where(x => x > 0 && x < 30)
            .Count();
    

    【讨论】:

      【解决方案4】:

      为什么不是越短越好。

      当其他人阅读您的代码时,当您调用 SomeRange 方法时,他会更容易理解

      我认为最好的原因是当代码更具可读性时,如果您的值与开始和结束范围匹配并调用它,您可以执行返回方法。

      一些 int 范围的示例,但同样可以检查日期的原因

          public static bool SomeRange(int value,int start,int end)
          {
              return (value > start && value < end);
          }
          static void Main()
          {
              List<int> valueList = new List<int> { 1,65,3,76,34,23,11,5,665,334};
              var result = valueList.Where(x => SomeRange(x, 0, 30)).Count();
          }
      

      【讨论】:

        【解决方案5】:

        是的,用 Enumerable.Range 解决它:

        oUsers.Where(x =&gt; x.SubscriptionEnddate != null &amp;&amp; Enumerable.Range(0, 30).Contains(x.SubscriptionEnddate.Value.Subtract(DateTime.Now).Days)).Count();

        【讨论】:

        • 您知道,这比比较所需范围的开始和结束效率低 30 倍。
        • 所以你建议使用 && 运算符?
        【解决方案6】:

        我会说,在执行计数之前预先计算范围开始和结束,然后比较start &amp;&amp; end

        // some test data
        var oUsers = Enumerable.Range(0, 100).Select(x => new { SubscriptionEnddate = (DateTime?)DateTime.Now.AddDays(x) });
        
        var rangeStart = DateTime.Now;
        var rangeEnd = rangeStart.AddDays(30);
        // Conditional count... can also be done as .Where(condition).Count()
        int Count = oUsers.Count(x => x.SubscriptionEnddate >= rangeStart && x.SubscriptionEnddate < rangeEnd);
        

        可能改用DateTime.Today,因为您只对天数感兴趣。

        【讨论】:

          【解决方案7】:

          如果你真的反对使用&amp;&amp;,你可以使用嵌套的 if 语句

          if x.SubscriptionEnddate.Value.Subtract(DateTime.Now.AddDays(30)).Days > 0 {
            if x.SubscriptionEnddate.Value.Subtract(DateTime.Now.AddDays(30)).Days < 30 {
              int count = oUsers;
            }
          
          }
          

          不过,这似乎是一种非常迟钝的方法。这就是我们有&amp;&amp; 运算符的原因。

          【讨论】:

          • 或者你可以不投我一票,因为这不是你想听到的?我猜真相很伤人。
          • if 语句在 linq 查询的 Where 部分中不起作用。
          • 确实如此,但您必须将它们包装在代码块中@JamesThorpe
          • @PatrickHofman 是的。比只使用&amp;&amp; 还要糟糕:)
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-06-05
          • 2012-06-06
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多