Search code examples
c#.net-corefunc

Debugging a func inside a static comparer class


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?


Solution

  • 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