Today I faced a SerializationException
that refered to some anonymous inner class +<>c__DisplayClass10
stating it was not serializable, when IIS tried to store the session in the ASP.NET State Service:
Type 'Xyz.GeneralUnderstandingTests+ASerializableType+<>c__DisplayClass10' in Assembly 'Xyz, Version=1.2.5429.24450, Culture=neutral, PublicKeyToken=null' is not marked as serializable.
I looked for lambdas in my code and found quite a few, but most of them were not new and did never have any issues in serialization. But then I noticed that I had built in a new lambda expression that "happened" to build up a closure.
Searching Stackoverflow for closure serialization
I found some Q&As that reveal that closures cannot be serialized in other languages such as PHP *) but I did not manage to find such a statement for C#. I have however been able to build a very simple example that seems to confirm that closures are not serializable whereas "normal" functions are
[TestFixture]
public class GeneralUnderstandingTests
{
[Serializable]
private class ASerializableType
{
private readonly Func<int> thisIsAClosure;
private readonly Func<int> thisIsNotAClosure;
public ASerializableType()
{
const int SomeConst = 12345;
thisIsNotAClosure = () => SomeConst; // succeeds to serialize
var someVariable = 12345;
thisIsAClosure = () => someVariable; // fails to serialize
}
}
[Test]
public void ASerializableType_CanBeSerialized()
{
var sessionStateItemCollection = new
System.Web.SessionState.SessionStateItemCollection();
sessionStateItemCollection["sut"] = new ASerializableType();
sessionStateItemCollection.Serialize(new BinaryWriter(new MemoryStream()));
}
}
This test fails but goes green as soon as the line thisIsAClosure = ...
is commented out. The line thisIsNotAClosure = ...
however does not cause any issues as SomeConst
is not a variable but a constant, that is, it does not build a closure but is inlined by the compiler.
Can you confirm that what I have concluded is correct?
=> Is there a way to circumvent this issue?
=> Could it be that this depends on the internals of the compiler used? Since it is the compiler that turns the lambda/closure expression into a anonymous inner class.
*) Links: