I'm building up tooling for a piece of software and would like to be able save out the boolean expression in the source code that exists in a Debug.Assert (or Trace.Assert) call.
For example, if the program crashes with:
var x = -1;
Debug.Assert(x >= 0, "X must be non-negative", "some detail message");
I'd like to be able to get out the string "x >= 0" as well as the message and detail message.
I've looked into using a TraceListener, but TraceListener#Fail(string) and TraceListener#Fail(string, string) only can capture the message and detail message fields (which, in the case a developer does not include, leaves me with no easy way to report what went wrong).
I suppose it's possible to create a stack trace and read the particular line that failed and report that (assuming the source code is available), but this seems relatively fragile.
Thanks for your time!
You can use expressions to accomplish something rough:
public static class DebugEx
{
[Conditional("DEBUG")]
public static void Assert(Expression<Func<bool>> assertion, string message)
{
Debug.Assert(assertion.Compile()(), message, assertion.Body.ToString());
}
}
and use it like so:
var i = -1;
DebugEx.Assert(() => i > 0, "Message");
There are some down sides to this. The first is, you have to use a lambda, so that complicates the syntax a little bit. The second is since we are dynamically compiling things, there is a performance hit. Since this will only happen in Debug mode (hence the conditional), the performance loss won't be seen in Release mode.
Lastly, the output isn't pretty. It'll look something like this:
(value(WindowsFormsApplication1.Form1+<>c__DisplayClass0).i > 0)
There isn't a whole lot you can do about this. The reason this happens is because of the closure around i. This is actually accurate since that is what it gets compiled down into.
I had already started typing an answer when #vcsjones posted his answer, so I abandoned mine, but I see there are some parts of it that are still relevant. Primarily with regards to formatting the lambda expression into something readable, So I will merge his with that part of my intended answer.
It uses a number of regular expressions to format the assertion expression, so that in many cases it will look decent (i.e. close to what you typed).
For the example given in #vcsjones answer it will now look like this:
Assertion '(i > 0)' failed.
public static class DebugEx
{
private static readonly Dictionary<Regex, string> _replacements;
static DebugEx()
{
_replacements = new Dictionary<Regex,string>()
{
{new Regex("value\\([^)]*\\)\\."), string.Empty},
{new Regex("\\(\\)\\."), string.Empty},
{new Regex("\\(\\)\\ =>"), string.Empty},
{new Regex("Not"), "!"}
};
}
[Conditional("DEBUG")]
public static void Assert(Expression<Func<bool>> assertion, string message)
{
if (!assertion.Compile()())
Debug.Assert(false, message, FormatFailure(assertion));
}
private static string FormatFailure(Expression assertion)
{
return string.Format("Assertion '{0}' failed.", Normalize(assertion.ToString()));
}
private static string Normalize(string expression)
{
string result = expression;
foreach (var pattern in _replacements)
{
result = pattern.Key.Replace(result, pattern.Value);
}
return result.Trim();
}
}
Related
I was fiddling with compiled delegates and tried to call Serialize and Deserialize functions in the following class using compile delegates (don't mind the names). I had success in calling Serialize, but not Deserialize. The problem seem to be I don't seem to understand how to pass the string argument to the Func object in the following code. Does anyone know a fix to my code (and brain)?
public class SomeClass
{
public string SomeString { get; }
public SomeClass(string str)
{
SomeString = str;
}
public string Serialize()
{
return SomeString;
}
public SomeClass Deserialize(string str)
{
return new SomeClass(str + " - !!!!");
}
}
public class Program
{
private static class TypeSerializationCache<T>
{
public static readonly Func<T, string> Serialize;
public static readonly Func<string, T> DeserializeThatShouldBe;
public static readonly Func<T, string, T> DeserializeOriginalFixed;
static TypeSerializationCache()
{
const string SerializeFunctionToCall = "Serialize";
var serializeFuncParameterValue = Expression.Parameter(typeof(T), "serializeFuncParameterValue");
var serializeMethod = typeof(T).GetMethod(SerializeFunctionToCall, BindingFlags.Instance | BindingFlags.Public, null, new Type[] { }, null);
var serializeCall = serializeMethod != null ? (Expression)Expression.Call(serializeFuncParameterValue, serializeMethod) : Expression.Constant(default(T), typeof(T));
Serialize = Expression.Lambda<Func<T, string>>(serializeCall, serializeFuncParameterValue).Compile();
const string DeserializeCallFunction = "Deserialize";
var deserializeFuncParameterValue = Expression.Parameter(typeof(T), "DeserializeFuncParameterValue");
var deserializeMethod = typeof(T).GetMethod(DeserializeCallFunction, BindingFlags.Instance | BindingFlags.Public, null, new Type[] { typeof(string) }, null);
var deserializeArgument = Expression.Parameter(typeof(string), "deserializeArgument");
var deserializeCall = Expression.Call(deserializeFuncParameterValue, deserializeMethod, deserializeArgument);
DeserializeOriginalFixed = Expression.Lambda<Func<T, string, T>>(deserializeCall, deserializeFuncParameterValue, deserializeArgument).Compile();
//To my great dismay, the following throws.
DeserializeThatShouldBe = Expression.Lambda<Func<string, T>>(deserializeCall, deserializeFuncParameterValue, deserializeArgument).Compile();
}
}
public static void Main(string[] args)
{
var class11 = new SomeClass("XYZ");
var class12 = new SomeClass("123");
var class31 = TypeSerializationCache<SomeClass>.Serialize(class11);
var class32 = TypeSerializationCache<SomeClass>.Serialize(class12);
var class31d = TypeSerializationCache<SomeClass>.DeserializeOriginalFixed(class11, class31);
var class32d = TypeSerializationCache<SomeClass>.DeserializeThatShouldBe(class32);
}
<edit: I needed to come back (awake) and make this attempt to fix the number of parameters. Not quite what I was hoping for, ideally I'd like to use just the type parameter and the serialized string. Also, duck talk reminds me of bug talk. :)
Aanyway, I'm still in search of the root fix, not just band-aid...
<edit 2: Now, the root fix appears to be in my brain and to understand one needs an instance for an instance method, or a static method. I think I got my ducks lined up and counted for after a good shut-eyes. My thanks to Eric.
Does anyone know a fix to my code
Show a programmer where the bug is, they fix the bug. Teach the programmer how to find the bug, and they stop posting their buggy code for other people to debug for them, saving everyone time.
Obtain a rubber duck. Read this line out loud to the duck.
var deserializeFuncParameterValue = Expression.Parameter(typeof(T), "DeserializeFuncParameterValue");
Now read this line out loud to the duck.
Deserialize = Expression.Lambda<Func<string, T>>(deserializeCall, deserializeFuncParameterValue, deserializeArgument).Compile();
Now explain to the duck like the duck is completely ignorant of expression trees why it is that the code is correct. Since the code is not correct, you should be unable to do so. The specific point at which you are unable to do so is either the bug, or a point where there is correct code that you cannot justify. Either way, you've learned something about the code, and probably you've found the bug.
Hint: The error message is not wrong. If you need to, read the error message out loud to the duck as well.
(The original poster has neglected to post the error message, which is "Incorrect number of parameters supplied for lambda declaration".)
(and brain)?
Rubber duck debugging works because it does an end run around the part of your brain that is stopping you from finding the bug. Your brain wants to believe that the code you wrote is correct, and it is literally not allowing you to see the obvious problem. You read the code, your eyes glaze over a little bit, and it is "obviously correct". Well no, it is not.
Explaining it to the duck forces your brain to re-examine the incorrect assumptions that led you to believe that the wrong code was "obviously correct".
Note that it works for mechanical engineering problems and stuffed ducks too.
I created a library that handles database access. I recently added transaction handling; however, I came across a small issue. To outline this, I wrote this sample for demonstration purposes:
class Program
{
static void Main(string[] args)
{
String data = null;
DoAction(ref data, () =>
{
Console.WriteLine(data);
});
Console.ReadLine();
}
private static void DoAction(ref String data, Action action)
{
if (data == null)
data = "Initialized Data";
action();
}
}
I get "Access to modified closure" underline on the following code line for the 'data' variable:
Console.WriteLine(data);
I understand that the modification of the ref data variable can cause issues (e.g. when running foreach loops). However, in the following case, I don't see this to happen.
Here is another version with a loop changing the variable further - the output is as expected:
class Program
{
static void Main(string[] args)
{
String data = null;
for (var i = 0; i < 10; i++)
DoAction(ref data, () =>
{
Console.WriteLine(data);
});
Console.ReadLine();
}
private static void DoAction(ref String data, Action action)
{
if (data == null)
data = "Initialized Data";
else
data += "|";
action();
}
}
ReSharper offers me to create a local variable, but I explicitly want to use the created string from the DoAction() method. If I would accept ReSharpers approach, it actually would break the code. Is there any other way to solve this problem? I'd like to use this Action approach, but I don't want ReSharper to complain about it either (and possibly not disable ReSharpers inspection).
Any suggestions?
I would suggest avoid using a ref parameter for this in the first place - it seems needlessly complicated to me. I'd rewrite DoAction as:
static string DoAction(string data, Action<string> action)
{
data = data == null ? "Initialized Data" : data + "|";
action(data);
return data;
}
Then you can have:
data = DoAction(data, Console.WriteLine);
or if you want to use a lambda expression:
data = DoAction(data, txt => Console.WriteLine(txt));
You can make DoAction a void method if you don't actually need the result afterwards. (It's not clear why you need the result to be returned and a delegate to execute in DoAction, but presumably that makes more sense in your wider context.)
In case you feel certain that the warning is not appropriate, there is the InstantHandleAttribute which is documented as:
Tells code analysis engine if the parameter is completely handled
when the invoked method is on stack. If the parameter is a delegate,
indicates that delegate is executed while the method is executed.
If the parameter is an enumerable, indicates that it is enumerated
while the method is executed.
I think is exactly what you want.
You can get the attribute from the JetBrains.Annotations package or alternatively as copy-paste from ReSharper options.
Before tracing to a TraceSource, should the "Trace Level" be checked prior to issuing the trace itself?
var ts = new TraceSource("foo");
ts.Switch.Level = SourceLevels.Warning;
if (/* should there be a guard here? and if so, what? */) {
ts.TraceEvent(TraceEventType.Warning, 0, "bar");
}
While there is SourceSwitch.ShouldTrace(TraceEventType), the documentation indicates
Application code should not call this method; it is intended to be called only by methods in the TraceSource class.
It appears that pre-TraceSource model employed the TraceSwitch (not SourceSwitch) class which had various TraceXYZ methods (for this purpose?), but such appears to be not needed/used/mentioned with the TraceSource model.
(Having the guard outside the trace method affects evaluation of expressions used in/for the call - of course side-effects or computationally expensive operations in such are "bad" and "ill-advised", but I'd still like focus on the primary question.)
As per expensive trace parameters computation I came up with the following:
internal sealed class LazyToString
{
private readonly Func<object> valueGetter;
public LazyToString(Func<object> valueGetter)
{
this.valueGetter = valueGetter;
}
public override string ToString()
{
return this.valueGetter().ToString();
}
}
The usage would be
traceSource.TraceEvent(TraceEventType.Verbose, 0, "output: {0}", new LazyToString(() =>
{
// code here would be executed only when needed by TraceSource
// so it can contain some expensive computations
return "1";
}));
Any better idea?
I know that in NLog you generally just do the trace at whatever level you want and it will take care of whether or not the log level should be traced or not.
To me it looks like TraceSource works the same way.
So I would say "No" you probably shouldn't check.
Test it out by setting different trace levels and tracing messages at different levels and see what gets traced.
I think in terms of performance you are generally ok if you use the methods defined on the class:
Based on an example from: http://msdn.microsoft.com/en-us/library/sdzz33s6.aspx
This is good:
ts.TraceEvent(TraceEventType.Verbose, 3, "File {0} not found.", "test");
This would be bad:
string potentialErrorMessageToDisplay = string.Format( "File {0} not found.", "test" );
ts.TraceEvent(TraceEventType.Verbose, 3, potentialErrorMessageToDisplay );
In the first case the library probably avoids the call to string.Format if the error level won't be logged anyway. In the second case, string.Format is always called.
Are strings you provide to the message argument expensive? A constant or literal is pretty cheap. If that is the case, don't worry about it, use the trace switch/trace listener filters, etc to reduce the amoount of trace processed (and the perf cost of trace) (BTW, the default trace listener is very expensive, always clear the trace listeners before adding the ones you want)
System.Diagnostics doesn't have anything to make a inactive TraceSource invocation costless. Even if you use the listener filters, or set the trace switch to zero (turn it off) the TraceEvent will be invoked and the message string will be constructed.
Imagine that the trace string is expensive to calculate, for example, it iterates across all the rows in a dataset and dumps them to a string. That could take a not trivial number of milliseconds.
To get around this you can make the string building part wrapped in a function that has a conditional attribute to turn it off in release mode, or use wrapper method that takes a lambda expression or a Func that creates the string (and isn't executed when not needed)
Like #nexuzzz suggests, there could be situations where calculation of event parameter is expensive. Here is what I could think of.
Suggestions to developers would be: "If you don't have string argument readily available, use the lambda version of TraceInformation or TraceWarning.
public class TraceSourceLogger : ILogger
{
private TraceSource _traceSource;
public TraceSourceLogger(object that)
{
_traceSource = new TraceSource(that.GetType().Namespace);
}
public void TraceInformation(string message)
{
_traceSource.TraceInformation(message);
}
public void TraceWarning(string message)
{
_traceSource.TraceEvent(TraceEventType.Warning, 1, message);
}
public void TraceError(Exception ex)
{
_traceSource.TraceEvent(TraceEventType.Error, 2, ex.Message);
_traceSource.TraceData(TraceEventType.Error, 2, ex);
}
public void TraceInformation(Func<string> messageProvider)
{
if (_traceSource.Switch.ShouldTrace(TraceEventType.Information))
{
TraceInformation(messageProvider());
}
}
public void TraceWarning(Func<string> messageProvider)
{
if (_traceSource.Switch.ShouldTrace(TraceEventType.Warning))
{
TraceWarning(messageProvider());
}
}
}
I just started using C# this afternoon, so be a little gentle.
Currently I am working on a type of "template engine" where one of the callbacks needs to generate a globally unique ID. I am using delegates to manage the callbacks.
Currently the code looks like this (though I have also tried an anonymous function & returning NewGuid directly w/o a variable):
static string UID(List<string> p)
{
string s = Guid.NewGuid().ToString();
return s;
}
Which, when called directly, works fine. However if I try to call it via the delegate (added to a StringDictionary via addCallback("generate UID", new CallbackWrapper(UID))), the program will generate the same GUID regardless of how many times I duplicate it; even though calling the method directly both before & after the event occurs results in a unique ID as expected. I'v
No doubt it's just something simple I've missed, inevitably stemming from me being relatively inexperienced at C#.
Any help would be appreciated.
Thanks.
Well, I've now tried Dictionary with the same result.
CallbackWrapper is just the delegate, it's defined like this:
delegate string CallbackWrapper(List<string> parameters);
The remainder of the work is done in another class, which looks like this:
class TemplateParser
{
private Dictionary<string, CallbackWrapper> callbackMap;
public TemplateParser(string directivePrefix, string directiveSuffix)
{
...
callbackMap = new Dictionary<string,CallbackWrapper>();
}
public TemplateParser() : this("<!-- {", "} -->") {}
{
callbackMap.Add(name, callback);
}
public string parse(string filename)
{
...
string replacement =
callbackMap[directiveName](new List<string>(parameters.Split(new string[] { ";", " " }, StringSplitOptions.RemoveEmptyEntries));
...
}
}
I've stripped out the majority of the string handling code to save some space.
The issue is in your calling code, not in the code itself, nor in the delegate.
Using delegates here definitely works if called correctly.
Furthermore, your code can be slightly simplified:
static string UID(List<string> p)
{
return Guid.NewGuid().ToString();
}
(The variable is utterly redundant.)
use delegate.invoke
The difference between direct function call and delegate.invoke is here
http://social.msdn.microsoft.com/Forums/en/csharplanguage/thread/f629c34d-6523-433a-90b3-bb5d445c5587
StringDictionary will automatically cast your CallbackWrapper to a string, meaning it will only run once and store the output of CallbackWrapper.ToString(). This is probably not what you want.
Try using Dictionary<string, CallbackWrapper> instead.
Going from a lambda to an Expression is easy using a method call...
public void GimmeExpression(Expression<Func<T>> expression)
{
((MemberExpression)expression.Body).Member.Name; // "DoStuff"
}
public void SomewhereElse()
{
GimmeExpression(() => thing.DoStuff());
}
But I would like to turn the Func in to an expression, only in rare cases...
public void ContainTheDanger(Func<T> dangerousCall)
{
try
{
dangerousCall();
}
catch (Exception e)
{
// This next line does not work...
Expression<Func<T>> DangerousExpression = dangerousCall;
var nameOfDanger =
((MemberExpression)dangerousCall.Body).Member.Name;
throw new DangerContainer(
"Danger manifested while " + nameOfDanger, e);
}
}
public void SomewhereElse()
{
ContainTheDanger(() => thing.CrossTheStreams());
}
The line that does not work gives me the compile-time error Cannot implicitly convert type 'System.Func<T>' to 'System.Linq.Expressions.Expression<System.Func<T>>'. An explicit cast does not resolve the situation. Is there a facility to do this that I am overlooking?
Ooh, it's not easy at all. Func<T> represents a generic delegate and not an expression. If there's any way you could do so (due to optimizations and other things done by the compiler, some data might be thrown away, so it might be impossible to get the original expression back), it'd be disassembling the IL on the fly and inferring the expression (which is by no means easy). Treating lambda expressions as data (Expression<Func<T>>) is a magic done by the compiler (basically the compiler builds an expression tree in code instead of compiling it to IL).
Related fact
This is why languages that push lambdas to the extreme (like Lisp) are often easier to implement as interpreters. In those languages, code and data are essentially the same thing (even at run time), but our chip cannot understand that form of code, so we have to emulate such a machine by building an interpreter on top of it that understands it (the choice made by Lisp like languages) or sacrificing the power (code will no longer be exactly equal to data) to some extent (the choice made by C#). In C#, the compiler gives the illusion of treating code as data by allowing lambdas to be interpreted as code (Func<T>) and data (Expression<Func<T>>) at compile time.
private static Expression<Func<T, bool>> FuncToExpression<T>(Func<T, bool> f)
{
return x => f(x);
}
What you probably should do, is turn the method around. Take in an Expression>, and compile and run. If it fails, you already have the Expression to look into.
public void ContainTheDanger(Expression<Func<T>> dangerousCall)
{
try
{
dangerousCall().Compile().Invoke();;
}
catch (Exception e)
{
// This next line does not work...
var nameOfDanger =
((MemberExpression)dangerousCall.Body).Member.Name;
throw new DangerContainer(
"Danger manifested while " + nameOfDanger, e);
}
}
public void SomewhereElse()
{
ContainTheDanger(() => thing.CrossTheStreams());
}
Obviously you need to consider the performance implications of this, and determine if it is something that you really need to do.
If you sometimes need an expression and sometimes need a delegate, you have 2 options:
have different methods (1 for each)
always accept the Expression<...> version, and just .Compile().Invoke(...) it if you want a delegate. Obviously this has cost.
NJection.LambdaConverter is a library that converts a delegate to an expression
public class Program
{
private static void Main(string[] args) {
var lambda = Lambda.TransformMethodTo<Func<string, int>>()
.From(() => Parse)
.ToLambda();
}
public static int Parse(string value) {
return int.Parse(value)
}
}
You can go the other way via the .Compile() method however - not sure if this is useful for you:
public void ContainTheDanger<T>(Expression<Func<T>> dangerousCall)
{
try
{
var expr = dangerousCall.Compile();
expr.Invoke();
}
catch (Exception e)
{
Expression<Func<T>> DangerousExpression = dangerousCall;
var nameOfDanger = ((MethodCallExpression)dangerousCall.Body).Method.Name;
throw new DangerContainer("Danger manifested while " + nameOfDanger, e);
}
}
public void SomewhereElse()
{
var thing = new Thing();
ContainTheDanger(() => thing.CrossTheStreams());
}
Expression<Func<T>> ToExpression<T>(Func<T> call)
{
MethodCallExpression methodCall = call.Target == null
? Expression.Call(call.Method)
: Expression.Call(Expression.Constant(call.Target), call.Method);
return Expression.Lambda<Func<T>>(methodCall);
}
JB Evain from the Cecil Mono team is doing some progress to enable this
http://evain.net/blog/articles/2009/04/22/converting-delegates-to-expression-trees
Change
// This next line does not work...
Expression<Func<T>> DangerousExpression = dangerousCall;
To
// This next line works!
Expression<Func<T>> DangerousExpression = () => dangerousCall();