Wes*_*ser 6 f# nullreferenceexception .net-4.5
我有一些看起来像这样的记录:
[<DataContract>]
type Rec1 = {
[<DataMember>] mutable field1 : int;
[<DataMember>] mutable field2 : string;
}
[<DataContact>]
type Rec2 = {
[<DataMember>] mutable field3 : Rec1;
[<DataMember>] mutable field4 : int;
}
Run Code Online (Sandbox Code Playgroud)
我DataContactJsonSerializer用来将JSON反序列化为这个结构.这是一个有效的JSON值:
{ "field3": null, "field4": 1 }
Run Code Online (Sandbox Code Playgroud)
这意味着在运行时,field3是null/Unchecked.defaultOf<_>.在Visual Studio 2010中,此测试工作正常:
(deserialize<Rec2> "{ field3: null, field4: 1 }") = { field3 = Unchecked.defaultOf<_>; field4 = 1 } //true
Run Code Online (Sandbox Code Playgroud)
在Visual Studio 2013中,相同的代码抛出NullReferenceException:
at Rec2.Equals(Rec2 obj)
Run Code Online (Sandbox Code Playgroud)
偷看ILSpy中的代码,我看到这是生成的:
if(this != null)
{
return obj != null && this.field3.Equals(obj.field3) && this.field4.Equals(obj.field4);
}
return obj == null;
Run Code Online (Sandbox Code Playgroud)
所以问题是编译器假定field3从不为null,因为DataContractJsonSerializer将值设置为不是这种情况null.我已尝试应用该AllowNullLiteral属性,Rec1但不允许F#记录将该属性应用于它们.我怎么能告诉编译器字段可以是null或重新构造我的类型以允许它工作?
F#正在生成类型,假设它只能在F#中使用,null而不可能.因为[<AllowNullLiteral>]不允许在该元素上我不认为有一种方法来控制代码gen,因此它将解释这种可能性.我可以想到两种方法来解决这个问题
Rec2而不是默认的结构相等.这意味着你必须自己编写相等的方法,这是不幸的,但它应该让你考虑到的可能性nullstruct实例而不是class.这消除了null任何CLR用例的可能性.这将要求您从记录定义移动到完整类型| 归档时间: |
|
| 查看次数: |
339 次 |
| 最近记录: |