Возвращает ноль, если элемент массива не существует - PullRequest
0 голосов
/ 25 сентября 2018

Существует ли простой способ получения значения 'null', если элемент массива не существует?

Например, в приведенном ниже коде sArray имеет 3 элемента и первые 3 вызова SomeMethod работа (печатает правда), однако 4-й звонок SomeMethod(sArray[3]); дает мне IndexOutOfRangeException.Есть ли способ сделать 4-й вызов 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);

^ Предпочел бы однострочное выражение

Ответы [ 5 ]

0 голосов
/ 25 сентября 2018

Массивы в C # имеют свойство .Length, которое вы можете проверить, прежде чем пытаться передать элемент от одного до SomeMethod, и типичный подход состоит в том, чтобы циклически проходить через каждый элемент массива, а не гадать, есть ли индексдопустимо:

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

Вы не сможете избежать IndexOutOfRangeException, если будете ссылаться на индекс в массиве, который не существует.


Однако, если выесли вам действительно нужен метод с таким типом функциональности, вы можете просто изменить существующий код, чтобы проверить, больше ли указанный индекс, чем длина массива.

Поскольку ваш массив является int[] (а не int?[]), все допустимые индексы будут иметь значение.Кроме того, мы можем использовать ?. для обработки случаев, когда сам массив может быть null:

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

Затем используется вместо передачи элемента массива с недопустимым индексом (который всегда выбрасывает* IndexOutOfRangeException), вы бы передавали сам массив и индекс отдельно:

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...");
}

Выход

enter image description here

0 голосов
/ 25 сентября 2018

в этом случае я предложу вам создать расширение где-нибудь в вашем коде, как это

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

, тогда вы можете сделать это

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

хорошо, это не одноЛинейное решение, я знаю, но это проще для программиста и компьютера.

0 голосов
/ 25 сентября 2018

Как насчет метода расширения?

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;
    }
}

Тогда вы можете написать:

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));
}
0 голосов
/ 25 сентября 2018

Существует метод Linq ElementAtOrDefault

Чтобы использовать его так, как вы хотите (возвращая null), вам потребуется изменить базовый тип вашего массива на nullable int:

    int?[] sArray = new int?[]{1,2,3};
    SomeMethod(sArray.ElementAtOrDefault(1000));
0 голосов
/ 25 сентября 2018
SomeMethod(sArray.Skip(3).Select(z => (int?)z).FirstOrDefault());

является рабочей заменой:

SomeMethod(sArray[3]);

Первый вызовет SomeMethod с null (в то время как последний вызовет исключение, если массив не имеет по крайней мере 4записи).

В Skip(3) значение 3 можно изменить на любой индекс, который вы хотите получить из массива.Select необходим для проецирования int в int?, поэтому FirstOrDefault возвращает либо 4-й элемент , либо null.

Если вы неЕсли вы не хотите использовать LINQ, вы можете использовать:

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

.

Или рассмотрите возможность использования:

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

для циклического прохождения до 4 элемента массива (он будет работать нормально, если их меньше 4 - он просто сделает меньше вызовов SomeMethod).

...