Nullable Array и зачем они нам нужны - PullRequest
0 голосов
/ 02 января 2019

Я вижу код, подобный этому, и понимаю, что это делает массив обнуляемым, но я не понимаю, зачем он нам нужен, поскольку массивы относятся к типам ref, поэтому они уже обнуляются.

Итак, мой вопрос - почемуэто нам нужно?

private readonly decimal?[] _amounts = new decimal?[_count];

Ответы [ 4 ]

0 голосов
/ 02 января 2019

Стоит отметить, что из C # 8.0 вы можете иметь обнуляемый ссылочный тип : https://docs.microsoft.com/en-us/dotnet/csharp/tutorials/nullable-reference-types, поскольку C # 8.0 ссылочные типы не могут быть пустыми по умолчанию (если эта функция включена впроект).

но, как уже упоминали другие:

private readonly decimal?[] _amounts = new decimal?[_count];

означает, что элементы типа значения в массиве могут быть нулевыми.decimal является типом значения, и обычно вы не можете присвоить ему значение NULL, но если у вас есть decimal?, то вы можете.

С включенной функцией C # 8.0 и обнуляемыми ссылочными типами вы ДОЛЖНЫ иметь обнуляемый ссылочный тип (указано)явно), если вы хотите задавать им ноль.Вы можете объявить так:

private decimal?[]? _amounts;

Теперь это означает, что оба элемента в массиве могут быть нулевыми, а весь массив (переменная _amounts) может быть пустым.

Так что в общем вопросительный знак послетип значения элемента ? и до [] -> SomeValueType?[] означает, что элементы в массиве могут быть нулевыми.Начиная с C # 8.0 (с включенной функцией в проекте), вопросительный знак ? после типа массива SomeArrayType[] -> SomeArrayType[]? означает, что вы можете присвоить нулевую переменную, которая содержит ссылку на массив.

0 голосов
/ 02 января 2019

Спецификатор обнуляемый здесь относится не к самому массиву, а к его содержимому. Как вы правильно сказали, массив сам по себе является ссылочным типом, и поэтому всегда допускает использование нуля (по крайней мере, до C # 8).

Несколько примеров разницы:

decimal[] nonNullable = new decimal[2];
nonNullable[0] = 1;             //OK, a non null item
nonNullable[1] = null;          //Compile error: array doesn't accepts nulls
nonNullable = null;             //OK, set the array reference to null

decimal?[] nullable = new decimal?[2];
nullable[0] = 1;                //OK, a non null item
nullable[1] = null;             //OK, a null item (actually, a Nullable<decimal> instance)
nullable = null;                //OK, set the array reference to null
0 голосов
/ 02 января 2019

Существует разница между самим объектом массива и элементами массива.Когда вы используете decimal?[], вы объявляете массив, элементы которого имеют значения NULL decimal.Если бы вы использовали decimal[]? (я не уверен, что это правильный синтаксис, но только для пояснения, предположим, что это так), вы бы объявили переменную, которая может ссылаться на массив или не ссылаться ни на что.Последним является бесполезный случай, который вы описываете, потому что, как вы говорите (по крайней мере, в более старых версиях C #), все переменные массива являются ссылочными переменными, которые уже могут быть установлены на null.

Чтобы прояснить разницу, рассмотримкод, опубликованный Алехандро, а также этот код:

decimal[]? reallyNullable = null;

Array.Sort(reallyNullable); // ArgumentNullException -- there is no array here
Array.Sort(nullable); // OK, assuming null can be compared to decimal.

Причина, по которой последняя строка в порядке, заключается в том, что здесь действительно указан объект массива.Единственное, что имеет значение null, это некоторые значения в нем.

0 голосов
/ 02 января 2019

Объявление его как decimal?[] означает, что элементы, содержащиеся в массиве , могут быть null или отличными от NULL .

Не делая его обнуляемым , элементы, которые массив может хранить , не могут быть null.

Другими словами, decimal?[] читается как «массив обнуляемых десятичных знаков». ? относится к элементам, которые может содержать массив, а не к самому массиву, поскольку все массивы являются ссылочными типами.

...