Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get string representing the expression used as function argument in C#

I'm developing for Unity3D using C#, and decided it would be useful to have an assert function. (In Unity3D, System.Diagnostics.Debug.Assert exists, but does nothing.)

As a developer that works primarily in C++, I'm used to assert messages that contain the asserted expression by way of the preprocessor stringizing operator. That is, given a failed assertion of the form ASSERT(x > 0, "x should not be zero."), the message displayed at runtime message can include the text "x > 0". I'd like to be able to do the same in C#.

I'm aware of ConditionalAttribute and DebuggerHiddenAttribute, and am using both (although the latter seems to be ignored by the custom build of MonoDevelop bundled with Unity). While searching for a solution to this problem, I came across three attributes in the System.Runtime.CompilerServices namespace that seem related to what I'm trying to do: CallerFilePathAttribute, CallerLineNumberAttribute, and CallerMemberNameAttribute. (In my implementation, I use System.Diagnostics.StackTrace with fNeedFileInfo == true instead.)

I'm wondering if there is perhaps any reflection magic (seems unlikely) or attribute magic (seems slightly more likely) that can help me achieve the same functionality as I'm used to in C++.

like image 424
Neverender Avatar asked Feb 28 '13 22:02

Neverender


1 Answers

If you pass an expression you can get close to the x > 0 you want:

[Conditional("DEBUG")]
public static void Assert(Expression<Func<bool>> assertion, string message, [CallerMemberName] string memberName = "", [CallerFilePath] string sourceFilePath = "", [CallerLineNumber] int sourceLineNumber = 0)
{
    bool condition = assertion.Compile()();
    if (!condition)
    {
        string errorMssage = string.Format("Failed assertion in {0} in file {1} line {2}: {3}", memberName, sourceFilePath, sourceLineNumber, assertion.Body.ToString());
        throw new AssertionException(message);
    }
}

You then need to call it like:

Assert(() => x > 0, "x should be greater than 0");
like image 82
Lee Avatar answered Oct 20 '22 04:10

Lee