简体   繁体   中英

How to handle Index out of range in a better way

My code was giving me Index out of Range exception for a certain input. Below is the problematic code:

string[] snippetElements = magic_string.Split('^');

string a = snippetElements[10] == null ? "" : "hello";
string b = snippetElements[11] == null ? "" : "world";

For that particular input, array snippetElements had only one element in it, hence while trying to index 10th and 11th element, I got the exception.

For now, I have introduced the following check:

if (snippetElements.Length >= 11)
{
    string a = snippetElements[10] == null ? "" : "hello"; 
    string b = snippetElements[11] == null ? "" : "world";
}

Can someone suggest a better way to write this check. Somehow the number 11 is not looking good in the code.

Yes this is an old post, but still helpful. You could use this which I think is cleaner:

string a = snippetElements.ElementAtOrDefault(10) ?? "hello"; 
string b = snippetElements.ElementAtOrDefault(11) ?? "world";

Can someone suggest a better way to write this check. Somehow the number 11 is not looking good in the code.

Well you are accessing the element with 11 index, if you have that index in your variable then you can use that in your check, otherwise 11 is fine in your check. Your check should be if(index < snippetElements.Length)

Something like:

int index = 11;

if(index < snippetElements.Length)
{
   string b = snippetElements[index] == null ? "" : "world";
}

snippetElements[11] is the 12th element.

if (snippetElements.Length >= 12)

As long your are actually using the [10] and [11] indexes it doesn't look wrong to use the 12 in the if statement.

You can generalize the problem to an extension method like this:

public static class ArrayExtensions
{
    public static bool TryIndex<T>(this T[] array, int index, out T result)
    {
        index = Math.Abs(index);

        result = default(T);
        bool success = false;

        if (array != null && index < array.Length)
        {
            result = (T)array.GetValue(index);
            success = true;
        }

        return success;
    }
}

And convert your code to:

string[] snippetElements = magic_string.Split('^');

string a = null;
string b = null;

if (snippetElements.TryIndex(10, out a) && snippetElements.TryIndex(11, out b))
{
}

Or, more like your source code and using the TryIndex(...) extension method:

string[] snippetElements = magic_string.Split('^');

string a = null;
string b = null;

snippetElements.TryIndex(10, out a);
snippetElements.TryIndex(11, out b);

a = a ?? "hello"; // Null coalesence ?? operator is great!
b = b ?? "world";

It makes the array indexed access safer since your code won't never throw ArgumentOutOfRangeException .

Note that this extension method will work for any kind of array, regardless of its type! Either if its a value type (int, byte...) or a reference type (string, your own classes...).

The logic here is wrong.
If your Split method produces less than 12 elements your indexing on the array snippetElements could go only from zero to (Length - 1) of the array.

In that case there aren't elements at index 10 or 11. And, in any case, if the snippetElement.Lenght is equal or greater than 12, then the elements in the array can't be null. Or they contain a string or they will be empty strings.
You could just write

string a = snippetElements.Length >= 12 ? "hello" : string.Empty; 
string b = snippetElements.Length >= 12 ? "world" : string.Empty;

It might be late now, but for any one else who's having the same problem, that's how I solved it. I usually use this logic inside a for loop.

int index = 10;
string a = (index < snippetElements?.Length) ? snippetElements[index] : string.Empty; 

snippetElements?.Length checks if snippetElements is not empty then it calls its Length property. Accessing Length property of an empty array results in an exception. snippetElements[index] (you could replace this with "hello" as in your example) is accessed only if the index is in the bound of an array. Otherwise, it assigns String.Empty to a.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM