Resharper从foreach移除收益.为什么?

本文关键字:收益 为什么 foreach Resharper | 更新日期: 2023-09-27 18:19:40

我最近了解了yield,然后创建了以下测试控制台程序:

    public static string Customers = "Paul,Fred,Doug,Mark,Josh";
    public static string Admins = "Paul,Doug,Mark";
    public static void Main()
    {
        var test = CreateEfficientObject();
        Console.WriteLine(test.Admins.FirstOrDefault());
        //Note that 'GetAllCustomers' never runs. 
    }
    public static IEnumerable<string> GetAllCustomers()
    {
        var databaseFetch = Customers.Split(',');
        foreach (var s in databaseFetch)
        {
            yield return s;
        }
    }
    public static IEnumerable<string> GetAllAdmins()
    {
        var databaseFetch = Admins.Split(',');
        foreach (var s in databaseFetch)
        {
            yield return s;
        }
    }
    static LoginEntitys CreateEfficientObject()
    {
        var returnObject = new LoginEntitys {};
        returnObject.Admins = GetAllAdmins();
        returnObject.Customers = GetAllCustomers();
        return returnObject;
    }
}
public class LoginEntitys
{
    public IEnumerable<String> Admins { get; set; }
    public IEnumerable<String> Customers { get; set; }
}

然而,我注意到Resharper想要将我的foreach循环转换为:

public static IEnumerable<string> GetAllCustomers()
{
    var databaseFetch = Customers.Split(',');
    return databaseFetch;
}

为什么Resharper想要从这个案例中删除收益?它完全改变了功能,因为它将不再无收益地延迟加载。我只能猜测

  • A) 我使用yield不正确/操作不当
  • B) 这是一个可以忽略的Resharper错误/建议

任何见解都会很棒。

Resharper从foreach移除收益.为什么?

您是正确的,这个提议的转换以微妙的方式更改了代码的功能,防止了它推迟对属性的评估,并阻止了Split的早期评估。

也许那些实现它的人很清楚这是一个功能上的改变,并认为这仍然是一个有用的建议,如果现有的语义很重要,或者他们实际上没有意识到语义正在被改变,那么这个建议可以被忽略。没有什么好办法让我们知道,我们只能猜测。如果这些语义对您的程序很重要,那么您不进行建议的转换是正确的。

我认为Resharper在这里有点愚蠢,因为它在不了解上下文的情况下应用了标准的"将foreach转换为LINQ"转换。

它不建议对while循环进行相同的编辑:

public static IEnumerable<string> ReadLineFromFile(TextReader fileReader)
{
    using (fileReader)
    {
        string currentLine;
        while ((currentLine = fileReader.ReadLine()) != null)
        {
            yield return currentLine;
        }
    }
}

我想使用Roslyn的Resharper的下一次迭代将更加注重上下文。

感谢@servy的精彩讨论!

示例中的代码没有在返回的IEnumerable上调用迭代器。例如,如果在LINQ查询中使用GetAllAdmins()的结果,yield将非常有用,因为表达式的执行可以在每次迭代中恢复。

我想Resharper只是建议您删除未使用的代码。