我会退后一步。您将注意力集中在代码的挑剔细节上,但却错过了大图。让我们看一下您的示例循环之一:
int offset = 0;
while(true)
{
Record r = Read(offset);
if(r == null)
{
break;
}
// do work
offset++;
}
该代码的含义是什么?含义是“对文件中的每个记录做一些工作”。但这不是代码的样子。该代码看起来像“保持偏移量。打开文件。输入没有结束条件的循环。读取记录。测试是否为空。” 在我们开始工作之前,所有这些!您应该问的问题是“ 如何使此代码的外观与其语义相匹配? ”此代码应为:
foreach(Record record in RecordsFromFile())
DoWork(record);
现在,代码读起来像它的意图一样。 将机制与语义分开。在原始代码中,您将机制-循环的详细信息-以及语义-混合了对每条记录所做的工作。
现在我们必须执行RecordsFromFile()
。最好的实现方法是什么? 谁在乎?那不是任何人都会看的代码。它是基本的机制代码,有十行。随便写。这个怎么样?
public IEnumerable<Record> RecordsFromFile()
{
int offset = 0;
while(true)
{
Record record = Read(offset);
if (record == null) yield break;
yield return record;
offset += 1;
}
}
现在,我们正在处理懒散计算的记录序列,各种情况都成为可能:
foreach(Record record in RecordsFromFile().Take(10))
DoWork(record);
foreach(Record record in RecordsFromFile().OrderBy(r=>r.LastName))
DoWork(record);
foreach(Record record in RecordsFromFile().Where(r=>r.City == "London")
DoWork(record);
等等。
每当您编写一个循环时,都要问自己“这个循环是像机制还是代码的含义?” 如果答案是“像一种机制”,则尝试将该机制移至其自己的方法,并编写代码以使含义更明显。