Search code examples
c#visual-studiodebugginglambdapredicates

How to debug Predicates in C#/Visual Studio?


In debugging mode, if I hover over a predicate, what I see is just some type names and some non-understandable symbols. This makes it very difficult to debug a code, for example to know what predicate some variable is holding. I usually assign this predicates values using lambda expression. Is there any way to have some idea of what the predicates contain?

For example, if I have a Predicate<object> myPred variable or a List<Predicate<object>> predList variables, how can I debug what value myPred has or what predList contains at runtime?


Solution

  • [I haven't checked the C# IDE experience, but actually the VS2010 VB.NET experience.]

    Either use Expression as @BenVoigt suggests, or don't use anonymous lambdas for your predicates: (VB.NET answer: Use Functions named by you and specify them with the AddressOf operator.)

    C# answer is something like: declare explicit functions named by you and specify the function name when assigning the predicate.

    Here is my test VB.NET code that confirms at least one way of dynamically creating predicates can be named successfully. In the VB.NET IDE these are easily seen by name.

    Module Module1
    
    Sub Main()
        For i = 1 To 2
            'Dim p As Predicate(Of Object) = Function(o) (o Is Nothing)
            'Dim p As Predicate(Of Object) = AddressOf NamedPredicate
            Dim p As Predicate(Of Object) = GeneratePredicate(i)
            Dim q As Expressions.Expression(Of Predicate(Of Object)) = Function(o) (o IsNot Nothing)
            If p(q) Then Console.WriteLine((q.Compile)(p))
        Next
    End Sub
    Private Function NamedPredicate(ByVal o As Object) As Boolean
        Return (o Is Nothing)
    End Function
    Private Function GeneratePredicate(ByVal i As Integer) As Predicate(Of Object)
    
        Dim gp = New Reflection.Emit.DynamicMethod("DynPred" & i, GetType(Boolean), {GetType(Object)})
        Dim mb = gp.GetILGenerator
        mb.Emit(Reflection.Emit.OpCodes.Ldarg, 0)
        mb.Emit(Reflection.Emit.OpCodes.Ldnull)
        mb.Emit(Reflection.Emit.OpCodes.Ceq)
        If i = 2 Then
            mb.Emit(Reflection.Emit.OpCodes.Ldc_I4_0)
            mb.Emit(Reflection.Emit.OpCodes.Ceq)
        End If
        mb.Emit(Reflection.Emit.OpCodes.Ret)
        GeneratePredicate = DirectCast(gp.CreateDelegate(GetType(Predicate(Of Object))), Predicate(Of Object))
    End Function
    End Module