1

I am trying to make a 1d array of lists. I make it like this:

public static List<string>[] words = new List<string>[30];
public static List<string>[] hints = new List<string>[30];

And I call it like this:

foreach (string item in vars.directory)
        {
            reader2 = new StreamReader(item);
            while (reader2.Peek() > 0)
            {
                string line = reader2.ReadLine();
                if (line.StartsWith("#"))
                {
                    vars.words[counter].Add(line.Substring(1, line.Length - 1)); //here
                }
                else if (line.StartsWith("-"))
                {
                    vars.hints[counter].Add(line.Substring(1, line.Length - 1)); //another here
                }
                else if (line == "@end")
                {
                    counter++;
                }
            }
        }

I just wanted to add that vars is where I keep my public variables and that counter is indeed at 0 when the loop starts.

EDIT In my haste I forgot to add the question... oops...

Here it is: When I call the add function (or any another function for that matter) it returns a null reference exception. How can I fix this?

2

6 Answers 6

7

I assume you're crashing when attempting to call .Add on your array element. You need to initialize your arrays with valid objects.

for( Int32 i = 0; i < vars.words.Length; ++i )
  vars.words[i] = new List<string>();
for( Int32 i = 0; i < vars.hints.Length; ++i )
  vars.hints[i] = new List<string>();
Sign up to request clarification or add additional context in comments.

7 Comments

Since words and hints are arrays you should use the Length property instead of the Count method.
I always wondered about this, is there a "normal" way to initialize all the array at once ?
I put that in and I get: Operator '<' cannot be applied to operands of type 'int' and 'method group'. should I replace count with length?
@Oops: There is no direct syntax support, but you can get short-and-sweet syntax with Linq: List<int>[] lists = Enumerable.Range(0, 5).Select(i => new List<int>()).ToArray(); (formatting - I'd put each of those extra method calls on their own line)
@Adam8797, change vars.words.Count to vars.words.Length. Same for hints
|
6

Why not just make a List<List<string>>, but yes you can make an array of lists

Comments

2

Using a list of lists, as already recommended, would make you escape your problems, and it´s much more flexible and handy than your construction.

-> f.i. if the size of your data changes, you don´t have to change the list size, but the array

Comments

0

Here's a one-liner to initialize an array of lists of size 30:

    static List<string>[] lists = (from i in Enumerable.Range(0, 30)
                                   select new List<string>()).ToArray();

Comments

0

The problem is that array values are initialized to the default value, and the default value for reference types is null.

default(List<string>) returns null.

So, you'll need to re-initialize the objects in the array before you can access them, otherwise you will get a NullReferenceException.

One way to initialize all the objects in your array up front is to use this Linq statement:

const int sizeOfLists = 5;
List<string>[] lists = Enumerable.Range(0, sizeOfLists)
    .Select(i => new List<string>())
    .ToArray();

Another option is to initialize and add the sub-lists only when you need them, by using an outer List:

var lists = new List<List<string>>();
// ...
var aSubList = new List<string>();
lists.Add(aSubList);

This is particularly useful if you don't know the size of the outer set of lists up-front, and is still accessible by index.

(This was a comment before, but I made it an answer since many other answers got caught up in the solution and don't describe the problem)

Comments

0

You could initialize the lists right before you use them:

foreach (string item in vars.directory)
{
    reader2 = new StreamReader(item);
    while (reader2.Peek() > 0)
    {
        string line = reader2.ReadLine();
        // new code
        if (vars.words[counter] == null) vars.words[counter] = new List<string>();
        if (vars.hints[counter] == null) vars.hints[counter] = new List<string>();

        if (line.StartsWith("#"))
        {
            vars.words[counter].Add(line.Substring(1, line.Length - 1)); //here
        }
        else if (line.StartsWith("-"))
        {
            vars.hints[counter].Add(line.Substring(1, line.Length - 1)); //another here
        }
        else if (line == "@end")
        {
            counter++;
        }
    }
}

1 Comment

He may have more than a single word or hint to store in each list so each initializer would need to be run only when the element is null.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.