Dynamic array, index was outside the bound of the array? [duplicate] - c#

This question already has answers here:
What is an IndexOutOfRangeException / ArgumentOutOfRangeException and how do I fix it?
(5 answers)
Closed last year.
Here's my code:
using System;
public class Program
{
private static string[] ar = new string[] {};
public static void Main()
{
ar[0] = "hello";
Console.WriteLine("Total array length: " + ar.Length);
}
}
It show the error below when I run the above code:
Run-time exception (line 10): Index was outside the bounds of the array.
I thought that's how to define a dynamic array in C# but I must be missed something here.

You create an empty array, that is an array with fixed length 0 and no entries.
Consider List<string> ar = new List<string>() instead.
Related thread: Dynamic array in C#
EDIT: It later turned out the asker could use a Dictionary<int, string>. For a Dictionary<,>, the set accessor of the indexer (by which I mean the syntax ar[0] = "hello") will either create a new key/value pair (0 → "hello"), or overwrite the value of an already existing key (0).

Declaring private static string[] ar = new string[] {} actually means that you have an array of string with size of 0, i.e., empty array. C# doesn't allow to resize an array so you should initialize the array size if the length is fixed and this the reason you are getting the error Index was outside the bounds of the array. you are trying to set a value to an index which is larger then the array length.
In case the length is not fixed and you want to be dynamic, I recommend using List. Lists use arrays to store the data so you get the speed benefit of arrays with the convenience of a LinkedList by being able to add and remove items without worrying about having to manually change its size.
List<string> myList = new List<string>();
myList.Add("hello");
myList.Add("Ola");

private static string[] ar = new string[] {};
The above will create an empty array of string (i.e. allowed length = 0) and hence the IndexOutOfBound exception.
When you are not certain of the size of your collection, use List.
For e.g.: -
List<string> ar= new List<string>();
ar.Add("hello");
ar.Add("Ola");

Related

Apply "new" to only one dimension of multi-dimensional array?

I have this C# program, and it has the following code:
/*10 data for one peprson */
private int[] data = new int[10];
private void SomeMethod()
{
/*More code*/
this.data = new int[10];
/*More code*/
}
This program calls this method when an event occurs, and every time that happens, this one-dimensional array gets a "new" instance of an array of size 10, and refresh the array. Kinda like resetting it.
Now, I was told to write a new program that does the same thing, except that there are 5 people now. So I created a 2-dimensional array like
private int[,] data = new int[5, 10];
which will be able to store 10 data for each of the 5 people.
Now I am at a loss on how to refresh/reset only one person's data from this 2-d array. I tried
private void SomeMethod(int index) /*index 0 - 4 for each of the 5 people*/
{
this.data[index] = new int[10];
}
but this clearly does not work, and I get an error saying I am missing a dimension. Is there a way to achieve this?
For the time being, I am using
private void SomeMethod(int index) /*index 0 - 4 for each of the 5 people*/
{
for(int i=0; i<10; i++)
this.data[index, i] = 0;
}
When I tested it with the original code, I noticed that every time it got a "new" instance, it was assigning 0's to the array. Now the difference is that the original one is referencing the new instance with no data (and hence 0?), and the rewritten one is overwriting with 0's.
Do these two basically work the same way, program's-function-wise?
There's nothing wrong with the code you have. It's even likely faster than creating the new array. But if you really want to, you can use a jagged array instead:
private int[][] data = new int[5][];
//...
private void SomeMethod(int index) /*index 0 - 4 for each of the 5 people*/
{
this.data[index] = new int[10];
}
But arrays seem weird for this. A List<T> might be better:
private List<int[]> data = new List<int[]>();
where you can then use the .Add() method as you get new records, and use the Count property to know how many you've added.
Moreover, it's common to find out the int[10] array was actually a stand-in for named fields, where each position in the array has meaning. In that situation, you're usually much better off building a class for this data, where each item in the array is a named field in the class (we'll just call it MyClass for now). Then you end up with something like this:
private List<MyClass> data = new List<MyClass>();

c # - copying elements of one array to another - compile error

Learning some basics.. I'm trying to copy elements of an array to another. Let's say I don't know the size of the array 'bar'. So, I create an empty array 'arr' to copy the elements to bar into. The code below doesn't work.
It works if I replace
string[] arr ={} to string[] arr ={"",""}
How to declare an empty array and what should I modify in my code to achieve my goal?
Thanks!
//code
string[] bar = {"test", "user"};
string[] arr = {};
//iterate from the first to the last element of array bar
for (int i =0;i<bar.Length-1;i++)
{
Console.WriteLine("copy");
//copy string from bar to arr
arr[i]= bar[i];
//display the copied content from new array
Console.WriteLine(arr[i]);
}
in C#, arrays are of a fixed size. So when you create your array with size 0, you can't change the number of items it will contain, without re-instantiating it.
If you want to use a collection you can actively add/remove from (as is very common), consider using a List<T>:
string[] bar = {"test", "user"};
List<string> list = new List<string>();
for (int i =0;i<bar.Length-1;i++)
{
list.Add(bar[i]);
Console.WriteLine(list[i]);
}
By string[] arr = {}; you're instantiating an empty array of ZERO length, thus you need to define it like string[] arr = string[bar.Length];.
UPD:
Your code worked with string[] arr = {"",""}, because in this case you defined an array of length 2 using a two empty strings, but that's a code smell.
Arrays are fixed in size, which is why things like Lists are preferred over them.
In the case where you change your array definition to: string[] arr ={"",""} you are defining an array with a size of 2, same as your original array. When you try to copy it, the compiler already has everything allocated and ready to go, so it knows where position 0 and position 1 are in the array arr.
In the example in your code, where you have the array defined by string[] arr = {}; you are giving it an empty array (array size 0). The compiler has an issue, because it cannot reference position 0 or position 1 on an array that is empty.
You can modify the line as:
string[] arr = new string[4];
or
List<string> arr = new List<string>();
If you're going to use arrays, you'll want to create the second array as the same size as the first.
string[] bar = {"test", "user"};
string[] arr = new string[bar.Length];
If you know ahead of time that your array will be two, then you can just create it to be size two. Otherwise you'll want to inspect the size of the array you're copying from. If you know that you'll be adding and/or removing items, you'll want to use a different collection.

Deleting a specific item of an array [duplicate]

This question already has answers here:
Remove element of a regular array
(15 answers)
Closed 9 years ago.
string[] columns
I want to delete the item on an index specified by a variable of type int.
How do I do this ?
I tried
columns.RemoveAt(MY_INT_HERE);
But apparently this does not works.
Array is immutable class, you can't change it, all you can do is to re-create it:
List<String> list = columns.ToList(); // <- to List which is mutable
list.RemoveAt(MY_INT_HERE); // <- remove
string[] columns = list.ToArray(); // <- back to array
May be the best solution is to redesign your code: change immutable array into List<String>:
List<String> columns = ...
columns.RemoveAt(MY_INT_HERE);
If you don't want to use linq you can use this function :
public string[] RemoveAt(string[] stringArray, int index)
{
if (index < 0 || index >= stringArray.Length)
return stringArray;
var newArray = new string[stringArray.Length - 1];
int j = 0;
for (int i = 0; i < stringArray.Length; i++)
{
if(i == index)continue;
newArray[j] = stringArray[i];
j++;
}
return newArray;
}
You use it like that : columns = RemoveAt(columns, MY_INT_HERE)
You can also make it to an extension method.
You cannot delete items in an array, because the length of a C# array is fixed at the time when it is created, and cannot be changed after that.
You can null out the corresponding element to get rid of the string, or use LINQ to produce a new array, like this:
columns = columns.Take(MY_INT_HERE-1).Concat(columns.Skip(MY_INT_HERE)).ToArray();
You need to add using System.Linq at the top of your C# file in order for this to compile.
However, using a List<string> would be a better solution:
List<string> columns;
columns.RemoveAt(MY_INT_HERE);
Try one of the following (depending on what you need):
columns[MY_INT_HERE] = null;
columns[MY_INT_HERE] = string.Empty;
...otherwise you'll just have to create a new array which has a length of 1 less than your current array, and copy the values over.
If you want something more flexible, you might use a something like a List<string>, where you can use RemoveAt()
Arrays are faster for the computer to work with but slower for a programmer. You will have to find that value with a loop or some other means, then set that position to null. You will end up with an empty space in the array. You could reallocate the array etc etc...
What is easier to use for relatively small amounts of data is a List. You can do myList.RemoveAt(100); and it will work nicely.
You can not delete it.You can recreate the array or I advice you to use List<string> for the same.
List<string> columns = new List<string>();
columns.RemoveAt(1);
It will remove the 2nd element from your List<String> columns

How add an item to a member of List<> array? [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 8 years ago.
How can i add an item to a member of List<> array?
please see the example below :
List<string>[] array_of_lists = new List<string>[10];
array_of_lists[1].Add("some text here");
but a have the error below :
Object reference not set to an instance of an object.
what this error mean and how can i fix it?
You have initialized the array, but all elements are null yet. If you want to initialize it with a List<String> at a given index you can't use Add which is a method of List<T>.
In this way you initalize the array at the second element:
array_of_lists[1] = new List<string>{"some text here"};
Note also that indices start with 0, not 1.
Here's a demonstration.
After so many edits, changes and commented answers I´d like to give a complete solution for you:
List<string>[] array_of_lists = new List<string>[10];
for (int i = 0; i < array_of_lists.Length; i++) {
array_of_lists[i] = new List<string>();
array_of_lists[i].Add("some text here");
array_of_lists[i].Add("some other text here");
array_of_lists[i].Add("and so on");
}
problem is that when you initialize an array, it is created with default values of items. For most of the value types (int, float, vs... ) default value will be 0. for reference types (strings and nullable and List and many other) default value will be null.
so your code should be like this
List<string>[] list_lines_link_scanner_ar = new List<string>[int.Parse(txt_ParaCount_In_LinkScanner.Text)];
// this is the line -->
list_lines_link_scanner_ar[1] = new new List<string>();
// <----
list_lines_link_scanner_ar[1].Add("some text here");
I think you mixed List<T> and arrays.
From MSDN
The List<T> class is the generic equivalent of the ArrayList class. It
implements the IList<T> generic interface using an array whose size is
dynamically increased as required.
So, easyly you can write,
List<string> array_of_lists = new List<string>();
array_of_lists.Add("some text here");
Declare:
List<List<string>> listOfList = new List<List<string>>();
Add:
listOfList.Add(new List<string> { "s1", "s2", "s3" });
unless you really need an array.

How do I initialize an empty array in C#?

Is it possible to create an empty array without specifying the size?
For example, I created:
String[] a = new String[5];
Can we create the above string array without the size?
If you are going to use a collection that you don't know the size of in advance, there are better options than arrays.
Use a List<string> instead - it will allow you to add as many items as you need and if you need to return an array, call ToArray() on the variable.
var listOfStrings = new List<string>();
// do stuff...
string[] arrayOfStrings = listOfStrings.ToArray();
If you must create an empty array you can do this:
string[] emptyStringArray = new string[0];
In .NET 4.6 the preferred way is to use a new method, Array.Empty:
String[] a = Array.Empty<string>();
The implementation is succinct, using how static members in generic classes behave in .Net:
public static T[] Empty<T>()
{
return EmptyArray<T>.Value;
}
// Useful in number of places that return an empty byte array to avoid
// unnecessary memory allocation.
internal static class EmptyArray<T>
{
public static readonly T[] Value = new T[0];
}
(code contract related code removed for clarity)
See also:
Array.Empty source code on Reference Source
Introduction to Array.Empty<T>()
Marc Gravell - Allocaction, Allocation, Allocation - my favorite post on tiny hidden allocations.
Try this:
string[] a = new string[] { };
You could inititialize it with a size of 0, but you will have to reinitialize it, when you know what the size is, as you cannot append to the array.
string[] a = new string[0];
There is not much point in declaring an array without size. An array is about size. When you declare an array of specific size, you specify the fixed number of slots available in a collection that can hold things, and accordingly memory is allocated. To add something to it, you will need to anyway reinitialize the existing array (even if you're resizing the array, see this thread). One of the rare cases where you would want to initialise an empty array would be to pass array as an argument.
If you want to define a collection when you do not know what size it could be of possibly, array is not your choice, but something like a List<T> or similar.
That said, the only way to declare an array without specifying size is to have an empty array of size 0. hemant and Alex Dn provides two ways. Another simpler alternative is to just:
string[] a = { };
[The elements inside the bracket should be implicitly convertible to type defined, for instance, string[] a = { "a", "b" };]
Or yet another:
var a = Enumerable.Empty<string>().ToArray();
Here is a more declarative way:
public static class Array<T>
{
public static T[] Empty()
{
return Empty(0);
}
public static T[] Empty(int size)
{
return new T[size];
}
}
Now you can call:
var a = Array<string>.Empty();
//or
var a = Array<string>.Empty(5);
string[] a = new string[0];
or short notation:
string[] a = { };
The preferred way now is:
var a = Array.Empty<string>();
I have written a short regular expression that you can use in Visual Studio if you want to replace zero-length allocations e.g. new string[0].
Use Find (search) in Visual Studio with Regular Expression option turned on:
new[ ][a-zA-Z0-9]+\[0\]
Now Find All or F3 (Find Next) and replace all with Array.Empty<…>() !
Simple and elegant!
string[] array = {}
You can define array size at runtime.
This will allow you to do whatever to dynamically compute the array's size. But, once defined the size is immutable.
Array a = Array.CreateInstance(typeof(string), 5);
I had tried:
string[] sample = new string[0];
But I could only insert one string into it, and then I got an exceptionOutOfBound error, so I just simply put a size for it, like
string[] sample = new string[100];
Or another way that work for me:
List<string> sample = new List<string>();
Assigning Value for list:
sample.Add(your input);
As I know you can't make array without size, but you can use
List<string> l = new List<string>()
and then l.ToArray().
Performance Rule CA1825: Avoid allocating zero-length arrays.
Rule discription:
Initializing a zero-length array leads to an unnecessary memory allocation. Instead, use the statically allocated empty array instance by calling the Array.Empty method.
In your case:
var a = Array.Empty<string>();
Combining #nawfal & #Kobi suggestions:
namespace Extensions
{
/// <summary> Useful in number of places that return an empty byte array to avoid unnecessary memory allocation. </summary>
public static class Array<T>
{
public static readonly T[] Empty = new T[0];
}
}
Usage example:
Array<string>.Empty
UPDATE 2019-05-14
(credits to #Jaider ty)
Better use .Net API:
public static T[] Empty<T> ();
https://learn.microsoft.com/en-us/dotnet/api/system.array.empty?view=netframework-4.8
Applies to:
.NET Core: 3.0 Preview 5 2.2 2.1 2.0 1.1 1.0
.NET Framework: 4.8 4.7.2 4.7.1 4.7 4.6.2 4.6.1 4.6
.NET Standard: 2.1 Preview 2.0 1.6 1.5 1.4 1.3
...
HTH
you can use the Array.Empty method (in .Net Core, at least)
string ToCsv(int[] myArr = null) { // null by default
// affect an empty array if the myArr is null
myArr ??= Array.Empty<int>();
//... do stuff
string csv = string.Join(",", myArr);
return csv;
}
You can do:
string[] a = { String.Empty };
Note: OP meant not having to specify a size, not make an array sizeless
Here is a real world example. In this it is necessary to initialize the array foundFiles first to zero length.
(As emphasized in other answers: This initializes not an element and especially not an element with index zero because that would mean the array had length 1. The array has zero length after this line!).
If the part = string[0] is omitted, there is a compiler error!
This is because of the catch block without rethrow. The C# compiler recognizes the code path, that the function Directory.GetFiles() can throw an Exception, so that the array could be uninitialized.
Before anyone says, not rethrowing the exception would be bad error handling: This is not true. Error handling has to fit the requirements.
In this case it is assumed that the program should continue in case of a directory which cannot be read, and not break- the best example is a function traversing through a directory structure. Here the error handling is just logging it. Of course this could be done better, e.g. collecting all directories with failed GetFiles(Dir) calls in a list, but this will lead too far here.
It is enough to state that avoiding throw is a valid scenario, and so the array has to be initialized to length zero. It would be enough to do this in the catch block, but this would be bad style.
The call to GetFiles(Dir) resizes the array.
string[] foundFiles= new string[0];
string dir = #"c:\";
try
{
foundFiles = Directory.GetFiles(dir); // Remark; Array is resized from length zero
}
// Please add appropriate Exception handling yourself
catch (IOException)
{
Console.WriteLine("Log: Warning! IOException while reading directory: " + dir);
// throw; // This would throw Exception to caller and avoid compiler error
}
foreach (string filename in foundFiles)
Console.WriteLine("Filename: " + filename);

Categories

Resources