The scenario is:
Log.Info(() => $"Some Text {SomeSlowMethod()}");
public static string SomeSlowMethod()
{
Thread.Sleep(5000);
return "Foo";
}
Now... What happens if the logging of Info
is disabled? Is the SomeSlowMethod
called? The answer is no! Because the calling of the delegate () => $"Some Text {SomeSlowMethod()}
is done by Log.Info()
if it needs to do it. Compare it with:
Log.Info($"Some Text {SomeSlowMethod()}");
Now SomeSlowMethod()
is always called, and there is the possibility that Log.Info
will ignore its value.
If you think that SomeSlowMethod()
s in real case scenarios don't exist, remember that even string composition is "slow" compared to other operations. Simply doing useless string.Format
($"Some Text {SomeVariableorProperty}
is a string.Format
) is a waste of time. And one of the laws of a good logging library is that if it isn't active it shouldn't slow your application.
To make an interesting comparison, Debug.Assert()
:
[Conditional("DEBUG")]
public static void Assert(bool condition, string message);
Here message
is a string
, but you see the [Conditional(...)]
? if DEBUG
isn't defined at compile time, the C# compiler can remove the whole Debug.Assert()
method call, and even remove all the methods that are called inside the Debug.Assert()
, so modifying possible side effects:
Debug.Assert(false, Throw());
public static string Throw()
{
throw new Exception();
}
If DEBUG
isn't defined (so you are executing a RELEASE
build), this will be converted to:
; // nothing
so no throw
(see for example this). But note that this must be resolved at compilation time, while logging libraries are configured at runtime.