У меня есть параметр, определенный так: params object?[] values, и я не могу отправить null (т.е. я хотел бы иметь массив с одним null внутри).
Он работает без параметров.
Ошибка: Cannot convert null literal to non-nullable reference type.
public class Foo
{
private void DoesNotWork(params object?[] values)
{
}
private void DoesWork1(object? value)
{
}
private void DoesWork2(object?[] values)
{
}
public void Test()
{
DoesNotWork(null);
DoesWork1(null);
DoesWork2(new object?[] { null });
}
}
Я что-то не так делаю или компилятор накладывает какие-то ограничения?
P.S. Это также работает, если метод «DoesNotWork» из библиотеки, в которой не включено значение nullable, то есть он определен так: DoesNotWork(params object[] values), поэтому я могу отправить туда null.
П.П.С. Я обнаружил, что этот обходной путь также работает:
DoesNotWork((object?) null);.
П.П.П.С. DoesNotWork(null!); тоже работает
Я не вижу там ответа на свой вопрос или я что-то упускаю. Как видите, совершенно нормально отправлять значение null в параметр без «параметров». Итак, без параметров С# может привести к объекту значение null? видимо
Нет способа отличить передачу нулевого массива от массива с 1 нулевым значением? Когда вы ставите (object?)null, C# теперь может понять, что вы имели в виду object[]{ null }, а не (object?[])null
Ну, сам массив не обнуляемый, это только элементы массива. Итак, кажется, есть простой способ отличить? Кроме того, он работает, когда метод находится в библиотеке, которая игнорирует нули. т.е. компилятор может точно отличить, что это первый элемент массива объектов





object тип по умолчанию не обнуляемый.
Вы можете вызывать свои методы, например
DoesNotWork((object?)null);
В качестве альтернативы, если вы измените метод, например
private void DoesWork(params object[]? values)
{
}
Вы могли бы просто назвать это как DoesWork(null);
вы получаете сообщение об ошибке, поскольку единственный предоставленный параметр имеет значение null, компилятор отправит значение null вместо создания массива с предоставленными параметрами:
DoesNotWork(null); // creates no array
DoesNotWork((object?)null); // creates array with one null element
DoesNotWork(null, null); // create array with two null elements
если бы вы изменили подпись метода на:
void DoesNotWork(params object?[]? values)
тогда вы не получите предупреждение, или вы подавите предупреждение с помощью !, как вы это сделали
Я вижу, меня на самом деле обманули, заставив думать, что когда я использовал библиотечный метод, он действительно создал массив с одним нулевым элементом, хотя на самом деле это был «нулевой массив», который просто обрабатывался, чтобы сделать то же самое в библиотеке. Таким образом, выполнение object?[]? values действительно будет имитировать то же поведение, что и для object[] values без возможности обнуления. R# даже показывает, что когда я отправляю, например. (1) это params values, но (null) просто values.
Хотя теоретически С# мог бы различать, что «нуль» должен быть элементом массива (так же, как, например, 1), если сам массив не может быть нулевым.
Да, я думаю, что компилятор может определить, что массив не имеет значения NULL, а затем предоставить массив с одним нулевым элементом, но это не тот случай, когда ссылки, допускающие значение NULL, отключены, следовательно, это поведение по умолчанию imo.
Да, понятно, спасибо за хороший и разъясняющий ответ!
null рассматривается как необнуляемый ссылочный тип.
вы можете использовать оператор приведения с нулевым значением, чтобы явно указать, что нулевой литерал следует рассматривать как обнуляемый, например:
DoesNotWork((object?[])null).
public class Foo
{
private void DoesNotWork(params object?[] values)
{
}
private void DoesWork1(object? value)
{
}
private void DoesWork2(object?[] values)
{
}
public void Test()
{
DoesNotWork((object?[])null);
DoesWork1(null);
DoesWork2(new object?[] { null });
}
}
Отвечает ли это на ваш вопрос? Какой тип нулевого литерала?