tags:

views:

182

answers:

4

Hi, Reading some article about singleton, I stopped at the point saying: "Do not allow to crate copy of existing instance". I realized that I do not know how would I do that! Could you tell me, please, how could I copy existing instance of class? And the second one: deserializaition. How it could be dangerous?

And for both - how to deny creating copies or deserialization? Thanks

+2  A: 

There are objects with something like a Clone or a Copy method. The idea behind it that it will take the current values of the object and make a new one. The defeats the purpose of a singleton object, because suddenly someone can create a second copy of it.

Another possible way of creating a copy of the object, would be to serialize the object and then de-serialize it to create another copy. So you probably want to mark the singleton object as not serializable.

Kevin
+2  A: 

Using serialization/deserialization, you could store the object somewhere and then restore it. That way, you will have two objects. Any changes made to the singleton in the meantime would not be reflected in your new copy.

Afterwards, when you now try to get/set something using the singleton object, you might change it in/get it from the one object or the other. Obviously that can cause all sorts of (sometimes very hard to debug) problems.

EDIT: To create a singleton in C#, see the explanation at http://www.yoda.arachsys.com/csharp/singleton.html

As for serialization: You have to explicitely enable it by including the SerializableAttribute. So simply don't mark your class with it. Note that there is no NonSerializableAttribute for classes, only for fields. It is used when you enabled serialization, but want to deny it for certain parts of the class.

EDIT2: To deny XML-serialization, you could implement IXmlSerializable on the class. Then simply either have empty implementations or throw exceptions from the member methods.

Daniel Rose
XmlSerialization is still possible.
galford13x
True. I thought about that. What you could do is implement IXmlSerializable and throw exceptions from the methods ReadXml and WriteXml. Although if someone actually tries to clone a singleton by using XML-serialization, they deserve to be spanked.
Daniel Rose
@Daniel: Ah yes that would be a way to prevent XmlSerialization. However, normally if a class implements an interface, it implies the support of that interface. Would you agree that singletons can and sometimes are intended to be Serialized (such as application settings)?
galford13x
Daniel Rose
A: 

As has already been mentioned:

You don't want to make a singleton serializable or copy/clone-able because then you can make more than one object, which defeats the purpose of the singleton.

To prevent serialization in c# is easy - don't mark the class as [Serializable]

To prevent copying/cloning of your singleton you could try changing it to a static class so that can't be instantiated (in the normal way) if that's practical. I'm not sure if the class is technically a singleton any more then.

Another way (probably better) is detailed in Item 13 of Bill Wagner's Effective C#. i.e. using a static constructor and making your singleton a read only property of your static class.

Example:

public class SingletonExample
{
    private static readonly SingletonExample singleInstance
    static SingletonExample()
    {
        singleInstance = new SingletonExample();
    }
    public static SingletonExample Instance
    {
        get { return singleInstance; }
    }
    private SingletonExample()
    {
    }
}
Matt Ellen
+1  A: 

There are a few things to look out for, like Kevin mentioned any sort of .Clone() or .Copy() methods. If your building the class your self, then be carful with the .MemberwiseClone() method as it will make shallow copies of the object.

As far as serialization. Preventing general serialization can be done by not tagging [SerializableAttribute()] to you class. I'm not sure there is a way to prevent XmlSerialzation, directly. But there are a few things you could do to prevent this if your building the class.

If you're building the class, and you do not provide a default constructor then the XmlDeserializer will not work as it uses the default constructor to rebuild the object. I belive this funcitonality has changed in 4.0 however, so you may want to look more into that. Using the [XmlIgnore] Attribute on yoru fields and properties will render the serialzation useless as well.

The important part here is that the person trying to do this understand it shouldn't be done, not that it can't. If someone really wants to do serialization/deserialization on your class, then you can't stop all avenues as he can implement his own serialzation/deserialization of your object. Also serialzation of singletons is sometimes intended such as the cases of application settings or custom settings. The intent is to inform somehow the person trying to serialize/deserialize not to do so.

galford13x