Record Equals or GetHashCode throws NullReferenceException

Viewed 406

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 AllowNullLiteralattribute 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?

3 Answers
Related