Is it possible in c# to initialize an array in, for example, subindex 1?
I'm working with Office interop, and every property is an object array that starts in 1 (I assume it was originally programed in VB.NET), and you cannot modify it, you have to set the entire array for it to accept the changes.
As a workaround I am cloning the original array, modifying that one, and setting it as a whole when I'm done.
But, I was wondering if it was possible to create a new non-zero based array
It is possible to do as you request see the code below.
// Construct an array containing ints that has a length of 10 and a lower bound of 1
Array lowerBoundArray = Array.CreateInstance(typeof(int), new int[1] { 10 }, new int[1] { 1 });
// insert 1 into position 1
lowerBoundArray.SetValue(1, 1);
//insert 2 into position 2
lowerBoundArray.SetValue(2, 2);
// IndexOutOfRangeException the lower bound of the array
// is 1 and we are attempting to write into 0
lowerBoundArray.SetValue(1, 0);
You can use Array.CreateInstance.
See Array Types in .NET
Not simply. But you can certainly write your own class. It would have an array as a private variable, and the user would think his array starts at 1, but really it starts at zero and you're subtracting 1 from all of his array accesses.
You can write your own array class
I don't think if it's possible to modify the starting index of arrays.
I would create my own array using generics and handle it inside.
Just keep of const int named 'offset' with a value of one, and always add that to your subscripts in your code.
I don't think you can create non-zero based arrays in C#, but you could easily write a wrapper class of your own around the built in data structures.This wrapper class would hold a private instance of the array type you required; overloading the [] indexing operator is not allowed, but you can add an indexer to a class to make it behave like an indexable array, see here. The index function you write could then add (or subtract) 1, to all index's passed in.
You could then use your object as follows, and it would behave correctly:
myArrayObject[1]; //would return the zeroth element.
In VB6 you could change the array to start with 0 or 1, so I think VBScript can do the same. For C#, it's not possible but you can simply add NULL value in the first [0] and start real value at [1]. Of course, this is a little dangerous...
Related
HOMEWORK: I'm getting and index out-of-bounds on the following code. It's a hangman game, and I'm keeping track of the letters I've guessed in a char array.
Here's the assumptions I made:
In the calling method, I have an unpopulated array (char[] displayGuesses = new char[26];) passing to the method below as the char[] usedLetters parameter.
The first iteration of the letter-guessing, the array will be empty.
It's length will be 0.
I populate usedLetters[0] with the letterGuessed parameter.
The next time I guess, length of the array will be 1, so usedLetters[1] gets populated...and so on.
public char[] trackUsedLetters(char letterGuessed, char[] usedLetters)
{
int letterIndex = usedLetters.Length;
usedLetters[letterIndex] = letterGuessed;
return usedLetters;
}
There's a couple things I think may be going on.
When I try to get the length of usedLetters on the first run, the empty array does
NOT return zero, but null. Boom. Out-of-bounds.
There's some issue with passing a blank array defined with 26
members...? But I'm not sure what that issue would even BE, so I have no idea what to google that will yield relevant results.
I may have a scope issue; I found this link to a similar
question for Java, though using a for loop. I don't quite get
what the Java user was going for, but some of the problems sounded
familiar.
I need a second pair of eyes to look at this and point me in the right direction for solving this.
According to the c# specification: (emphasis mine)
1.8 Arrays
Array types are reference types, and the declaration of an array variable simply sets aside space for a reference to an array instance. Actual array instances are created dynamically at run-time using the new operator. The new operation specifies the length of the new array instance, which is then fixed for the lifetime of the instance. The indices of the elements of an array range from 0 to Length - 1. The new operator automatically initializes the elements of an array to their default value, which, for example, is zero for all numeric types and null for all reference types.
Default Values which gives the char data type default as '\0'
It looks like you want List<char> that can grow (with Add) method.
Arrays have fixed size and following code (that you have in sample) will always throw out of range exception because you are accessing element past last element in array.
usedLetters[usedLetters.Length] = 'c';
More details on array length:
// newArray - array of 0 chars. newArray.Length is 0
var newArray = new char[0];
// nullArray not created, nullArray.Length will throw NullReferenceExcetption
char[] nullArray = null;
// defaultArray = array of 26 characters, each value 0.
// defaultArray.Length is 26;
char[] defaultArray = new char[26];
When you define a new array, but don't manually initialize the items inside of it, it will automatically be initialized with the default values for whatever type the array contains. In your case, you're creating a character array. The default value for a char is '\0', or the null character.
This means that the array is never truly "empty." If you define an array with 26 slots, it will always have that length, unless you make a new array.
Hi I was trying to find the number of elements in an array
byte[] salt = new byte[32];
now I only have mentioned size 32 so the Length Property of Array and Enumerable's Count Method will give me 32.
Even if I will iterate on this Array salt using for or foreach or any other looping construct it will iterate 32 times and on each index the value is 0 (i.e default value of byte)
Now suppose I do:
for (int i = 0; i < 5 ; i++)
{
salt[i] = 4-i;
}
And I want to know how many elements are inserted sequentially in Array starting from index 0, Here you may say are you fool you iterating it 5 times and you know the number is 5 , but I am having heavy looping and other logic (appending prepending to another arrays of byte) in it. *My question Is there any other inbuilt function that could give me this number 5 ? * Even if I iterate and check for first default value and break the loop there and get the count but there might be the chance last value inserted is 0 like above salt[4] is 0 so that iterating will give me the count 4 which is incorrect . If I am not wrong I think when we declare Array with size like 32 above 32 consecutive memory bytes are reserved and you are free to insert at any index from 0-31 and its your responsibility to keep the track where and how and how many elements are assigned to Array .I hope you got my point And thanks in advance for help.
An array is an array, and in .NET is initialized when it is allocated. Once it's initialized, the question of whether a given value is uninitialized or simply 0 isn't something that's possible to check. A 0 is a 0.
However, you can bypass that in several ways. You can use a List<int>, like #SLaks suggested, to have a dynamically allocated list that's only initialized with the elements you want.
You can also use, instead of an array of int, and array of int?, so a null value isn't the same as a 0.
Short answer is you can't, the array contains 32 integers, .net framework doesn't care if some of them are 0, so you can create your own function that counts how many integers from an array are different than 0, or keep a "count" when you assign values for array elements or something like that.
Or you can use another container, example a list and dynamically add or remove integers from it.
Ok, when you define an array as int[] myArray = int[32]; you are saying, I HAVE 32 ints. Not, create me space for 32 ints that I will fill in later. That's why count is giving you 32.
If you want something which you can genuinly add to and resize, you need to use a List (or one of it's relatives.
If you want to have a "cap" for a list, I found this :Maximum capacity collection in c#
For multidimensional arrays Array.CreateInstance can be used to create non-zero index based arrays, but if you try that for a 1-dimensional arrays (vectors) as in e.g.:
public double[] myArray = (double[])Array.CreateInstance(typeof(double), new int[1] { 12 }, new int[1] { 1 });
this will fail at run-time when the cast from the the multidimensional Array to a single-dimensional array fails
"Unable to cast object of type 'System.Double[*]' to type 'System.Double[]'"
Now I could just create a zero based array and ignore the first value, or work with offsets etc., but am I overlooking some c# syntactic magic that allows for non zero based vectors?
Update:
I'll take Eric Lippert's word for it if he says "There's no obvious way to make a non-zero-based array in C#"
You can make a non-zero-based array in C#, but the useage of it is kind-of obnoxious. It is definitly not a simple substitute for a normal (i.e., zero-based single dimentional) array.
// Create the array.
Array myArray = Array.CreateInstance(typeof(double), new int[1] { 12 }, new int[1] { 1 });
// Fill the array with random values.
Random rand = new Random();
for (int index = myArray.GetLowerBound(0); index <= myArray.GetUpperBound(0); index++)
{
myArray.SetValue(rand.NextDouble(), index);
}
// Display the values.
for (int index = myArray.GetLowerBound(0); index <= myArray.GetUpperBound(0); index++)
{
Console.WriteLine("myArray[{0}] = {1}", index, myArray.GetValue(index));
}
The GetValue/SetValue syntax that is required for this is uglier than subtracting one from a vector index at each occurance.
If a value type is stored in the array, then it will be stored in consecutive position just as in a regular array, but the getter and setter will require boxing of the values (unless there is some compiler magic that I am not aware of). And the getter will usually require a cast (just to make it even uglier).
double myValue = (double)myArray.GetValue(index);
Also note that the correct comparison for GetUpperBound is <=, unlike Length which is compared with <.
Non-Zero based arrays DO exist in C, and there IS a way to create a 1's (or whatever) based array.
I fully agree that they are messy, and they should not be used for anything other than legacy stuff, but they are ESSENTIAL to interact with old COM libraries.
The most common place to run into this is working with the Microsoft.Office.Interop.Excel.Range object in the Excel library which still uses the old DCOM interface underneath.
Example:
/// <summary>
/// Makes the equivalent of a local Excel range that can be populated
/// without leaving .net
/// </summary>
/// <param name="iRows">number of rows in the table</param>
/// <param name="iCols">number of columns in the table</param>
/// <returns>a 1's based, 2 dimensional object array which can put back to Excel in one DCOM call.</returns>
public static object[,] NewObjectArray(int iRows, int iCols)
{
int[] aiLowerBounds = new int[] { 1, 1 };
int[] aiLengths = new int[] { iRows, iCols};
return (object[,])Array.CreateInstance(typeof(object), aiLengths, aiLowerBounds);
}
In this case, the reason this code is necessary is each DCOM call to excel is a cross-process call, and if you were to access cells one-at-a-time, you'd incur huge overhead, (either retrieving or setting values). An Excel range is a 1's based 2 dimensional array, and if one creates the array, and populates it locally, it can be pushed to excel in one cross-process call, creating an enormous performance improvement.
If anybody is still looking for a one-based array implementation, here is a one-dimensional generic one-based array, which is just a wrapper type on a regular array:
https://github.com/ColmBhandal/CsharpExtras/blob/master/CsharpExtras/Enumerable/OneBased/OneBasedArray.cs
There is also a two-dimensional version, but no higher dimensional versions as of yet (this code was written to support Excel, so 2D was all that was needed):
https://github.com/ColmBhandal/CsharpExtras/blob/master/CsharpExtras/Enumerable/OneBased/OneBasedArray2D.cs
Both of these types have test written for them in an associated test project under the same repo:
https://github.com/ColmBhandal/CsharpExtras/tree/master/CsharpExtrasTest/OneBased
Disclaimer: these repos are hosted on my personal GitHub account and are open source.
All arrays in C# are zero based. As far as I know there is no way to create a 1 based array. Imagine what kind of a mess would have happened if that was possible. Here is a similar thread which explains the issue with more details - C#: Nonzero-based arrays are not CLS-compliant
I am using C#.
I have an array of size 10. I want to pass it to a function, but only from the second element. In C, this is how I would implement it
myfunc( myarray + 1 )
Effectively I am virtually shifting the array / deleting the first element.
How do I implement this in C# ?
If you're using .NET 3.5, the easiest is to use Skip(1) then convert back to an array.
myFunc(myArray.Skip(1).ToArray());
If performance is an issue then you will either need to construct a new array manually or change your function to accept an index parameter.
There are four options here:
Pass in an index, and use that in your function
Make your function use IEnumerable<T> instead of an array (T[]), then use myArray.Skip(1).
Use skip, but convert back to an array. This copies the array elements, however.
Use an ArraySegment<T> instead of an array for your function.
This really depends on whether you have control over the usage within your myfunc function. If that function must accept an array, and you can't pass an index, you're going to be stuck creating a copy of the array.
You could pass an index to the function also, and only access the array beginning at that index.
Is it possible in c# to initialize an array in, for example, subindex 1?
I'm working with Office interop, and every property is an object array that starts in 1 (I assume it was originally programed in VB.NET), and you cannot modify it, you have to set the entire array for it to accept the changes.
As a workaround I am cloning the original array, modifying that one, and setting it as a whole when I'm done.
But, I was wondering if it was possible to create a new non-zero based array
It is possible to do as you request see the code below.
// Construct an array containing ints that has a length of 10 and a lower bound of 1
Array lowerBoundArray = Array.CreateInstance(typeof(int), new int[1] { 10 }, new int[1] { 1 });
// insert 1 into position 1
lowerBoundArray.SetValue(1, 1);
//insert 2 into position 2
lowerBoundArray.SetValue(2, 2);
// IndexOutOfRangeException the lower bound of the array
// is 1 and we are attempting to write into 0
lowerBoundArray.SetValue(1, 0);
You can use Array.CreateInstance.
See Array Types in .NET
Not simply. But you can certainly write your own class. It would have an array as a private variable, and the user would think his array starts at 1, but really it starts at zero and you're subtracting 1 from all of his array accesses.
You can write your own array class
I don't think if it's possible to modify the starting index of arrays.
I would create my own array using generics and handle it inside.
Just keep of const int named 'offset' with a value of one, and always add that to your subscripts in your code.
I don't think you can create non-zero based arrays in C#, but you could easily write a wrapper class of your own around the built in data structures.This wrapper class would hold a private instance of the array type you required; overloading the [] indexing operator is not allowed, but you can add an indexer to a class to make it behave like an indexable array, see here. The index function you write could then add (or subtract) 1, to all index's passed in.
You could then use your object as follows, and it would behave correctly:
myArrayObject[1]; //would return the zeroth element.
In VB6 you could change the array to start with 0 or 1, so I think VBScript can do the same. For C#, it's not possible but you can simply add NULL value in the first [0] and start real value at [1]. Of course, this is a little dangerous...