Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Is there an opposite to the null-forgiving operator?

This program generates compiler warning CS8620

Argument of type ‘IEnumerable<(string S1, string S2)>’ cannot be used
for parameter ‘e’ of type ‘IEnumerable<(string? s1, string? s2)>’ in
‘void Program.F(IEnumerable<(string? s1, string? s2)> e)’ due to
differences in the nullability of reference types.

But I’m not trying to pass off something that can be null as something that can’t, I’m doing the opposite! That should be perfectly fine!

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Is there some way I can tell the compiler, "look I know it can’t be null, just pretend that it can be"? An opposite to the null-forgiving operator? A null-condemning operator?!

namespace MyNamespace;

public static class Program
{
    public static void Main(string[] args)
    {
        var L = new [] {new C("S1", "S2")};
        F(L);
    }

    public class C
    {
        public string S1 { get; }
        public string S2 { get; }

        public C(string s1, string s2)
        {
            S1 = s1;
            S2 = s2;
        }
    }

    public static void F(IEnumerable<C> e)
        => F(e.Select(c => (c.S1, c.S2)));

    public static void F(IEnumerable<(string? s1, string? s2)> e)
    {}
}

>Solution :

But I’m not trying to pass off something that can be null as something that can’t, I’m doing the opposite! That should be perfectly fine!

It would be fine if the original collection cannot be modified through the IEnumerable .. but it can be. Consider this code, which yes, is a bit of a hack, that’s the point:

public static void Main(string[] args)
{
    var L = new[] { ("S1", "S2") };
    F(L);
    Console.WriteLine(String.Join(", ", L));
}

public static void F(IEnumerable<(string? s1, string? s2)> e)
{
    if (e is (string? s1, string? s2)[] array)
        array[0].s1 = null;
}

L is an array of tuples of regular strings (not string?). The body of the if in F is executed, and a null ends up in that tuple anyway. So the compiler warning about that call to F is not wrong.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading