GOTO是退出双Foreach的唯一途径吗?

时间:2012-12-28 14:43:46

标签: c# .net vb.net goto

  

可能重复:
  breaking/exit nested for in vb.net

GOTO是退出双重ForEach的唯一途径吗?

For Each city in cities
  For Each person in city.People
    If IsOK(person) GOTO Found_
  Next person
Next city

Found_: 
' ...

问题出在VB.NET上,但也想知道C#...

8 个答案:

答案 0 :(得分:9)

将它放在单独的函数

  Private Function FindPerson(cities As List(of City)) As Person
     For Each city in cities
        For Each person in city.People
           If IsOK(person) Return person
        Next person
     Next city
     Return Nothing
  End Function

和...

  Private Function ContainsPerson(cities As List(of City)) As Bool  
     For Each city in cities
        For Each person in city.People
           If IsOK(person) Return True
        Next person
     Next city
     Return False
  End Function

编辑:修正了VB语法

答案 1 :(得分:5)

海因兹在this question回答:

很遗憾,没有exit two levels of for声明,但有一些解决办法可以避免Gotoconsidered to be bad practice

  • 虚拟外部块

    Do
        For Each item In itemList
            For Each item1 In itemList1
                If item1.Text = "bla bla bla" Then
                    Exit Do
                End If
            Next
        Next
    Loop While False
    

    Try
        For Each item In itemlist
            For Each item1 In itemlist1
                If item1 = "bla bla bla" Then
                    Exit Try
                End If
            Next
        Next
    Finally
    End Try
    
  • 单独的功能:将循环放在一个单独的函数中,可以使用return退出。但是,这可能需要您传递大量参数,具体取决于您在循环中使用的局部变量数量。另一种方法是将块放入多行lambda,因为这会在局部变量上创建一个闭包。

  • 布尔变量:这可能会使您的代码的可读性降低,具体取决于您拥有多少层嵌套循环:

    Dim done = False
    
    For Each item In itemList
        For Each item1 In itemList1
            If item1.Text = "bla bla bla" Then
                done = True
                Exit For
            End If
        Next
        If done Then Exit For
    Next
    

答案 2 :(得分:5)

为什么不使用LINQ?

C#:

// Or use SingleOrDefault(...) if there can ever only be one.
var person = Cities.SelectMany(city => city.People)
                   .FirstOrDefault(person => IsOK(person));

if (person != null)
{
    ...
}

VB.Net(我最好的尝试,我并没有在其中详细说明):

// Or use SingleOrDefault(...) if there can ever only be one.
Dim person = Cities.SelectMany(Function(city) city.People)
                   .FirstOrDefault(Function(person) IsOK(person));

If person Not Nothing Then
    ...
End If

如果您要做的只是查看是否有IsOK(person),请改用Any(...)扩展方法:

C#:

var isOK = Cities.SelectMany(city => city.People)
                 .Any(person => IsOK(person));

VB.Net(我最好的尝试,我并没有在其中详细说明):

Dim isOK = Cities.SelectMany(Function(city) city.People)
                 .Any(Function(person) IsOK(person));

答案 3 :(得分:2)

你可以在第一个循环中放一个bool并在内循环中将其设置为false然后中断。 然后在外循环中断,如果bool为假。

答案 4 :(得分:0)

你也可以抛出异常:

Try
  For Each city in cities
    For Each person in city.People
      If IsOK(person) Throw New FoundException
    Next person
  Next city
Catch ex As FoundException
  DoFoundStuff
End Try

警告:我的观点只是表明异常是退出多个嵌套循环的选项,而不是在这个代码示例的特定情况下它是合适的。特别是,例外通常应限于“异常/错误”条件而不是“正常”条件。例如,如果您只是将“If”更改为“If Not IsOK ....”,则异常可能是正确的解决方案。

答案 5 :(得分:0)

添加布尔值并在找到人员时将其设置为true并从内部循环中断开。然后检查发现是否属实。如果是这样,那么从外循环中断。

bool found;
For Each city in cities
    For Each person in city.People
        If IsOK(person) 
            found = true
            Exit For
        End If
    Next person
    If (found) 
        Exit For
    End If
 Next city

答案 6 :(得分:0)

一直在写vb.net的年龄,但以下应该有效(我认为)

    Dim found As Boolean
    For Each city In cities
        If found = True Then
            Exit For
        End If
        For Each person In city.People

            If IsOK(person) Then
                found = True
                Exit For
            End If
        Next person
    Next city

答案 7 :(得分:0)

除了888的回答:额外的功能不一定需要传递参数:

Dim a, b, c As Integer
    a = 100
    b = 50
    c = 20

    Dim r = Function()
                For i = 1 To a
                    For j = 1 To b
                        For k = 1 To c
                            If i * j * k = 150 Then Return 1
                        Next
                    Next
                Next
                Return 2
            End Function

    Console.WriteLine(r)

关键字:关闭