VB.NET“For each”与“.GetUpperBound(0)”

时间:2014-04-17 14:17:30

标签: vb.net string vector foreach

我想知道什么是首选...

    Dim sLines() As String = s.Split(NewLine)

每个人:

    For Each sLines_item As String In sLines

.GetUpperBound:

    For i As Integer = 0 To sLines.GetUpperBound(0)

我不知道为什么" For Each"是为这种情况介绍的。到目前为止,我只使用了.GetUpperBound,而且我没有看到任何专业版的#34; For Each"。

谢谢

ps:当我使用。" GetUpperBound(0)"时,我知道我正在迭代向量。 " For Each"相反,听起来像是"我不关心矢量给我的顺序"。但我认为这只是个人兴趣。

3 个答案:

答案 0 :(得分:3)

简答:不要使用GetUpperBound()GetUpperBound()的唯一优势是它适用于多维数组,其中Length不起作用。但是,即使该用法已过时,因为有Array.GetLength()可用的dimension参数。对于所有其他用途,For i = 0 to Array.Length - 1更好,可能是最快的选择。

答案 1 :(得分:0)

这主要是个人偏好。

如果您需要更改数组的元素,则应使用For i ...,因为更改sLines_item不会影响相应的数组元素。

如果您需要删除数组的元素,可以迭代For i = ubound(sLines) to 0 step -1(或等效的)。

答案 2 :(得分:0)

简短回答

除非您别无选择,否则应始终在For Each类型上使用IEnumerable

答案很长

与流行的理解相反,For EachFor Next之上 <=> 一个句法糖。它不一定会迭代其源的每个元素。它是IEnumerable.GetEnumerator()之上的一个语法糖。 For Each将首先获取一个枚举器到其源,然后循环,直到它无法进一步枚举。基本上,它将被以下代码替换。请记住,这是过于简单化了。

' Ask the source for a way to enumerate its content in a forward only manner.
Dim enumerator As IEnumerator = sLines.GetEnumerator()
' Loop until there is no more element in front of us.
While enumerator.Next() Then
    ' Invoke back the content of the for each block by passing
    ' the currently enumerated element.
    forEachContent.Invoke(enumerator.Current)
End While

这与经典For Next循环之间的主要区别在于它不依赖于任何长度。这解决了现代.NET语言中的两个限制。第一个与Count方法有关。 IEnumerable提供Count方法,但实现可能无法跟踪其存储的实际元素数量。因此,调用IEnumerable.Count可能会导致源被迭代以实际计算它包含的元素数量。此外,将此作为传统For Next循环的结束值将导致对循环中的每个元素执行此过程。这很慢。以下是此过程的说明:

For i As Integer = 0 To source.Count()  ' This here will cause Count to be
                                        ' evaluated for every element in source.
    DoSomething(source(i))
Next

使用For Each通过永远不会请求源的长度来修复此问题。

它修复的第二个限制是缺少具有无限元素的数组的概念。这种情况的一个例子是包含PI的每个数字的数组,其中每个数字仅在您请求时计算。这是LINQ进入并真正发光的地方,因为它使您能够编写以下代码:

Dim piWith10DigitPrecision = From d In InfinitePiSource
                             Take 10
Dim piWith250DigitPrecision = From d In InfinitePiSource
                              Take 250
Dim infite2PiSource = From d In InfinitePiSource
                      Select d * 2

现在,在一个无限的源中,你不能依赖于一个长度迭代它的所有元素。它具有无限长度,因此使传统的For Next循环成为无限循环。这并没有改变我用pi给出的前两个例子的任何内容,因为我们明确地提供了我们想要的元素数量,但它确实用于第三个。你什么时候停止迭代? For EachYield(由Take运算符使用)结合使用时,请确保在实际请求特定值之前不会进行迭代。

你可能已经把它弄清楚但是这两件事意味着For Each实际上没有边界的概念,因为它根本不需要它们。 GetLowerBoundGetUpperBound的唯一用途是非零索引数组。例如,您可能有一个数组从1而不是零索引值。即便如此,您只需要GetLowerBoundLength。显然,这只是在源中元素的位置实际上很重要的时候。如果没有,您仍然可以使用For Each迭代所有元素,因为它是绑定不可知的。

此外,如前所述,GetLength应该用于零索引的多维数组,同样,只有当元素的位置很重要而不仅仅是元素本身时。