0

I have a parameter defined like that: params object?[] values and I cannot send null in (i.e. I would like to have an array with one null inside).

It does work without params.

The error is: 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 });
    }
}

Am I doing something wrong or is there is some limitation in compiler that does not allow this?

P.S. It does as well work if the method "DoesNotWork" is from the library that does not have nullable turned on, i.e. it is defined like this: DoesNotWork(params object[] values), so I can send null there.

P.P.S. I have found that this workaround works as well: DoesNotWork((object?) null);.

P.P.P.S. DoesNotWork(null!); works as well

Ilya Chernomordik
  • 27,817
  • 27
  • 121
  • 207
  • Does this answer your question? [What is the type of null literal?](https://stackoverflow.com/questions/8204578/what-is-the-type-of-null-literal) – phuzi May 03 '23 at 08:01
  • I do not see an answer to my question in there or I am missing something. As you can see it is totally fine to send null to a parameter without "params". So without params C# can cast null to object? apparently – Ilya Chernomordik May 03 '23 at 08:02
  • 1
    There's no way to differentiate between passing a null array or an array with 1 null value? When you put `(object?)null` C# can now figure out that you meant `object[]{ null }` and not `(object?[])null` – phuzi May 03 '23 at 08:07
  • Well, the array itself is not nullable, it is only the elements of the array that are. So it seems there is an easy way to differentiate? Additionally it DOES work when the method is in the library that ignores nulls. I.e. the compiler can differentiate just fine that this is a first element of an object array – Ilya Chernomordik May 03 '23 at 08:10

3 Answers3

4

you are getting the error since the single parameter provided is null, the compiler will send down null instead of creating an array with provided params:

DoesNotWork(null); // creates no array
DoesNotWork((object?)null); // creates array with one null element
DoesNotWork(null, null); // create array with two null elements

if you were to change the signature of the method to: void DoesNotWork(params object?[]? values) then you will not get the warning, or you suppress the warning with ! as you did

Florent Bunjaku
  • 268
  • 2
  • 7
  • I see, I was actually tricked into thinking that when I used the library method it did create an array with one null element while in reality it was a "null array" that was just handled to do the same in the library. So doing `object?[]? values` would indeed imitate the same behaviour as for not nullable enabled `object[] values`. R# even shows that when I send e.g. `(1)` it is `params values`, but (`null`) is just `values`. – Ilya Chernomordik May 03 '23 at 08:15
  • Though in theory C# could have differentiated that "null" should be an element of the array (same as e.g. `1` is) if the array itself is not nullable. – Ilya Chernomordik May 03 '23 at 08:17
  • Yep I think the compiler might be able to determine that array is not nullable and then provide an array with one null element, but this is not the case when nullable references are disabled, hence that is the default behavior imo. – Florent Bunjaku May 03 '23 at 08:22
  • 1
    Yes, it makes sense, thanks for a good and clarifying answer! – Ilya Chernomordik May 03 '23 at 08:23
0

object type is a non-nullable by default.

You can call your methods like

DoesNotWork((object?)null);

Alternatively if you change method like

private void DoesWork(params object[]? values)
{
}

You could just call it like DoesWork(null);

AVTUNEY
  • 923
  • 6
  • 11
0

null is being treated as a non-nullable reference type.

you can use a nullable cast operator to explicitly indicate that the null literal should be treated as nullable like this:

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 });
    }
}
Zen Of Kursat
  • 2,672
  • 1
  • 31
  • 47