我可以在c#中执行类似foreach while循环(我将如何引用它)的内容吗?

问题描述 投票:-3回答:3

我已经研究了一些,我找不到一个很好的方法来做到这一点。我有功能代码,但我想清理它而不使用手动计数或中断。我查看了LINQs TakeWhile函数,但在这种情况下这还不够。以下是功能等效的工作实现示例:

bool foo(List<strings> stringList, int counter)//assume this list has, like, 10 elements, and counter=3, idk
{
    ...

    bool found= false;
    for(int i=0; i<stringList.Count && !found; i++)
    {
        if(stringlist[i].length < 2 || counter >=6)
            found=true;
        counter++;
    }

    ...

    return found
}

我想用一些像这样的“魔术”函数替换它:

bool foo(List<strings> stringList, int counter)//assume this list has, like, 10 elements, and counter=3, idk
{
    ...

    bool found= false;
    foreachwhile(string s in stringList while !found)
    {
        if(s.length < 2 || counter >=6)
            found=true;
        counter++;
    }

    ...

    return found
}

是否有一些功能可以做到这一点,如果没有,我怎么能用C#写一个...或者接近?我经常发现我需要这样做,是的,我知道:

bool foo(List<strings> stringList, int counter)//assume this list has, like, 10 elements, and counter=3, idk
{
    ...

    bool found= false;
    foreach(string s in stringList)
    {
        if(found)
            break;
        if(s.length < 2 || counter >=6)
            found=true;
        counter++;
    }

    ...

    return found
}

技术上也有效,但我想避免我的代码中断。在c#中有没有其他干净的方法来实现这一目标?

编辑:我看到很多关于我在这里问的问题。我希望有一种方法可以添加一个非常清晰的检查,如果可能的话我们是否应该打破foreach语句本身,或者编写我自己的foreach版本的方法,它接受一个仅在条件为真时继续的参数,例如路径还没有找到。

另外,我很抱歉不清楚,但我想避免休息的最大原因是我不会在任意点跳出循环。在这方面,回报也是不合需要的。

我也没有反对Linq,我试图使用它,但我发现它不会产生我正在寻找的功能:

bool foo(List<strings> stringList, int counter)//assume this list has, like, 10 elements, and counter=3, idk
{
    bool found= false;
    foreach(string s in stringlist.Takewhile(x=> (!found)))
    {
        if(s.length < 2 || counter >=6)
            found=true;
        counter++;
    }
    return found
}

与上面的逻辑不同,因为TakeWhile首先执行并返回一个空集,导致foreach循环没有任何循环。如果有人有另一种方式来写这个,我真的很想听到它在语法上看起来非常干净。

c# loops foreach while-loop
3个回答
1
投票

在循环之前和之后存在其他代码的事实表明您应该重构代码以分离关注点。如果将逻辑片段分成不同的位置,您的代码将会得到改善。具有紧密耦合逻辑的长方法不可重用且难以维护。

例如,您的方法可以返回几个不同逻辑的逻辑组合,每个逻辑组合被委托给不同的方法。显示的逻辑片段可以委托给另一种方法,如下所示。

我会使用break,因为它的设计完全符合您的要求,并且没有任何问题。但是对于你的具体例子,你也可以避免像这样的休息......

bool foo_part2(List<strings> stringList, int counter)
{
    foreach (string s in stringList)
    {
        if(s.length < 2 || counter >=6)
            return true;
        counter++;
    }
    return false;
}

......而原始方法看起来像这样......

bool foo(List<strings> stringList, int counter)
{
    return foo_part1(stringList,counter) ||
        foo_part2(stringList,counter) ||
        foo_part3(stringList,counter);
}

(您可能需要使用&&s而不是||,具体取决于所需的逻辑。)使用正确命名的方法(而不是这个“foo”示例),这可以非常容易阅读,并且可以避免您必须查看函数看看它在做什么。

但是,总结......问题中存在错误。你声明“我也没有反对Linq,我试图使用它,但我发现它不会产生我正在寻找的功能......因为TakeWhile首先执行”。这是不正确的。这意味着你没有自己尝试,而且你不理解the answer you were given to your previous question 20 minutes before asking this one。它使用谓词,因此每次迭代都会评估值,这正是您想要的。所以这整个问题都存在缺陷,如果你自己尝试过(甚至在问过上一个问题之前),你就会自己解决这个问题。

我将OP引用到How much research effort is expected of Stack Overflow users?的问题。


0
投票

不确定你的代码在做什么;但是以下使用Linq Any实现了相同的功能。

bool foo(List<string> stringList, int counter)//assume this list has, like, 10 elements, and counter=3, idk
            {
                return stringList.Any(s =>
                {
                    var found = s.Length < 2 || counter >= 6;
                    counter++;
                    return found;
                });            
            }

0
投票

如果您坚持不使用break,则替代方法是使用委托,尽管使用break是最佳实践。

...

bool found= false;
Action Search = () =>
{
    foreach(string s in stringList)
    {
        if(s.length < 2 || counter >=6)
            found=true;
            return;
        counter++;
    }
}

Search();

...

不要使用此代码。使用休息。

© www.soinside.com 2019 - 2024. All rights reserved.