问题描述
给出以下内容:
[<DataContract>]
type TweetUser = {
[<field:DataMember(Name="followers_count")>] Followers:int
[<field:DataMember(Name="screen_name")>] Name:string
[<field:DataMember(Name="id_str")>] Id:int
[<field:DataMember(Name="location")>] Location:string}
[<DataContract>]
type Tweet = {
[<field:DataMember(Name="id_str")>] Id:string
[<field:DataMember(Name="text")>] Text:string
[<field:DataMember(Name="retweeted")>] IsRetweeted:bool
[<field:DataMember(Name="created_at")>] DateStr:string
[<field:DataMember(Name="user", IsRequired=false)>] User:TweetUser
[<field:DataMember(Name="sender", IsRequired=false)>] Sender:TweetUser
[<field:DataMember(Name="source")>] Source:string}
使用DataContractJsonSerializer(typeof<Tweet[]>)
反序列化将导致用户"或发件人"字段为空(至少这是调试器告诉我的内容).
Deserializing with DataContractJsonSerializer(typeof<Tweet[]>)
will result in either the User or Sender field being null (at least that's what the debugger is telling me).
如果我尝试编写以下内容:
If I try to write the following:
let name = if tweet.User <> null
then tweet.User.Name
else tweet.Sender.Name
编译器发出错误:类型'TweetUser'没有适当的'null'"
the compiler emits the error: "The type 'TweetUser' does not have 'null' as a proper value"
在这种情况下如何测试空值?
How do I test null values in this case?
推荐答案
要循环扩展@Tomas的答案;-]
To cyclically expand on @Tomas' answer ;-]
let name = if not <| obj.ReferenceEquals (tweet.User, null)
then tweet.User.Name
else tweet.Sender.Name
或
let inline isNull (x:^T when ^T : not struct) = obj.ReferenceEquals (x, null)
Unchecked.defaultof<_>
在做正确的事情,并为您的记录类型生成null.问题是默认的相等运算符使用泛型结构比较,它期望您在使用F#类型时始终按照F#的规则进行操作.无论如何,空检查实际上只需要首先进行参照比较.
Unchecked.defaultof<_>
is doing the right thing and producing nulls for your record types; the issue is that the default equality operator uses generic structural comparison, which expects you to always play by F#'s rules when using F# types. In any case, a null-check really only warrants referential comparison in the first place.
这篇关于在F#中测试空引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!