views:

20

answers:

1

Hello =)

I have implemented a singleton that works well...

(implemented like this example:

public sealed class Singleton
{
    static Singleton instance=null;
    static readonly object padlock = new object();

    Singleton()
    {
       //breakpoint
    }

    public static Singleton Instance
    {
        get
        {
            lock (padlock)
            {
                Console.WriteLine("test");
                if (instance==null)
                {
                    instance = new Singleton();
                }
                return instance;
            }
        }
    }
}

When the Debugger step through the constructor, the lock doesn't lock anymore. the output window shows test very, very, very often and then a stack overflow exception occurs.

I can't post the whole code, it's a very big example. With the following implementation, the error does not occur.

public sealed class Singleton
{
    static readonly Singleton instance=new Singleton();

    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit
    static Singleton()
    {
    }

    Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            return instance;
        }
    }
}

What's the problem? Without a break point the error doesn't exist in either implementations....

thanks.

michael

A: 

I found the problem, but did not understand it...

i have a tostring method, which is the problem (uses reflection)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Reflection;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            Singleton s = Singleton.Instance;
            Console.ReadLine();
        }
    }

    class Singleton
    {

        static Singleton instance = null;
        static readonly object padlock = new object();

        Singleton()
        {
        }

        public static Singleton Instance
        {
            get
            {
                    lock (padlock)
                    {
                        if (instance == null)
                        {
                            instance = new Singleton();
                        }
                    }
                return instance;
            }
        }
        public override String ToString()
        {
            StringBuilder str = new StringBuilder();
            object myObject = this;
            // werden nicht alle gewünscht Properties angezeigt, müssen ggf. die Bindingflags
            // in GetProperties umgesetzt werden http://msdn.microsoft.com/de-de/library/system.reflection.bindingflags%28VS.95%29.aspx
            foreach (PropertyInfo info in myObject.GetType().GetProperties())
            {
                if (info.CanRead)
                {
                    object o = info.GetValue(myObject, null);
                    if (o != null)
                    {
                        // mit typ: o.GetType()
                        str.Append(info.Name + "\t\t" + o.ToString() + Environment.NewLine);
                    }
                }
            }
            return str.ToString();
        }


    }
}
Michael