简体   繁体   中英

Return null if array element does not exist

Is there a simple^ way of getting the value 'null' if an array element does not exist?

For example, in the code below sArray has 3 elements and the first 3 calls to SomeMethod work (prints true), however the 4th call SomeMethod(sArray[3]); gives me an IndexOutOfRangeException . Is there a way to make the 4th call to SomeMethod print false?

    static void Main(string[] args)
    {
        int[] sArray = new int[]{1,2,3};
        SomeMethod(sArray[0]);
        SomeMethod(sArray[1]);
        SomeMethod(sArray[2]);
        SomeMethod(sArray[3]);
    }
    static void SomeMethod(int? s) => Console.WriteLine(s.HasValue);

^Would prefer single line expression

How about an extension method?

public static T? TryGet<T>(this T[] source, int index) where T: struct
{
    if (0 <= index && index < source.Length)
    {
        return source[index];
    }
    else
    {
        return null;
    }
}

Then you could write:

static void Main(string[] args)
{
    int[] sArray = new int[]{1,2,3};
    SomeMethod(sArray.TryGet(0));
    SomeMethod(sArray.TryGet(1));
    SomeMethod(sArray.TryGet(2));
    SomeMethod(sArray.TryGet(3));
}

There is a Linq method ElementAtOrDefault

To use it the way you want to (returning null ) you will need ti change the underlying type of your array to nullable int:

    int?[] sArray = new int?[]{1,2,3};
    SomeMethod(sArray.ElementAtOrDefault(1000));
SomeMethod(sArray.Skip(3).Select(z => (int?)z).FirstOrDefault());

is a working replacement of:

SomeMethod(sArray[3]);

The former will call SomeMethod with null (while the latter will throw an exception if the array doesn't have at least 4 entries).

In Skip(3) the 3 can be changed to whatever index you want to retrieve from the array. The Select is needed to project the int into a int? so that FirstOrDefault returns either the 4th element or null .

If you don't want to use LINQ then you could use:

SomeMethod(sArray.Length > 3 ? sArray[3] : (int?)null);

instead.

Or consider using:

foreach (var entry in sArray.Take(4))
{
    SomeMethod(entry);
}

to loop through up to 4 elements of the array (it will work fine if there are fewer than 4 - it will just make fewer calls to SomeMethod ).

Arrays in C# have a .Length property which you can check before trying to pass an item from one to SomeMethod , and the typical approach is to loop through each element of the array rather than guessing whether or not an index is valid:

for (int i = 0; i < sArray.Length; i++) 
{
    SomeMethod(sArray[i]); 
}

You will not be able to avoid an IndexOutOfRangeException if you reference an index in an array that doesn't exist.


However, if you really want a method with this type of functionality, you could simply modify your existing code to check whether or not the index specified is greater than the length of the array.

Since your array is an int[] (and not an int?[] ), all valid indexes will have a value. Also, we can use the ?. to handle cases where the array itself may be null :

private static void SomeMethod(int[] array, int index) => 
    Console.WriteLine(index >= 0 && index < array?.Length);

Then in use, instead of passing an array item with an invalid index (which will always throw an IndexOutOfRangeException ), you would pass the array itself and the index separately:

static void Main()
{
    int[] sArray = new int[] { 1, 2, 3 };

    SomeMethod(sArray, 0);
    SomeMethod(sArray, 1);
    SomeMethod(sArray, 2);
    SomeMethod(sArray, 3);
    SomeMethod(null, 0);

    GetKeyFromUser("\nPress any key to exit...");
}

Output

在此处输入图片说明

in this case I'll suggest you to create a extension somewhere in your code like this

static class ArrExt
{
    public static int? Get(this int[] arr, int i)
    {
        return (i >= 0 && i < arr.Length) ? arr[i] : default(int?);
    }
}

then you can do this

int[] sArray = new int[] { 1, 2, 3 };
SomeMethod(sArray.Get(0));
SomeMethod(sArray.Get(1));
SomeMethod(sArray.Get(2));
SomeMethod(sArray.Get(3));

okay this is not a single line solution I know, but it's easier for both programmer and computer.

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