Resharper从foreach中移除了产量。为什么?

时间:2014-08-26 20:37:29

标签: c# resharper yield-return

我最近了解了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错误/建议。

任何见解都会很棒。

3 个答案:

答案 0 :(得分:3)

这是正确的,这个提议的转换以微妙的方式改变了代码的功能,阻止它推迟对属性的评估并且尽早执行Split

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

答案 1 :(得分:1)

我认为Resharper在这里有点愚蠢,因为它应用了标准&#34;将foreach转换为LINQ&#34;转换而不了解上下文。

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

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

我想使用Roslyn的Resharper的下一次迭代会更多地了解情境。

感谢@servy进行了精彩的讨论!

答案 2 :(得分:-2)

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

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