so you CAN have non zero based array

G

Guest

so I've read these blog entries and such on why the not allowing non-zero based array index. turns out, you can make it work in C#. this code coming straight from the .NET SDK 1.1 under Array.CreateInstance. my question is, is this there for VB compatibility reason or something

using System
public class SamplesArray

public static void Main()

// Creates and initializes a multidimensional Array of type String
int[] myLengthsArray = new int[2] { 3, 5 }
int[] myBoundsArray = new int[2] { 2, 3 }
Array myArray=Array.CreateInstance( typeof(String), myLengthsArray, myBoundsArray )
for ( int i = myArray.GetLowerBound(0); i <= myArray.GetUpperBound(0); i++
for ( int j = myArray.GetLowerBound(1); j <= myArray.GetUpperBound(1); j++ )
int[] myIndicesArray = new int[2] { i, j }
myArray.SetValue( Convert.ToString(i) + j, myIndicesArray )


// Displays the lower bounds and the upper bounds of each dimension
Console.WriteLine( "Bounds:\tLower\tUpper" )
for ( int i = 0; i < myArray.Rank; i++
Console.WriteLine( "{0}:\t{1}\t{2}", i, myArray.GetLowerBound(i), myArray.GetUpperBound(i) )

// Displays the values of the Array
Console.WriteLine( "The Array contains the following values:" )
PrintValues( myArray )


public static void PrintValues( Array myArr )
System.Collections.IEnumerator myEnumerator = myArr.GetEnumerator()
int i = 0
int cols = myArr.GetLength( myArr.Rank - 1 )
while ( myEnumerator.MoveNext() )
if ( i < cols )
i++
} else
Console.WriteLine()
i = 1

Console.Write( "\t{0}", myEnumerator.Current )

Console.WriteLine()
 
N

Nicholas Paldino [.NET/C# MVP]

Daniel,

I think that it is only half of the issue. When dealing with arrays
being passed through COM interop, you need an array type that is not limited
to having the lower bound at zero (since the SAFEARRAY structure in COM
allows for variable lower bounds). Granted, this is almost ubiquitous (a
lower bound of zero), but supporting these fringe cases is important.

Hope this helps.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Daniel Jin said:
so I've read these blog entries and such on why the not allowing non-zero
based array index. turns out, you can make it work in C#. this code coming
straight from the .NET SDK 1.1 under Array.CreateInstance. my question is,
is this there for VB compatibility reason or something?
using System;
public class SamplesArray {

public static void Main() {

// Creates and initializes a multidimensional Array of type String.
int[] myLengthsArray = new int[2] { 3, 5 };
int[] myBoundsArray = new int[2] { 2, 3 };
Array myArray=Array.CreateInstance( typeof(String), myLengthsArray, myBoundsArray );
for ( int i = myArray.GetLowerBound(0); i <=
myArray.GetUpperBound(0); i++ )
for ( int j = myArray.GetLowerBound(1); j <=
myArray.GetUpperBound(1); j++ ) {
int[] myIndicesArray = new int[2] { i, j };
myArray.SetValue( Convert.ToString(i) + j, myIndicesArray );
}

// Displays the lower bounds and the upper bounds of each dimension.
Console.WriteLine( "Bounds:\tLower\tUpper" );
for ( int i = 0; i < myArray.Rank; i++ )
Console.WriteLine( "{0}:\t{1}\t{2}", i, myArray.GetLowerBound(i), myArray.GetUpperBound(i) );

// Displays the values of the Array.
Console.WriteLine( "The Array contains the following values:" );
PrintValues( myArray );
}


public static void PrintValues( Array myArr ) {
System.Collections.IEnumerator myEnumerator = myArr.GetEnumerator();
int i = 0;
int cols = myArr.GetLength( myArr.Rank - 1 );
while ( myEnumerator.MoveNext() ) {
if ( i < cols ) {
i++;
} else {
Console.WriteLine();
i = 1;
}
Console.Write( "\t{0}", myEnumerator.Current );
}
Console.WriteLine();
}
}
 
J

Jon Skeet [C# MVP]

Daniel Jin said:
so I've read these blog entries and such on why the not allowing
non-zero based array index. turns out, you can make it work in C#.

Sort of. You can have non-zero based objects which are of type Array
(or a derived type thereof) - but they aren't arrays in the C# sense of
being able to use

object[] foo = ...;

You can still use an indexer, however, by casting the Array (rather
than array :) to IList.
this code coming straight from the .NET SDK 1.1 under
Array.CreateInstance. my question is, is this there for VB
compatibility reason or something?

I suspect not, as I thought VB.NET arrays were 0-based as well. I
suspect it's there for the occasions where it makes things *much*
easier if you have a non-zero-based array - for example, a range of
[-10,10].
 
J

Jon Skeet [C# MVP]

Daniel Jin said:
You can still use an indexer, however, by casting the Array (rather
than array :) to IList.

actually, I tried this, you can safely cast your Array instance to an array in C# sense

string[,] strArray = (string[,])myArray; // add this to the sdk doc sample

and now you got a non-zero based C# array.

Intriguing. I'm sure I tried that a while ago and found it *didn't*
work.

<sfx: lots of tapping>

Okay, that's bizarre. If you have a multi-dimensional array, you can
cast it without any problems. If you have a single-dimensional array,
its lower bound must be 0 otherwise you get an InvalidCastException.

I'm at least glad I wasn't going totally mad...
 
J

Jon Skeet [C# MVP]

Daniel Jin said:
bizarre indeed. would be nice to have an explaination. so now it's
certain that you still cannot have a non-zero based
single-dimensional C# array.

I can't find any explanation in the language specification itself, but
I can think of an efficiency reason for doing it that way. Multi-
dimensional arrays already require a computation every time you access
an element - you've got to multiply one index by the size of the rank
below, and then add the other index. In that context, adding a couple
more subtractions isn't too bad. Single-dimension arrays are generally
very fast though - it's just a case of adding the index (shifted by
one, two or four bits depending on type) to the pointer for the array.
Adding the extra subtraction for different lower bounds there would add
a significant proportion of work.

Just a guess, of course...
 
G

Guest

a reasonable guess

----- Jon Skeet [C# MVP] wrote: ----

Daniel Jin said:
bizarre indeed. would be nice to have an explaination. so now it'
certain that you still cannot have a non-zero base
single-dimensional C# array

I can't find any explanation in the language specification itself, but
I can think of an efficiency reason for doing it that way. Multi
dimensional arrays already require a computation every time you access
an element - you've got to multiply one index by the size of the rank
below, and then add the other index. In that context, adding a couple
more subtractions isn't too bad. Single-dimension arrays are generally
very fast though - it's just a case of adding the index (shifted by
one, two or four bits depending on type) to the pointer for the array.
Adding the extra subtraction for different lower bounds there would add
a significant proportion of work

Just a guess, of course..
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top