I'm doing some comparisons for certain thing between different instances of two objects. Since those comparisons are sequential (if comparison A == 0, we go to comparison B, if comparison B == 0 we go to comparison C, and so on until we return a -1 or a 1) and I didn't want to put a lot of ifs, I thought about doing this:
public static class TStatsComparer
{
public static int Compare(TStats? t1, TStats? other)
{
Func<TStats, TStats, int>[] comparisonRules = new Func<TStats, TStats, int>[]
{
(t1, t2) => CompareA(t1, t2),
(t1, t2) => CompareB(t1, t2),
(t1, t2) => CompareC(t1, t2),
(t1, t2) => CompareD(t1, t2),
(t1, t2) => CompareE(t1, t2),
};
int result = comparisonRules.Select(method => method(t1, other))
.FirstOrDefault(result => result != 0);
return result;
}
where CompareA
(or B, or C...) is a method like
static int CompareA(TStats? t1, TStats? other)
{
int result = 0;
// ...
// We do the comparison and store it in result
// result values could be 0,1 or -1
return result;
}
and the compared class
public class TStats : IComparable<TStats>
{
//...
public int CompareTo(TStats? other)
{
return TStatsComparer.Compare(this, other);
}
}
So it gets the first comparison that returns something different than 0 and returns that. It works as intended, but the thing here is that I can't debug it from Visual Studio. If I put a break point inside CompareA
method, for example, it says that
Your app has entered a break state, but no code is currently executing that is supported by the selected debug engine (e.g. only native runtime code is executing)
It still works, though, but that's it, I can't debug it.
If I remove the Func<>
thing and call the CompareA/B/C
methods directly and sequentially, I can debug it normally.
Am I doing something big of a mistake using the comparer like that?
Even if the func is executed in other thread or some sort of anonymous method, shouldn't I be able to debug the inside methods?
As a workaround, you could try collecting the comparison rules in a list rather than an array.
I.e. when implementing your code snippet, changing
var comparisonRules = new Func<TStats, TStats, int>[]
{
...
};
to
var comparisonRules = new List<Func<TStats, TStats, int>>
{
...
};
may allow the debugger to hit the breakpoints inside the Compare*()
methods.
Doing this change worked for me in Visual Studio 22, Windows 11, targeting .NET 6.
Why you experience the debugging deviation, I really don't know.
An issue that looks very similar to your scenario was reported on GitHub in November 2021:
Debugger can't step into a function in a given situation with Linq #62232
The issue reporter claims that the issue occurs in VS Code and Visual Studio (2022) on Windows 10 when using .NET 6; whereas for .NET 5 and .NET Framework 4.8, the issue does not occur.
As of September 2023, the issue is still open.
The code snippet that is provided for recreation in is:
static void Main(string[] args)
{
var list = new[] { "1", "4", "h", "l1", "7" };
var parsedList = list.Select(item => DoSomething(item)).Where(item => item == 1).ToList();
}
public static int DoSomething<T>(T input)
{
return 1;
}
along with the following comment:
Just place a breakpoint in DoSomething and run.
VS Goes into break mode: ("Your app has entered a break state, but no code is currently executing that is supported by the selected debug engine (e.g. only native runtime code is executing).") - stepping seems still to work, no other error is shown
VS Code : the callstack shows: "Error processing stackTrace request. Unknown Error 0x80131c49" - and seems to be completely stuck