Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/453.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 跳出嵌套循环可以吗?_C#_Javascript - Fatal编程技术网

C# 跳出嵌套循环可以吗?

C# 跳出嵌套循环可以吗?,c#,javascript,C#,Javascript,JavaScript支持类似goto的语法来打破嵌套循环。一般来说,这不是一个好主意,但被认为是可以接受的做法。C#不直接支持break labelName语法……但它支持臭名昭著的goto 我相信C#也可以达到同样的效果: inti=0; 而(i)(5) { 转到断开;//断开所有循环 } } 中断: 按照JavaScript的相同逻辑,嵌套循环场景是否可以接受使用goto?否则,我知道实现此功能的唯一方法是通过设置具有适当范围的bool。IMO在不支持break n的语言中,这是可以接受的

JavaScript支持类似goto的语法来打破嵌套循环。一般来说,这不是一个好主意,但被认为是可以接受的做法。C#不直接支持
break labelName
语法……但它支持臭名昭著的
goto

我相信C#也可以达到同样的效果:

inti=0;
而(i)(5)
{
转到断开;//断开所有循环
}
}
中断:

按照JavaScript的相同逻辑,嵌套循环场景是否可以接受使用
goto
?否则,我知道实现此功能的唯一方法是通过设置具有适当范围的
bool

IMO在不支持
break n的语言中,这是可以接受的其中
n
指定它应该中断的循环数。

至少它比设置一个在外部循环中检查的变量可读性好得多。

我相信在这种情况下“goto”是可以接受的。不幸的是,C#不支持任何巧妙的方法来打破嵌套循环。

在C#中是不可接受的

只需将循环包装在函数中并使用
return

编辑:因此,向下投票习惯于对错误答案进行投票,而不是对您不同意的答案进行投票。正如OP明确地问到的“它可以接受吗?”,回答“不可接受”并不是不正确的(尽管您可能不同意)。

我个人会尝试通过简单地将循环放入不同的方法来避免在这里使用goto-虽然您不能轻易地打破特定级别的循环,但您可以在任何时候轻松地从方法返回


根据我的经验,这种方法通常会导致更简单、更可读的代码,方法通常更短(做一项特定的工作)。

让我们澄清一件事:使用
goto
语句从根本上说没有什么错,它不是坏事——它只是工具箱中的又一个工具。真正重要的是你如何使用它,它很容易被误用


打破某种描述的嵌套循环可能是对该语句的有效使用,尽管您应该首先查看它是否可以重新设计。可以重写循环出口表达式吗?您是否使用了适当的循环类型你能过滤你可能要迭代的数据列表,这样你就不需要提前退出吗?你应该把一些循环代码重构成一个单独的函数吗?

这在C#中有点不可接受。如果你的设计无法避免的话,那就得使用它。但首先要用尽所有其他选择。它将提高可读性和可维护性。在您的示例中,我精心设计了一个这样的潜在重构:

void Original()
{
    int i = 0;            
    while(i <= 10)
    {
        Debug.WriteLine(i);
        i++;
        if (Process(i))
        {
            break;
        }
    }
}

bool Process(int i)
{
    for(int j = 0; j < 3; j++)
        if (i > 5)
        {
            return true;
        }
    return false;
}
void Original()
{
int i=0;
而(i)(5)
{
返回true;
}
返回false;
}

我的观点:带有嵌套循环的复杂代码流很难推理;分支,无论是goto还是break,只会让事情变得更难。与其编写goto,我首先要认真考虑是否有办法消除嵌套循环

以下是一些有用的技巧:

第一种技术:将内部循环重构为方法。让方法返回是否中断外部循环。因此:

for(outer blah blah blah)
{
    for(inner blah blah blah)
    {
        if (whatever)
        {
             goto leaveloop;      
        }
    }
}
leaveloop:    
...
变成

for(outer blah blah blah)
{
    if (Inner(blah blah blah))
        break;
}

...

bool Inner(blah blah blah)
{
    for(inner blah blah blah)
    {
        if (whatever)
        {
             return true;      
        }
    }
    return false;
}
第二种技巧:如果循环没有副作用,使用LINQ

// fulfill the first unfulfilled order over $100
foreach(var customer in customers)
{
    foreach(var order in customer.Orders)
    {
        if (!order.Filled && order.Total >= 100.00m)
        {
             Fill(order);
             goto leaveloop;      
        }
    }
}
leaveloop:    
相反,写下:

var orders = from customer in customers
             from order in customer.Orders;
             where !order.Filled
             where order.Total >= 100.00m
             select order;
var orderToFill = orders.FirstOrDefault();
if (orderToFill != null) Fill(orderToFill);
无循环,因此无需中断

或者,正如configurator在注释中指出的,您可以用以下形式编写代码:

var orderToFill = customers
    .SelectMany(customer=>customer.Orders)
    .Where(order=>!order.Filled)
    .Where(order=>order.Total >= 100.00m)
    .FirstOrDefault();
if (orderToFill != null) Fill(orderToFill);

这个故事的寓意是:循环强调控制流,而牺牲了业务逻辑。与其试图将越来越复杂的控制流相互叠加,不如尝试重构代码,使业务逻辑清晰。

如果要跳过该项,我建议使用
continue
,如果要退出循环,建议使用
break
。对于更深层的嵌套,请将其放入方法中并使用
return
。我个人宁愿使用状态bool,也不愿使用
goto
。宁可使用
goto
作为最后手段。

inti=0;
int i = 0;                 
while(i <= 10)     
{         
    Debug.WriteLine(i);         
    i++;         
    for(int j = 0; j < 3 && i <= 5; j++)             
    {
        //Whatever you want to do
    }
 }      
while(i)匿名函数 你几乎总能找到匿名函数或lambda的内部循环,这里你可以看到函数曾经是一个内部循环,我不得不使用GoTo

private void CopyFormPropertiesAndValues()
{
    MergeOperationsContext context = new MergeOperationsContext() { GroupRoot = _groupRoot, FormMerged = MergedItem };
    // set up filter functions caller
    var CheckFilters = (string key, string value) =>
    {
        foreach (var FieldFilter in MergeOperationsFieldFilters)
        {
            if (!FieldFilter(key, value, context))
                return false;
        }
        return true;
    };
    // Copy values from form to FormMerged 
    foreach (var key in _form.ValueList.Keys)
    {
        var MyValue = _form.ValueList(key);
        if (CheckFilters(key, MyValue))
            MergedItem.ValueList(key) = MyValue;
    }
}
手动搜索数据集中的多个项目时也会出现这种情况。遗憾的是,从清晰的角度来看,正确使用goto比布尔/标志更好,但这比任何一个都清楚,避免了同事的嘲笑


然而,对于高性能的情况,goto是合适的,但只有1%,让我们诚实地说…

一如既往:我发现这篇有趣文章的可能副本-我本人从未在C#中使用过goto,但我喜欢这家伙的视角。它描述了我们对这些亵渎思想的反应,如(喘息)goto语句在C#中非常准确。@Dani除了重复别人说的“正确”之外,你还有什么理由吗?@Rob:我想这是一种风格的选择。你总是可以用全局变量编写整个程序,除了Main之外没有类和函数。语言支持它。从这个意义上说,它当然不是不适用的可接受的。什么样的东西对你来说是“可接受的”或“不可接受的”?不可接受的?从未见过有必要这样做,但“不可接受的”太多了。@Sjoerd-read@Rob,所以我们不同意。但这是问题的有效答案,而且有原因。因此:不需要否决投票。@Sjoerd你给出了一个替代的实现,而不是为什么它更好,或者为什么不应该使用goto的原因。叹气,我们又来了。对否决投票有什么解释吗,否决投票人?请参阅我的answe上的讨论r、 “不可接受”对某些人来说是一个不可接受的答案。try对我来说听起来太温和了。以我的经验,wha
private void CopyFormPropertiesAndValues()
{
    MergeOperationsContext context = new MergeOperationsContext() { GroupRoot = _groupRoot, FormMerged = MergedItem };
    // set up filter functions caller
    var CheckFilters = (string key, string value) =>
    {
        foreach (var FieldFilter in MergeOperationsFieldFilters)
        {
            if (!FieldFilter(key, value, context))
                return false;
        }
        return true;
    };
    // Copy values from form to FormMerged 
    foreach (var key in _form.ValueList.Keys)
    {
        var MyValue = _form.ValueList(key);
        if (CheckFilters(key, MyValue))
            MergedItem.ValueList(key) = MyValue;
    }
}