Version Used:
2.3.1.61913 (0ce1a70)
Steps to Reproduce:
Compile this program in release and look at the IL:
using System.Threading.Tasks;
class Program
{
static void Main() { }
static async Task Method1(bool value)
{
int i = 42;
int j = i;
await Task.Yield();
}
static async Task Method2(bool value)
{
int i = 42;
if (value)
{
int j = i;
await Task.Yield();
}
else
{
await Task.Yield();
}
}
static async Task Method3(bool value)
{
int i = 42;
if (value)
{
await Task.Yield();
}
else
{
int j = i;
await Task.Yield();
}
}
}
Expected Behavior:
No Int32 value is lifted to the state machine for any of the async methods.
Actual Behavior:
In both Method1 and Method2, the compiler correct deduces that there's no need to lift i from being a local to a field:
Method1:
public int <>1__state;
public AsyncTaskMethodBuilder <>t__builder;
private YieldAwaitable.YieldAwaiter <>u__1;
Method2:
public int <>1__state;
public AsyncTaskMethodBuilder <>t__builder;
private YieldAwaitable.YieldAwaiter <>u__1;
public bool value;
but for Method3, it fails to realize this and promotes the i local to being a field, consuming unnecessary space on the state machine object when it's boxed to the heap:
Method3:
public int <>1__state;
public AsyncTaskMethodBuilder <>t__builder;
private YieldAwaitable.YieldAwaiter <>u__1;
private int <i>5__1;
public bool value;
Version Used:
2.3.1.61913 (0ce1a70)
Steps to Reproduce:
Compile this program in release and look at the IL:
Expected Behavior:
No Int32 value is lifted to the state machine for any of the async methods.
Actual Behavior:
In both Method1 and Method2, the compiler correct deduces that there's no need to lift
ifrom being a local to a field:but for Method3, it fails to realize this and promotes the
ilocal to being a field, consuming unnecessary space on the state machine object when it's boxed to the heap: