I'm assuming you need to use the index within the loop - otherwise, just use a For Each loop instead.
1 is the idiomatic way for a single-dimensional array, in my view. It's the closest to the normal way you'd see in C#:
for (int x = 0; x < array.Length; x++)
It's unfortunate that VB has this slight dual personality these days in terms of whether it's zero or one-based. .NET is generally a zero-based platform, and you're suffering for it here; languages designed around zero-based APIs are likely to make the "inclusive lower-bound; exclusive upper-bound" pattern simpler - whereas VB is inclusive at both ends, which is why you need the "-1".
2 looks like it's a VB-specific function; I would try to avoid these unless they present significant advantages, as it will make it harder for non-VB programmers (e.g. C# programmers) to understand the code. That's only a very minor concern in many cases, but when there are no real advantages to it, I'd stick with "regular" .NET approaches.
3 is really designed for multi-dimensional (rectangular) arrays - the 0 there is saying that you want the first dimension. When you're dealing with single-dimensional arrays it's adding extra complexity for no good reason.
It's possible that the first approach is also the most performant - the JIT recognizes this pattern and is able to remove some array bounds tests within the loop (it knows that x
is within the bounds of the array). Now UBound
may compile to IL that has the same property - I'm not sure. I suspect it makes a call to a method within the Microsoft.VisualBasic assembly, which the JIT is less likely to have knowledge of.