Reputation: 4473
Logging is taking resources. Especially to create log messages. To save runtime resources I do this:
if (logFile!=null) Log(logFile, "Some Message "+someMethod());
It eliminates calling someMethod when logging is not required.
Is there more convenient way to code it? Like
Logger.logger?.Log("Some Message "+someMethod());
Logger is static class and logger is delegate... Unfortunately it doesn't work in my VS2012.
Update: Main purpose of this question is how to simplify code look and feel and reduce runtime spending. In my original approach method someMethod() is not called if logging is not necessary, but code stays the same. Checking for null is only suggested approach to avoid calling extra methods.
Update2: Some example:
public class Example {
public class Logger
{
public static void Log(string message)
{
Console.WriteLine(message);
}
}
public static Logger logger;
public static void Test()
{
// has compilation error "Invalid expression term '.'
logger?.Log("This "+"should "+"be "+"not invoked");
logger = new Logger();
logger?.Log("This should "+"be logged");
}
}
Upvotes: 2
Views: 2276
Reputation:
Could you wrap the null check inside the static class? You don't have to call the delegate directly.
e.g.
public class Logger
{
public Action<string> LogAction { get;set; }
public void Log(string message)
{
var logAction = LogAction;
if(logAction != null)
logAction(message);
}
}
Which would then be simply called as:
Logger.Log("Something happened");
Another option is using the Conditional
attribute.
https://msdn.microsoft.com/en-us/library/system.diagnostics.conditionalattribute(v=vs.110).aspx
Methods marked with that attribute will not be called in the compiled IL unless a compilation symbol is provided during the build.
public static class Logger
{
public static Action<string> LogAction { get;set; }
[Conditional("LoggingEnabled")]
public static void LogConditional(string message)
{
var logAction = LogAction;
if(logAction != null)
logAction(message);
}
public static void Log(string message)
{
var logAction = LogAction;
if(logAction != null)
logAction(message);
}
}
The Log method doesn't have the conditional attribute so the following code produces the following IL:
var foo = "foo";
var bar = "bar";
Logger.Log(foo + bar);
IL_0000: nop
IL_0001: ldstr "foo"
IL_0006: stloc.0 // foo
IL_0007: ldstr "bar"
IL_000C: stloc.1 // bar
IL_000D: ldloc.0 // foo
IL_000E: ldloc.1 // bar
IL_000F: call System.String.Concat
IL_0014: call UserQuery+Logger.Log
IL_0019: nop
IL_001A: ret
The LogConditional method does have the conditional attribute, and the compiler symbol has not been set so the following code produces the following IL:
var foo = "foo";
var bar = "bar";
Logger.LogConditional(foo + bar);
IL_0000: nop
IL_0001: ldstr "foo"
IL_0006: stloc.0 // foo
IL_0007: ldstr "bar"
IL_000C: stloc.1 // bar
IL_000D: ret
As you can see the string concatination is never performed because the method call isn't generated.
Upvotes: 3