Is there a shorter way to print out a variable name and its value in C#? What i do now is:
int myvar = 42;
Console.WritelLine($"{nameof(myvar)}={myvar}"); // or any other log function
//myvar=42
(I have been using Python a lot lately and really like pythons f"{myvar=}"
, which does exactly that.)
Thanks for your help
Yes-and-No.
No, you can't capture local variable names as simply as how Python does it.
...but it is possible by using a helper method with CallerArgumentExpression
- this does require C# 10.0 and .NET 6+ - you also need to add [assembly: EnableCallerArgumentExpression]
in your AssemblyInfo.cs
.
Like so:
public static class MyExtensions
{
public static String Dump<T>( this T value, [CallerArgumentExpression(nameof(value))] String? name = null )
{
String valueAsText;
if( value == null )
{
valueAsText = "null";
}
else if( value is IEnumerable e ) // Can't use IEnumerable<T> (unless you use MethodInfo.MakeGenericMethod, which is overkill)
{
valueAsText = "{ " + e.Cast<Object?>().Select( i => i?.ToString() ).StringJoin() + " }";
}
else
{
valueAsText = '"' + value.ToString() + '"';
}
name = name ?? "(Unnamed expression)";
return name + " := " + valueAsText;
}
public static String StringJoin( this IEnumerable<String?> collection, String separator = ", " )
{
return String.Join( separator: separator, collection.Select( s => s is null ? "null" : ( '"' + s + '"' ) ) );
}
}
The Dump<T>
method above is generic (over T
) instead of using this Object? value
to avoid unnecessary boxing of value
when T
is a value-type.
Used like so:
int myvar = 42;
Console.WriteLine( myvar.Dump() );
// myvar := "42"
Int32?[] arr = new[] { 1, 2, 3, (Int32?)null, 5 };
Console.WriteLine( arr.Dump2() );
// arr := { "1", "2", "3", null, "5" }
Screenshot proof:
(I had to name it Dump2
in the above screenshot because Dump
is already defined by Linqpad).