Version Used:
Microsoft Visual Studio Enterprise 2017 RC
Version 15.0.26014.0 D15REL
Microsoft .NET Framework
Version 4.6.01055
Steps to Reproduce:
Run the following app:
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp2017
{
class Program
{
class A
{
}
static void Main(string[] args)
{
var dummy = new List<int>();
switch((object)new A())
{
case A a:
{
dummy.Any(x => a != null);
}
break;
}
}
}
}
Expected Behavior:
App just runs, no output.
Actual Behavior:
Null-reference on the switch statement, when trying to initialize not created instance of a hidden class <>c__DisplayClass27_0 CS$<>8__locals0;
Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object.
at ConsoleApp2017.Program.Main(String[] args) in D:\Temp\ConsoleApp2017\ConsoleApp2017\Program.cs:line 16
@gafter, why are these display classes even being used. I wasn't expecting any extra allocations when using pattern matching.
There's a lambda that captures the pattern variable.
Doh!
But it seems related to that.
In my case I was able to work around the problem by extracting the code in the cases to other methods.
Another workaround is simply assigning the pattern variable to another temp one. Change this:
class C { public int A; }
class Program
{
static void Main(string[] args)
{
switch (new C())
{
case C c:
Func<bool> f = () => c.A > 10;
break;
default:
break;
}
}
}
to this:
class C { public int A; }
class Program
{
static void Main(string[] args)
{
switch (new C())
{
case C c:
var rcWorkaround = c;
Func<bool> f = () => rcWorkaround.A > 10;
break;
default:
break;
}
}
}
@AlekseyTs Is working on making an LDM-approved change so that the extent of a case-block scoped expression variable will be the switch block. That should fix this issue as a side-effect. Leaving it open until we can verify that.
@AlekseyTs Is working on making an LDM-approved change so that the extent of a case-block scoped expression variable will be the switch block. That should fix this issue as a side-effect. Leaving it open until we can verify that.
Say what?
The extent. Not the scope. It gives the variable a place to live that doesn't have lifetime concerns as switch cases get entered/exited.
The variable will still be scoped such that it can only be legally referenced inside the appropriate switch-section.
Tracked by VSO https://devdiv.visualstudio.com/DevDiv/_workitems?id=369824
Most helpful comment
The extent. Not the scope. It gives the variable a place to live that doesn't have lifetime concerns as switch cases get entered/exited.
The variable will still be scoped such that it can only be legally referenced inside the appropriate switch-section.