Can't access my list

Hello, I have made a list but I can’t access it. I get out of range error, please take a look.
I’ve tried both with array or Element at, but get the same error, which is what C# forums suggest should be working…
Otherwise it works fine with foreach loop or other functions like .count etc… quite strange

            if (selectedEnemies[2] != null)
            {
                selectedEnemies[2].transform.localPosition = new Vector3(7.50f, 37.5f, 0);
            }

Or

            if (selectedEnemies.ElementAt(1).transform != null)
            {
                selectedEnemies.ElementAt(1).transform.localPosition = new Vector3(6, 41.5f, 0);
            }

Here is a short version of the code, which should be the essentials.

List<Collider2D> selectedEnemies = new List<Collider2D>();

                    // Check if the enemy collider is active and enabled
                    if (enemyCollider.isActiveAndEnabled)
                    {
                        selectedEnemies.Add(enemyCollider);
                    }

Well, what does the error tell you? We’re not clairvoyant.

All I can say is there is no ElementAt method in the List. Also it is likely there is no element at index 2 of your list if you’re seeing errors. I’m sure Kurt will drop by to explain to you how debugging works and how you can debug such issues for yourself.

In other words this is a minor mistake on your part, and you’re supposed to handle this by yourself, by making sure you understand what List does and how it is used. If there are some bad assumptions on your part, that’s normal, and we all basically probe and print information in our code to make sure everything up to that point behaves as expected.

For example, you can use Debug.Log(..) to dump out values to the console, or toggle calls on or off (by commenting them out with //), or return early from a function in order to infer where the problem might be.

Also it helps to read the textual portion of the error and understand what the system is trying to tell you.

1 Like

It was an out of range array error. But I fixed it, actually the way i was checking for null was wrong, apparently am not supposed to do it using array but a workaround like list.count etc.
Solved.

Let me help you differentiate between arrays and lists more properly.

Arrays are a system-wide low level data structures to let you have series of data of the same type. All arrays have Length property which determines their allocated size. You can think of them as a substitute for having to write a multitude of variables

int myInt0 = 5;
int myInt1 = 15;
int myInt2 = 2;
Debug.Log(myInt1);

turns into

int[] myInt = new int[] { 5, 15, 2 };
Debug.Log(myInt[1]);

Much more compact and versatile, especially as the series grow into hundreds of items.
Lists are similar, however, these are dedicated collections which solve some of the shortcomings of how arrays operate.

Here are some things you cannot do with arrays:

  • have a dynamic size of items during runtime
  • insert an item
  • remove an item

You may consider Lists being high-level representations of arrays with additional functionality.
Lists, being true collections, specify methods such as Add, Clear, Contains, and Remove.

Arrays only act like they implement interfaces IList, ICollection, and IEnumerable, for convenience, even though they don’t directly support Add or Remove, as an example. But they can still be accessed through indexers [n] and iterated over. This helps when you want to pass a compatible data structure as an argument, regardless of whether it’s a list or an array.

void myFunc(IList list) { ... }

var myArray = new int[15];
var myList = new List<int>();

myFunc(myArray);
myFunc(myList);

It’s worth noting that a List still expresses itself through arrays under the hood, because it simply allocates chunks of arrays and knows how to produce a continuity between them. This is something you can control with Capacity. By stating Capacity you can limit your list’s maximum size, but normally this is not required.

Where this knowledge pays off is when your list is supposed to dramatically change in size. Because it will allocate arrays in advance, a growing list will double in allocation size once it hits its internal limit. Then when you remove the items from it, the vacant arrays stay in place to prevent extra work, even if you now have just 2 items and the capacity was in thousands. You can use TrimExcess punctually to get rid of this unused memory allocation.

Observe that Length doesn’t make much sense in the context of lists, because they allocate much more dynamically, it’s not just a single series of data. Instead, lists provide their own counter, called Count. It comes from the ICollection interface and will work in the previous example as well.

void myFunc(IList list) {
  Debug.Log(list.Count);
}

var myArray = new int[15];
myFunc(myArray); // prints 15

This is weird right, why does this work? Well arrays get retrofitted with all these interfaces during runtime, and Count rewires to Length when arrays are used like this. This will not work however

var myArray = new int[15];
Debug.Log(myArray.Count); // error

Because the compiler runs before the runtime, it cannot make any sense of it.

All in all, use arrays when you need tight control over allocation, when you don’t need to change the length of data, or when you yourself are building a collection of your own. Use lists for everything else, namely for high level logic and user data.

And remember that every high level collection supplies Count. The only data structure that has Length is an array, this is a reflection of how fundamental it is for the whole system. It is not a workaround.

1 Like

Here are some notes on IndexOutOfRangeException and ArgumentOutOfRangeException:

http://plbm.com/?p=236

Steps to success:

  • find which collection it is and what line of code accesses it <— critical first step!)
  • find out why it has fewer items than you expect
  • fix whatever logic is making the indexing value exceed the collection size
  • remember that a collection with ZERO elements cannot be indexed at all: it is empty
  • remember you might have more than one instance of this script in your scene/prefab
  • remember the collection may be used in more than one location in the code
  • remember that indices start at ZERO (0) and go to the count / length minus 1.

This means with three (3) elements, they are numbered 0, 1, and 2 only.