我是F#语言的新手,当使用带有字符串值的选项类型匹配一些和无时,我遇到了异常.这是使用FSCheck发现的.在给定(字符串选项)属性类型的情况下,如果分配的字符串的值为空,则会引发空引用异常,从而导致值=Some(空).我的预期(错误的)是,这将导致零.幼稚的方法是判断一些和不判断,如果是一些,添加一个后续的匹配来处理一些(空).我使用的不那么天真的方法是(Match Option.ofObj optValue与…).这似乎是违反直觉的,因为我必须在处理具有可以赋值为空的值的选项类型的任何地方重复这种模式.

使用的类型

type LoanApplication =
{ Name: string
  Age: int
  CreditScore: int option
  Website: string option
  Email: string option
  PhoneNumber: string option }

在匹配输入时抛出空引用的函数

    member this.processApplication(application: LoanApplication) =
    //we want to create a person
    //do we have a valid application
    let getValidRequest (input: string option) =
        match input with
        | None -> IsUrl false
        | Some optValue ->
                let isUrl = optValue.StartsWith("http://")
                let isEmail = optValue.ToString().Contains("@")
                let isPhone = optValue.ToString().StartsWith("+")

                match isUrl, isEmail, isPhone with
                | true, _, _ -> IsUrl true
                | _, true, _ -> IsEmail true
                | _, _, true -> IsPhone true
                | _ -> IsUrl false


    let validateTypeFields (application: LoanApplication) =
        match (getValidRequest application.Email), (getValidRequest application.PhoneNumber) with
        | IsEmail true, IsPhone true ->
            Valid
                { Name = application.Name
                  Age = application.Age
                  CreditScore = application.CreditScore
                  Website = application.Website
                  Email = application.Email.Value
                  PhoneNumber = application.PhoneNumber.Value }
        | _ -> Invalid application


    let validationResult = validateTypeFields application

    match validationResult with
    | Valid validApplication -> ProspectiveApplication validApplication
    | Invalid application -> InvalidApplication application

测试设置调用失败的函数(注意:FSCheck是将一些(空)分配给设置中的函数,以澄清问题.

    [<Fact>]
member this.IsTheTestThatIsFailing() =
    let application: LoanApplication =
        { Name = "Joe"
          Age = 30
          CreditScore = Some(700)
          Website = Some("http://www.google.com")
          Email = Some(null)
          PhoneNumber = Some("+123456789") }

    let processor = new ApplicantProcess()
    let result = processor.processApplication application

    match result with
    | ValidApplication validApplication
    | ProspectiveApplication validApplication -> Assert.True(false)
    | InvalidApplication application -> Assert.True(true)

处理选项(空)或从一开始就防止它们的一些正确方法是什么? 在我的示例中,我想要一个字符串值不能赋值为空的属性.

推荐答案

在F#获得与C#8特性匹配的nullable reference type support之前,您可以使用活动模式来使其更方便:

let (|IsNullOrEmptyString|IsNonEmptyString|) x =
  if System.String.IsNullOrEmpty x then
    IsNullOrEmptyString
  else
    IsNonEmptyString x

并调整您的代码

match input with
| None | Some IsNullOrEmptyString -> IsUrl false
| ... // rest of your code

它增加了判断空字符串的额外功能,但为您的域逻辑定义相关的活动模式取决于您自己.

.net相关问答推荐

SLN配置文件:映射问题

.NET MAUI ListView - ObservableCollection - 在异步方法期间不更新

在本地运行 Azure 函数会在 .NET7 升级后出现无运行时错误

判断 Windows 路径中是否存在可执行文件

在 C# 中输入按键

.NET 中的线程安全集合

发布版本中的 Debug.WriteLine

比较 C# 中的字符串和对象

XmlNode 值与内部文本

是什么让 Enum.HasFlag 这么慢?

共享 AssemblyInfo 用于跨解决方案的统一版本控制

软件包版本始终为 1.0.0,带有 dotnet pack

如何从 .NET 中的流中获取 MemoryStream?

文件按文件名模式存在

在 WPF DataGrid 中绑定 ComboBoxColumn 的 ItemsSource

实体框架中的 POCO 是什么?

使用 DateTime.ToString() 时获取日期后缀

如果锁定的对象内部发生异常,它会保持锁定状态吗?

MVVM 没有意义吗?

.NET 桌面应用程序中的 Settings.settings 与 app.config