Description
When an exception is thrown inside a foreach loop that iterates over an IEnumerable<T> implemented with yield return, the stack trace points to the foreach line instead of the actual line that caused the exception. This only happens in Release builds; Debug builds report the correct line number.
Steps to Reproduce
- Create a new .NET 9 console application.
- Replace
Program.cs with the following code:
namespace TestNamespace
{
public class Program
{
public static void Main(string[] args)
{
StackDumpTest();
}
class HeroInfo
{
public string skill;
public HeroInfo(string s) { skill = s; }
}
static IEnumerable<HeroInfo> GetAllHeroes()
{
yield return new HeroInfo("1");
yield return new HeroInfo(null!); // deliberately null string
yield return new HeroInfo("2");
}
public static void StackDumpTest()
{
foreach (var heroInfo in GetAllHeroes())
{
Console.WriteLine(heroInfo.skill.Length); // this is line 27
}
}
}
}
- Build and run in Release mode (e.g.,
dotnet run -c Release).
- Observe the stack trace in the console output.
Expected Behavior
The NullReferenceException thrown because of heroInfo.skill.Length (where skill is null) should be reported at line 27 (the line inside the loop body where .Length is accessed).
Actual Behavior
The stack trace reports the exception at line 25 (the foreach line), which is misleading:
Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object.
at TestNamespace.Program.StackDumpTest() in E:\...\Program.cs:line 25
at TestNamespace.Program.Main(String[] args) in E:\...\Program.cs:line 7
Additional Information
- .NET Version: .NET 9.0 (Release build,
win-x64)
- OS: Windows (x64)
- This problem does not occur in Debug builds (where line 27 is correctly reported).
- The issue seems specific to the interaction between
yield return (iterator state machine) and PDB/sequence point information in release-optimized code.
Description
When an exception is thrown inside a
foreachloop that iterates over anIEnumerable<T>implemented withyield return, the stack trace points to theforeachline instead of the actual line that caused the exception. This only happens in Release builds; Debug builds report the correct line number.Steps to Reproduce
Program.cswith the following code:dotnet run -c Release).Expected Behavior
The
NullReferenceExceptionthrown because ofheroInfo.skill.Length(whereskillisnull) should be reported at line 27 (the line inside the loop body where.Lengthis accessed).Actual Behavior
The stack trace reports the exception at line 25 (the
foreachline), which is misleading:Additional Information
win-x64)yield return(iterator state machine) and PDB/sequence point information in release-optimized code.