Roslyn: Should warn for ?. in expression of foreach

Created on 9 Aug 2016  路  6Comments  路  Source: dotnet/roslyn

Theres no WAY to handle ?. operator with foreach.
It should emit compile warning or error.
it just thorws NullReferencedException when nullptr object in it(from GetEnumerator)

class Program
{
        class Foo
        {
            public Bar bar = null;
        }
        class Bar
        {
            public List<int> list = new List<int>(2);
        }
        static void Main(string[] args)
        {
            Foo foo = new Foo();
            //It creates ?. check assembly but doesn't handle. also try to send 
            // DWORD PTR[foo.bar] to GetEnumerator so it throws NullReferencedException(nullptr)
            foreach (int j in foo.bar?.list)
            {
                System.Console.WriteLine(j);
            }
        }
}
Area-Compilers Feature Request

Most helpful comment

I think a warning would be appropriate here. By using ?., you say that you _want_ to get null, but foreach won't be able to handle that. Though this would probably have to be a part of a warning wave (#1580).

All 6 comments

OR just tacitly handle foreach .? operator from CoreCLR(just passing object if nullptr(loop continue))

Are you saying that:

``` C#
static void Main(string[] args)
{
Foo foo = new Foo();
foreach (int j in foo.bar?.list)
{
System.Console.WriteLine(j);
}
}

Should translate to:

``` C#
static void Main(string[] args)
{
    Foo foo = new Foo();
    foreach (int j in foo.bar != null 
        ? foo.bar.list
        : Enumerable.Empty<int>().ToList())
    {
        System.Console.WriteLine(j);
    }
}

?. returns null for the expression instead of throwing a null reference exception. what do you expect the following to do?

``` C#
static void Main(string[] args)
{
Foo foo = new Foo();
foreach (int j in null as List)
{
System.Console.WriteLine(j);
}
}

`foreach` attempts to get the enumerator from the list.  If the expression is null, this will always throw a null reference exception.

A simple fix for this is the `??` operator

``` C#
static void Main(string[] args)
{
    Foo foo = new Foo();
    foreach (int j in foo.bar?.list ?? Enumerable.Empty<int>())
    {
        System.Console.WriteLine(j);
    }
}

I think a warning would be appropriate here. By using ?., you say that you _want_ to get null, but foreach won't be able to handle that. Though this would probably have to be a part of a warning wave (#1580).

@svick That is actually what I mean

This would probably automatically get picked up by #5032 as a possible dereference of a nullable reference type.

What if foreach actually could handle null? See #6563

Was this page helpful?
0 / 5 - 0 ratings