c# - Resharper 转换 LINQ 错误?还是我的代码错了

标签 c# linq resharper

我有这个方法

 public static Status BiggestOverdue(List<StatusOverdueMinutes> overdueMinutes, DateTime lastReceived, int receiveTimeSpanMinutes)
 {
     var maxMinutesOverdueFound = 0;
     var status = Status.Ok;

     if (lastReceived.AddMinutes(receiveTimeSpanMinutes) >= DateTime.Now || 
         receiveTimeSpanMinutes == -1)
                return Status.Ok;

     foreach (var overdueStatus in overdueMinutes.Where(overdueStatus => 
              lastReceived.AddMinutes(receiveTimeSpanMinutes + 
              overdueStatus.OverdueMinutes) < DateTime.Now))
        if (overdueStatus.OverdueMinutes > maxMinutesOverdueFound)
        {
            maxMinutesOverdueFound = overdueStatus.OverdueMinutes;
            status = overdueStatus.StatusId;
        }

    return status;
}

状态枚举

public enum Status
{
    Error = 0,
    Warning = 1,
    Information = 2,
    Ok = 3,
    NeedsConfig = 4,
    Maintenance = 5,
    Disabled = 6,
    Enabled = 7
}

我有单元测试支持它按我预期的方式工作(即它从列表中返回最晚的状态)

public void ShouldReturnError()
{
    var lastReceived = DateTime.Now.AddMinutes(-30);
    var overdueMinutes = new List<StatusOverdueMinutes>
    {
        new StatusOverdueMinutes {OverdueMinutes = 10, StatusId = Status.Error},
        new StatusOverdueMinutes {OverdueMinutes = 7, StatusId = Status.Warning},
        new StatusOverdueMinutes {OverdueMinutes = 5, StatusId = Status.Information}
    };
    const int receiveTimeSpan = 15;
    var status = CacheHelper.BiggestOverdue(overdueMinutes, lastReceived, receiveTimeSpan);
    Assert.AreEqual(Status.Error, status);
}
[TestMethod]
public void ShouldReturnWarning()
{
    var lastReceived = DateTime.Now.AddMinutes(-30);
    var overdueMinutes = new List<StatusOverdueMinutes>
                         {
                             new StatusOverdueMinutes {OverdueMinutes = 20, StatusId = Status.Error},
                             new StatusOverdueMinutes {OverdueMinutes = 7, StatusId = Status.Warning},
                             new StatusOverdueMinutes {OverdueMinutes = 5, StatusId = Status.Information}
                         };
    const int receiveTimeSpan = 15;
    var status = CacheHelper.BiggestOverdue(overdueMinutes, lastReceived, receiveTimeSpan);
    Assert.AreEqual(Status.Warning, status);
}
[TestMethod]
public void ShouldReturnInformation()
{
    var lastReceived = DateTime.Now.AddMinutes(-30);
    var overdueMinutes = new List<StatusOverdueMinutes>
                         {
                             new StatusOverdueMinutes {OverdueMinutes = 30, StatusId = Status.Error},
                             new StatusOverdueMinutes {OverdueMinutes = 27, StatusId = Status.Warning},
                             new StatusOverdueMinutes {OverdueMinutes = 10, StatusId = Status.Information}
                         };
    const int receiveTimeSpan = 15;
    var status = CacheHelper.BiggestOverdue(overdueMinutes, lastReceived, receiveTimeSpan);
    Assert.AreEqual(Status.Information, status);
}
[TestMethod]
public void ShouldReturnOk()
{
    var lastReceived = DateTime.Now.AddMinutes(-10);
    var overdueMinutes = new List<StatusOverdueMinutes>
                         {
                             new StatusOverdueMinutes {OverdueMinutes = 20, StatusId = Status.Error},
                             new StatusOverdueMinutes {OverdueMinutes = 15, StatusId = Status.Warning},
                         };
    const int receiveTimeSpan = 15;
    var status = CacheHelper.BiggestOverdue(overdueMinutes, lastReceived, receiveTimeSpan);
    Assert.AreEqual(Status.Ok, status);
}

Resharper 建议可以将循环体的一部分转换为 linq。这就是它的建议:

        foreach (var overdueStatus in overdueMinutes.Where(overdueStatus => lastReceived.AddMinutes(receiveTimeSpanMinutes + overdueStatus.OverdueMinutes) < DateTime.Now)
                                                    .Where(overdueStatus => overdueStatus.OverdueMinutes > maxMinutesOverdueFound))
        {
            maxMinutesOverdueFound = overdueStatus.OverdueMinutes;
            status = overdueStatus.StatusId;
        }

结果它说这一行:

maxMinutesOverdueFound = overdueStatus.OverdueMinutes;

分配的值不在任何执行路径中使用,可以将其删除。所以我删除它。这使我的循环体变成了这样:

foreach (var overdueStatus in overdueMinutes.Where(overdueStatus => lastReceived.AddMinutes(receiveTimeSpanMinutes + overdueStatus.OverdueMinutes) < DateTime.Now)
                                  .Where(overdueStatus => overdueStatus.OverdueMinutes > maxMinutesOverdueFound))
            {
                status = overdueStatus.StatusId;
            }

现在我的测试失败了。这是resharper中的错误吗?或者我在这里做了一些完全愚蠢的事情。

最佳答案

是的,resharper 没有理解您的代码并提出错误建议。您需要 maxMinutesOverdueFound 来找到最大值,并在 if 中连续更新此值:

if (overdueStatus.OverdueMinutes > maxMinutesOverdueFound)
{
    maxMinutesOverdueFound = overdueStatus.OverdueMinutes;
    status = overdueStatus.StatusId;
}

如果 resharper 现在尝试删除这个 if 并且只与它不正确的初始值进行比较。

因此,即使您更新 foreach 中的值,LINQ 转换 resharper 建议也是不正确的,因为 Where 仅按初始值过滤。

但是您可以将整个查询简化为这样,不需要 foreach 或跟踪变量:

StatusOverdueMinutes maxOverdueStatus = overdueMinutes
    .Where(odm => lastReceived.AddMinutes(receiveTimeSpanMinutes + odm.OverdueMinutes) < DateTime.Now)
    .OrderByDescending(odm => odm.OverdueMinutes)
    .FirstOrDefault();
if (maxOverdueStatus == null) return Status.Ok;
return maxOverdueStatus.StatusId;

关于c# - Resharper 转换 LINQ 错误?还是我的代码错了,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45669597/

相关文章:

c# - Linq 和 Streamreader 获取行

c# - 如何在多个实体数据模型之间共享连接字符串

c# - Windows Azure 中的数据库连接

c# - 我在哪里可以找到在 C# 中为本地 HTTPs 服务器生成的证书

c# - 发送包含相同附件的多封电子邮件

c# - 泛型参数什么时候不能为 null

visual-studio-2010 - Visual Studio 2010 在命名空间内插入 using 指令

c# - 什么是后置条件异常?

c# - 查询EF上的虚拟列表属性

c# - N单元+ReSharper : How to view results for TestFixture with different parameters?