Today I faced a SerializationException that refered to some anonymous inner class stating it was not serializable, when IIS tried to store the session in the ASP.NET State Service:
Type ‘Xyz+<>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.
I have built a very simple example to confirm that closures are not serializable whereas “normal” functions are:
[TestFixture] public class GeneralUnderstandingTests { [Serializable] private class ASerializableType { private readonly Func thisIsAClosure; private readonly Func thisIsNotAClosure; public ASerializableType() { // Normal functions are allowed: The following // succeeds to serialize const int SomeConst = 12345; thisIsNotAClosure = () => SomeConst; // But closures are compiled to non-serializable // inner classes and break serialization: var someVariable = 12345; thisIsAClosure = () => someVariable; } } [Test] public void ASerializableType_CanBeSerialized() { var sessionState = SessionStateItemCollection(); sessionState["sut"] = new ASerializableType(); sessionState.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.
