我可以将此do-while循环重写为foreach循环吗?

时间:2011-08-03 17:35:42

标签: c# foreach do-while

有没有办法用foreach循环更优雅地编写这段代码? “创建新条目”逻辑阻碍了我,因为即使pendingEntries不包含任何项目,它也需要执行。

ItemDto itemToAdd; // an input parameter to the method
IEnumerator<Item> pendingEntries = existingPendingItems.GetEnumerator();
pendingEntries.MoveNext();
do // foreach entry
{
  Item entry = pendingEntries.Current;
  if (entry != null) // fold the itemToAdd into the existing entry
  {
    entry.Quantity += itemToAdd.Quantity; // amongst other things
  }
  else // create a new entry
  {
    entry = Mapper.Map<ItemDto, Item>(itemToAdd);
  }
  Save(entry);
} while (pendingEntries.MoveNext());

6 个答案:

答案 0 :(得分:4)

这应该重写。我不知道您使用的是哪种类型的集合,但Current在您的情况下未定义,因为MoveNext可能已返回false。如documentation中所述:

  

在以下任何条件下,当前未定义:   对MoveNext的最后一次调用返回false,表示结束   集合。

以下是我将如何重写它:

bool isEmpty = true;
foreach (Item entry in existingPendingItems)
{
  ProcessEntry(entry, itemToAdd);
  isEmpty = false;
}
if (isEmpty)
{
  ProcessEntry(null, itemToAdd);
}
  • ProcessEntry包含单个条目的逻辑,并且可以轻松进行单元测试。
  • 该算法已清除可读。
  • 可枚举仍然只列举一次。

答案 1 :(得分:2)

foreach (Item entry in existingPendingItems.DefaultIfEmpty())
{
    Item entryToSave;

    if (entry != null) // fold the itemToAdd into the existing entry
    {
        entry.Quantity += itemToAdd.Quantity; // amongst other things

        entryToSave = entry;
    }
    else // create a new entry
    {
        entryToSave = Mapper.Map<ItemDto, Item>(itemToAdd);
    }

    Save(entryToSave);
}

密钥是Enumerable.DefaultIfEmpty()调用 - 如果序列为空,这将返回带有default (Item)项的序列。对于引用类型,这将是null

编辑:修复neotapir提到的bug。

答案 2 :(得分:1)

就个人而言,我建议这样的事情:

ItemDto itemToAdd; // an input parameter to the method
if (existingPendingItems.Any())
{
    foreach(Item entry in existingPendingItems)
    {
        entry.Quantity += itemToAdd.Quantity    
        Save(entry);
    }
}
else
{
    entry = Mapper.Map<ItemDto, Item>(itemToAdd);
    Save(entry);
}

我认为这使得代码的意图更加清晰。

编辑:根据建议将计数更改为任何计数。还修复了添加数量逻辑

答案 3 :(得分:0)

我将其重写为更标准的while方法。你忘了IEnumerator<T>实现IDisposable,所以你应该处理它。

答案 4 :(得分:0)

foreach( Item entry in pendingEntries.Current)
{
    if( entry != null)
        entry.Quantity += itemToAdd.Quantity;
    else
       entry = Mapper.Map<ItemDto, Item>(itemToAdd);
    Save(entry)
}

无法准确测试它没有项目

答案 5 :(得分:0)

var pendingEntries = existingPendingItems.Any()
    ? existingPendingItems
    : new List<Item> { Mapper.Map<ItemDto, Item>(itemToAdd) };

foreach (var entry in pendingEntries)
{
    entry.Quantity += itemToAdd.Quantity; // amongst other things
    Save(entry);
}

这里的想法是你在迭代之前为自己做好准备。你要迭代什么?现有条目(如果有),或者只是新条目。

通过预先处理这个问题,所以你知道你有一些可以工作的东西,你的循环保持非常干净。