Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# equivalent to Delphi High() and Low() functions for arrays that maintains performance?

In Delphi there are the Low() and High() functions that return the lowermost and uppermost index dimensions for an Array. This helps eliminate error prone for loops for iterating an array that might fall victim to an insidious +1/-1 array boundary error, like using <= when you meant < for the terminating condition in the for loop statement.

Here's an example for the Low/High functions (in Delphi):

for i := Low(ary) to High(ary) do

For now I'm using a simple for loop statement in C#:

for (int i = 0; i < ary.Length; i++)

I know there is the Array method GetDimension(N) but that has its own liabilities since I could introduce an error by accidentally using the wrong dimension index. I guess I could do something with enumerators, but I worry that there would be a significant performance cost when scanning a large array compared to using a for loop. Is there an equivalent to High/Low in C#?

like image 675
Robert Oschler Avatar asked Jan 18 '26 07:01

Robert Oschler


2 Answers

The C# equivalent to the intrinsic low(ary) and high(ary) functions are, respectively, 0 and ary.Length-1. That's because C# arrays are zero based. I don't see any reason why the Length property of an array should have performance characteristics that differ from Delphi's high().

In terms of performance, the big difference between a Pascal for loop and that used by C derived languages concerns evaluation of the termination test. Consider a classic Pascal for loop:

for i := 0 to GetCount()-1 do
  ....

With a Pascal for loop, GetCount() is evaluated once only, at the beginning of the loop.

Now consider the equivalent in a C derived language:

for (int i=0; i<GetCount(); i++)
  ....

In this loop, GetCount() is evaluated every time round the loop. So in a language like C#, you would need a local variable to avoid calling that function over and over.

int N = GetCount();
for (int i=0; i<N; i++)
  ....

In the case of an array, if the optimiser could be certain that ary.Length did not mutate during the loop, then the code could be optimised by the compiler. I personally do not know whether or not the C# optimiser does that, but please refer to the comments for some more information.

Before you start re-writing your loops to use local variables containing the length of the array, check whether or not it makes any difference. Almost certainly it won't. The difference between Pascal and C-like for loops that I outline above is probably more significant in semantic terms than performance.


The language that I am particularly envious of is D. Here you can use a foreach loop that presents each item in an array as a reference, and thus allows you to modify the contents of the array:

void IncArray(int[] array, int increment) {
    foreach (ref e; array) {
        e += increment;
    }
}    
like image 188
David Heffernan Avatar answered Jan 19 '26 22:01

David Heffernan


In C# the lower boundary is always zero, so the equivalent of Low(ary) is just 0.

For a single dimension array, the equivalent of High(ary) is ary.Length - 1. (For multi dimensional arrays you would need more than one loop anyway.)

like image 44
Guffa Avatar answered Jan 19 '26 21:01

Guffa