I have a number of records that look like this:
[<DataContract>]
type Rec1 = {
[<DataMember>] mutable field1 : int;
[<DataMember>] mutable field2 : string;
}
[<DataContact>]
type Rec2 = {
[<DataMember>] mutable field3 : Rec1;
[<DataMember>] mutable field4 : int;
}
I use DataContactJsonSerializer
to deserialize JSON into this structure. This is a valid JSON value:
{ "field3": null, "field4": 1 }
Which means at runtime, field3
is null/Unchecked.defaultOf<_>
. In Visual Studio 2010, this test works fine:
(deserialize<Rec2> "{ field3: null, field4: 1 }") = { field3 = Unchecked.defaultOf<_>; field4 = 1 } //true
In Visual Studio 2013, the same code throws a NullReferenceException
:
at Rec2.Equals(Rec2 obj)
Peeking at the code in ILSpy, I see this is generated:
if(this != null)
{
return obj != null && this.field3.Equals(obj.field3) && this.field4.Equals(obj.field4);
}
return obj == null;
So the issue is the compiler assumes that field3
is never null which isn't the case since DataContractJsonSerializer
sets the value to null
. I've tried applying the AllowNullLiteral
attribute to Rec1
but F# records aren't allowed to have that attribute applied to them. How can I either tell the compiler that the fields can be null
or re-structure my types to allow this to work?
F# is generating the types assuming it will only ever be used from F# where null
isn't possible. Because [<AllowNullLiteral>]
isn't allowed on that element I don't think there is a way to control code gen such that it will account for this possibility. I can think of 2 approaches to fixing this
Rec2
instead of the default structural equality. This means you have to write the equality method yourself which is unfortunate but it should allow you to account for the possibility of null
struct
instances instead of class
. This eliminates the possibility of null
in any CLR use case. This will require you to move from a record definition to a full type though If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With