2

I have a singleton class that lazy creates its instance when a property is first called (property side effect).

namespace singletontest2
{
    using System.Diagnostics;
    using MySingleton = Singleton<MyClass>;

    public class MyClass
    {
        private int val = 42;

        public MyClass()
        {
        }
    }

    public static class Singleton<T> where T : new()
    {
        private static T t;

        public static bool IsNull
        {
            get
            {
                return t == null;
            }
        }

        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        public static T Instance
        {
            get
            {
                if (t == null)
                    t = new T();
                return t;
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var a = MySingleton.IsNull;
            var d = MySingleton.Instance;
        }
    }
}

If I place a break point in the Instance property getter and on the var d line, the t member will already be initialized when I step into the Instance getter.

If I move the break point from var d to the next line, the t is null when I debug into the Instance getter.

I was under the impression the DebuggerBrowsable attribute would prevent this but it seems to not make any difference.

HOWEVER, if I eliminate the using MySingleton = Singleton<MyClass>; above and call Singleton<MyClass>.Instance; instead of MySingleton.Instance;, then the member t is null when I enter the Instance getter regardless of DebuggerBrowsable which is what I want.

Why is the using directive enabling the debugger to evaluate that property before the code is actually executed?

cppguy
  • 3,611
  • 2
  • 21
  • 36
  • 1
    _"If I place a break point in the Instance property getter and on the var d line, the t member will already be initialized when I step into the Instance getter"_ -- I cannot reproduce your claimed behavior, with the code you've provided. The value of `t` is `null` when I step into the `Instance` getter. Since your example above has a `MainWindow` class, the code for which you failed to provide, it seems likely there is something else in your code, besides what you've shared, causing what you observe. Please fix the question so it includes a good [mcve] that reliably reproduces the problem. – Peter Duniho Aug 23 '17 at 00:41
  • (Note: I'm using VS2017) – Peter Duniho Aug 23 '17 at 00:42
  • The original example code was using a default WPF project with no other code. I changed the example to be a console app instead of a WPF project but I still see the same behavior as before. Perhaps it's a bug in VS 2015? – cppguy Aug 23 '17 at 00:46
  • Do you have a watch set on `MySingleton.Instance` in the Watch window? – lesscode Aug 23 '17 at 00:49
  • No, but it does show up in the Auto window unavoidably. – cppguy Aug 23 '17 at 00:50
  • Why are people voting to close this question? – cppguy Aug 23 '17 at 00:50
  • That'll do it, too. – lesscode Aug 23 '17 at 00:51
  • But removing the `using` directive eliminates the issue. The Auto window isn't completely to blame here. And that's not something I have control over. – cppguy Aug 23 '17 at 00:54
  • I think there are votes to close because it's technically not a programming question, but rather knowledge of a development tool, which to me is a bit nit-picky... – lesscode Aug 23 '17 at 00:54
  • 1
    @lesscode and also incorrect, since development tools are explicitly on-topic. Note there's only one close vote as yet, so I wouldn't worry about it. – Blorgbeard Aug 23 '17 at 00:55
  • Well, you can close it :-) (I didn't have it open when I first tried to reproduce, but a watch was able to repro it, and the Autos window is basically the same animal). – lesscode Aug 23 '17 at 00:56
  • I don't think telling every developer to close the Auto/Watch windows when debugging this code is a viable solution. – cppguy Aug 23 '17 at 00:58
  • Possible duplicate of https://stackoverflow.com/questions/1761668/how-to-avoid-triggering-properties-while-debugging – Peter Duniho Aug 23 '17 at 01:31
  • Possible duplicate of https://stackoverflow.com/questions/15925886/c-vs-2008-debugger-executing-property-code – Peter Duniho Aug 23 '17 at 01:32
  • @cppguy, What about this issue now? Is it related to the debugging settings like Iesscode's suggestion? – Jack Zhai Aug 28 '17 at 08:56
  • lesscode's suggestion of changing settings does not seem reasonable to me even if it does work. It would require all developers looking at this code forever to turn off a very valuable feature in the debugger. The problem is `[DebuggerBrowsable(DebuggerBrowsableState.Never)]` doesn't work when the `using` directive is used. That's a conflict between the language and the dev environment. The correct answer was unfortunately to not use a property and just add a method instead since the property had side effects. – cppguy Aug 28 '17 at 17:41
  • @cppguy, Do you mean that you have resolved this issue? – Jack Zhai Sep 01 '17 at 10:04
  • Not to my satisfaction no. I should be able to use the using directive and DebuggerBrowsable attribute together. I would rather not have to create a method instead of a property. I have worked around the issue but my question was not answered. – cppguy Sep 01 '17 at 16:45

1 Answers1

0

Turn off Tools->Options->Debugging->Enable property evaluation and other implicit function calls as advocated here: https://msdn.microsoft.com/en-us/library/0taedcee.aspx

lesscode
  • 6,221
  • 30
  • 58