在foreach中多次使用对象

本文关键字:对象 foreach | 更新日期: 2023-09-27 18:15:56

我使用foreach循环为每个对象执行特定任务。问题是,这有时会失败,然后需要再次执行,以此类推。有没有可能再次对同一对象执行相同的任务?

稍微形象化一下这个问题:

foreach (Foo obj in FooList)
{
     obj.DoSomething();
     obj.CheckIfSucceded();
}

现在,如果CheckIfSucceded()返回false,我希望在循环中再次使用相同的对象,而不是继续使用下一个对象。

在foreach中多次使用对象

这个怎么样:

foreach (Foo obj in FooList)
{
    do 
    {
         obj.DoSomething();
    } while (!obj.CheckIfSucceded())
}

这是一个做while循环的完美用例。

假设你很乐意永远在同一个对象上重复尝试操作,你可以做这样的事情:

foreach (Foo obj in FooList)
{
    do
    {
        obj.DoSomething();
    } while (!obj.CheckIfSucceded())
}

如果你只想尝试一定次数,你可以添加一个简单的超时:

foreach (Foo obj in FooList)
{
    int tries = 0;
    do
    {
        obj.DoSomething();
        tries++;
    } while (!obj.CheckIfSucceded() && tries < 5)
}

或者,如果你更喜欢使用while而不是do while,你可以这样做:

foreach (Foo obj in FooList)
{
    int tries = 0;
    bool succeeded = false;
    while (!succeeded && tries < 5)
    {
        obj.DoSomething();
        succeeded = obj.CheckIfSucceded();
        tries++;
    }
}
int failCount = 0;
int maxFailCount = 10;
foreach (Foo obj in FooList)
{
     failCount = 0;
     obj.DoSomething();
     bool succeeded = obj.CheckIfSucceded();
     while(!succeeded && ++failCount <= maxFailCount)
     {
         obj.DoSomething();
         succeeded = obj.CheckIfSucceded();
     }
}

这里有一种更为"复杂"的方法,可以处理每次运行的最大失败次数,以及可以禁用的总失败次数:

int maxFailCount = 10;          
int maxTotalFailCount = 100;
bool checkFailCount = maxFailCount > 0;
bool checkTotalFailCount = maxTotalFailCount > 0;
int totalFailCount = 0;
foreach (Foo obj in FooList)
{
    int failCount = 0;
    bool breakLoop = false;
    bool retry = true;
    while (retry)
    {
        obj.DoSomething();
        bool succeeded = obj.CheckIfSucceded();
        if (!succeeded)
        {
            if (checkTotalFailCount && ++totalFailCount > maxTotalFailCount)
            {
                breakLoop = true;
                retry = false;
            }
            else if (checkFailCount && ++failCount > maxFailCount)
            {
                retry = false;   
            }
        }
    }
    if (breakLoop)
        break;
}

其他想法是"实现自己的foreach":

        var enumerator = FooList.GetEnumerator();
        enumerator.MoveNext();
        while (enumerator.Current != null)
        {
            enumerator.Current.DoSomething();
            if(!enumerator.Current.CheckIfSucceded()) continue;
            enumerator.MoveNext();
        }

通过这种方式,您可以只使用一个while循环,并控制何时移动到该循环中的下一个对象(这在常规foreach循环中是不可能的(。。。