views:

2461

answers:

4

It seems like I can serialize classes that don't have that interface, so I am unclear on its purpose.

+3  A: 

With the ISerializable you can write custom methods in your object to take over serialization when doing binary serialization, to serialize your objects in a different manner than what the default approach used by BinaryFormatter will do.

In other words, if the default approach serializes your object in a different manner than how you want it to serialize as, you can implement ISerializable for complete control. Note that hand in hand with ISerializable, there's also a custom constructor you should implement.

XmlSerialization will of course only use properties, ISerializable has nothing to do with XML serialization.

Thanks Marc and Pop for the comments, I was a bit hasty with my first answer.

Lasse V. Karlsen
This answer is incorrect; ISerializable relates to BinaryFormatter; the "public with get/set" relates to XmlSerializer - the two are **very** different beasts, with completely different rules.
Marc Gravell
this is true only for XML serialization, binary serialization serializes the fields of an object (private or public) not the outside image of the object read through properties. This is where ISerializable is most useful.
Pop Catalin
+2  A: 

Classes can be serialized in .NET in one of two ways:

  1. Marking the class with SerializableAttribute and decorating all the fields that you don't want to be serialized with the NonSerialized attribute. (As Marc Gravell points out, BinaryFormatter, which is the class typically used to format ISerializable objects, automatically serializes all fields unless they are specifically marked otherwise.)
  2. Implementing the ISerializable interface for fully custom serialization.

The former is simpler to use as it simply involves marking declarations with attributes, but is limited in its power. The latter allows more flexibility but takes significantly more effort to implement. Which one you should use depends completely on the context.

Regarding the latter (ISerializable) and it usage, I've quoted from the MSDN page for the interface:

Any class that might be serialized must be marked with the SerializableAttribute. If a class needs to control its serialization process, it can implement the ISerializable interface. The Formatter calls the GetObjectData at serialization time and populates the supplied SerializationInfo with all the data required to represent the object. The Formatter creates a SerializationInfo with the type of the object in the graph. Objects that need to send proxies for themselves can use the FullTypeName and AssemblyName methods on SerializationInfo to change the transmitted information.

In the case of class inheritance, it is possible to serialize a class that derives from a base class that implements ISerializable. In this case, the derived class should call the base class implementation of GetObjectData inside its implementation of GetObjectData. Otherwise, the data from the base class will not be serialized.

Noldorin
Re point 1: BinaryFormatter (the main consumer of ISerializable) doesn't care about properties, and uses all fields by default (you need to opt out)
Marc Gravell
@Marc: Yeah, good point. I'll edit the post to correct that.
Noldorin
(I fixed the NonSerialized attribute name; hope you don't mind. I got it wrong in my original post, too... ;-p)
Marc Gravell
Of course, the third way to serialize classes is with the XML Serializer, and the fourth way is with the Data Contract Serializer.
John Saunders
@Marc: Of course not. :) As you can see, I'm a bit hazy on the attribute names regarding serialization. Your answer is more complete anyway, so meh.
Noldorin
+2  A: 

In order to make an object "transportable", you have to serialize it. For example, if you want to transfer object data using .NET Remoting or Web Services you have to provide methods which serializes your object data, reducing your object instances into a transportable format that represents a high-fidelity representation of the object.

You then may also take the serialized representation, transport it to another context such as a different machine, and rebuild your original object.

When implementing the ISerializable interface, a class must provide the GetObjectData method that is included in the interface, as well as a specialized constructor that is specialized to accept two parameters: an instance of SerializationInfo, and an instance of StreamingContext.

If your classes don't require fine-grained control of their object state, then you could just use [Serializable] attribute. Classes that require more control over the serialization process can implement the ISerializable interface.

splattne
+12  A: 

ISerializable is used to provide custom binary serialization, usually for BinaryFormatter (and perhaps for remoting purposes). Without it, it uses the fields, which can be:

  • inefficient; if there are fields that are only used for efficiency at runtime, but can be removed for serialization (for example, a dictionary may look different when serialized)
  • inefficient; as even for fields that are needed it needs to include a lot of additional metadata
  • invalid; if there are fields that cannot be serialized (such as event delegates, although they can be marked [NonSerialized])
  • brittle; your serialization is now bound to the field names - but fields are meant to be an implementation detail; see also Obfuscation, serialization and automatically implemented properties

By implementing ISerializable you can provide your own binary serialization mechanism. Note that the xml equivalent of this is IXmlSerializable, as used by XmlSerializer etc.

For DTO purposes, BinaryFormatter should be avoided - things like xml (via XmlSerializer or DataContractSerializer) or json are good, as are cross-platform formats like protocol buffers.

For completeness, protobuf-net does include hooks for ISerializable (allowing you to use a portable binary format without writing lots of code), but BinaryFormatter wouldn't be your first choice here anyway.

Marc Gravell