Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p><strong>Note:</strong> This is a complete rewrite of the original answer; the recommendation still stands, however.</p> <p>First: make sure you're not running under a debugger. For example, a watch window could touch your public static properties. This is one of the possible reasons the second example could behave differently from the first. It may sound silly, but you never know.</p> <p>Under .NET 4, your second example does work, and I'd honestly <em>expect</em> it to work under .NET 2 as well. As long as you don't touch the <code>Context.Log</code> property or <code>LogFactory.instance</code> field inadvertently. Yet, it looks terribly fragile.</p> <p>Also, strictly speaking, the <code>beforefieldinit</code> subtleties you're trying to use here can bite you in a multi-threaded application: the init of <code>LogFactory</code> does not need to run on the same thread as the setter of <code>Context.Log[Object]</code>. This means that when <code>LogFactory.instance</code> is initialized, on <em>that</em> thread <code>Context.LogObject</code> need not be set yet, while it is on another (such syncs can happen lazily). So it is <em>not</em> thread safe. You can try to fix this by making <code>Context.LogObject</code> <strong>volatile</strong>, that way the set is seen on all threads at once. But who knows what other race conditions we get into next.</p> <p>And after all the tricks, you're still left with the following rather unintuitive result:</p> <pre><code>Context.Log = value1; // OK Context.Log = value2; // IGNORED </code></pre> <p>You'd expect the second invocation of the setter to either work (<code>Context.Log == value2</code>) or to throw. Not to be silently ignored.</p> <p>You could also go for</p> <pre><code>public static class Context { private static BaseLogger LogObject; public static BaseLogger Log { get { return LogObject ?? LogFactory.instance; } set { LogObject = value; } } private class LogFactory { static LogFactory() {} internal static readonly BaseLogger instance = new BaseLogger(null, null, null); } } </code></pre> <p>Here the result <em>is</em> guaranteed, and lazy (in line with Jon Skeet's fifth singleton method). And it looks a lot cleaner IMHO.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload