f# - 在 F# 中测试空引用

标签 f#

鉴于以下情况:

[<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[]>) 反序列化将导致 User 或 Sender 字段为空(至少这是调试器告诉我的)。

如果我尝试编写以下内容:
    let name = if tweet.User <> null 
                  then tweet.User.Name
                  else tweet.Sender.Name

编译器发出错误:“类型‘TweetUser’没有‘null’作为正确值”

在这种情况下如何测试空值?

最佳答案

循环扩展@Tomas 的回答;-]

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<_>正在做正确的事情并为您的记录类型生成空值;问题是默认的相等运算符使用通用结构比较,它希望您在使用 F# 类型时始终遵循 F# 的规则。在任何情况下,空检查实际上只保证首先进行引用比较。

关于f# - 在 F# 中测试空引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10746618/

相关文章:

inheritance - 使用函数式编程风格数据类型的模型继承

f# - 在 F# 类型提供程序中发出生成的类型

F# 将函数应用于列表树的每个节点中的值

f# - 在不同的泛型实例中实现相同的接口(interface)

f# - 如何为受歧视的联盟覆盖 .Equals() ?

syntax - F# 创建和填充 FSharpx.Collections.Vector 的语法是什么?

arrays - 有没有一种简单的方法来打印数组的每个元素?

f# - 为什么 F# 会出现模块名称部分重叠的问题?

f# - 运行 dotnet build 时如何忽略 MSB4011

f# - “not equal to”的F#语法是什么?