This is an old issue with F# codegen which has left serialization in F#-defined exceptions using exception X = .... effectively broken. Here's a simple reproduction:
let clone (x : 'T) =
let bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter()
let m = new System.IO.MemoryStream()
bf.Serialize(m, x)
m.Position <- 0L
bf.Deserialize(m) :?> 'T
exception Foo of x:string * y:int
let foo = Foo ("value", 42)
clone foo // val it : exn = Foo (null,0)
The reason why this happens is that exceptions are necessarily serialized through ISerializable. Every type that inherits System.Exception must provide a SerializationInfo * StreamingContext constructor and an accompanying override of the ISerializable.GetObjectData() method, which are responsible for calling the corresponding base methods and serializing any additional data included in the subtype. In F# exceptions, generated code looks as follows (decompiled to C#):
[CompilationMapping(SourceConstructFlags.Exception)]
[Serializable]
public class Foo : Exception, IStructuralEquatable
{
internal string x@;
internal int y@;
protected Foo(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
...
}
My proposal is to update codegen such that the generated class looks like so:
[CompilationMapping(SourceConstructFlags.Exception)]
[Serializable]
public class Foo : Exception, IStructuralEquatable
{
internal string x@;
internal int y@;
protected Foo(SerializationInfo info, StreamingContext context) : base(info, context)
{
x@ = (string) info.GetValue("x", typeof(string));
y@ = (int) info.GetValue("y", typeof(int));
}
public override GetObjectData(SerializationInfo info, StreamingContext context)
{
base.GetObjectData(info, context);
info.AddValue("x", x@);
info.AddValue("y", y@);
}
...
}
This is an old issue with F# codegen which has left serialization in F#-defined exceptions using
exception X = ....effectively broken. Here's a simple reproduction:The reason why this happens is that exceptions are necessarily serialized through
ISerializable. Every type that inheritsSystem.Exceptionmust provide aSerializationInfo * StreamingContextconstructor and an accompanying override of theISerializable.GetObjectData()method, which are responsible for calling the corresponding base methods and serializing any additional data included in the subtype. In F# exceptions, generated code looks as follows (decompiled to C#):My proposal is to update codegen such that the generated class looks like so: