我最近了解了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想要从这种情况中移除收益?它完全改变了功能,因为它不会在没有产量的情况下延迟加载。我只能猜测
yield
任何见解都会很棒。
答案 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只是建议您删除未使用的代码。