Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET Runtime Serialization

Could someone please explain what's the difference between inheriting from ISerializable interface and declaring your object as [Serializable]?

I know that in the first case you are have to implement the ISerializable interface members, while in the second case this work is likely to be done by the C# itself.

But what doesn't make sense to me then is the following behavior:

public void Foo<T>() where T : ISerializable
{
   // Whatever
}

Now, if I have some class like this:

[Serializable]
public class Value
{
    public String Value { get; set; }
}

And unfortunately I can't call my X.Foo<Value>(), because the compiler says:

There is no implicit reference conversion from 'Value' to 'System.Runtime.Serialization.ISerializable'

I'm pretty sure it's my misunderstanding of something obvious, so please point out what am I doing wrong.


UPDATE (IMPORTANT :)

How do I make the where T : ISerializable statement work with [Serializable] class too? Is there a way?

What I'm trying to achieve is the compilation-time error if the supplied type T is not serializable (by using [Serializable] or ISerializable way).

Obviously, my current check handles only the second case, so how do I make it handle both of them?

like image 268
Yippie-Ki-Yay Avatar asked Dec 10 '10 00:12

Yippie-Ki-Yay


2 Answers

Serializable is merely an attribute you place on a class to let classes such as SoapFormatter know (via reflection) it can be serialized. Decorating a class with an attribute does not make a class implement an interface, which is why the compiler complains in your case. If memory serves, one implements ISerializable if one wants more control over the serialization process.

like image 113
Ohad Schneider Avatar answered Sep 20 '22 14:09

Ohad Schneider


To answer your update: there is no way you can put a generic constraint on the presence of an attribute.

The next best thing you can do is throw an exception (obviously at runtime, not at compile-time). For a generic method, it would look something like this:

public void Foo<T>()
{
    if (!typeof (ISerializable).IsAssignableFrom(typeof (T))
        || !typeof (T).GetCustomAttributes(true).OfType<SerializableAttribute>().Any())
    {
        throw new InvalidOperationException(string.Format("Type {0} is not serializable.", typeof (T).FullName));
    }
}

For a generic class, you could do this in the static constructor (fails faster):

public class Foo<T>
{
    static Foo()
    {
        if (!typeof(ISerializable).IsAssignableFrom(typeof(T))
            || !typeof(T).GetCustomAttributes(true).OfType<SerializableAttribute>().Any())
        {
            throw new InvalidOperationException(string.Format("Type {0} is not serializable.", typeof(T).FullName));
        }
    }
}
like image 27
jeroenh Avatar answered Sep 17 '22 14:09

jeroenh