Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 当编译器坚持它不是';不可能?_.net_F#_Null_Json.net_Optional - Fatal编程技术网

.net 当编译器坚持它不是';不可能?

.net 当编译器坚持它不是';不可能?,.net,f#,null,json.net,optional,.net,F#,Null,Json.net,Optional,我们的项目混合了C#和F#与ASP.NET核心。ASP.NET核心默认为Newtonsoft,用于在任何地方进行序列化/反序列化,而swagger文档生成(nswag)也依赖于类似CLI(可变)的DTO来生成正确的类型 我们的DTO在F#中定义如下: [] 类型查询= {状态:字符串 偏移量:int 限制:int} 这使得Newtonsoft序列化和nswag生成swagger文档变得非常简单 但是。。!我对空/选项“不匹配”感到非常困难。C#/Newtonsoft/NSwag坚持使用null

我们的项目混合了C#和F#与ASP.NET核心。ASP.NET核心默认为Newtonsoft,用于在任何地方进行序列化/反序列化,而swagger文档生成(nswag)也依赖于类似CLI(可变)的DTO来生成正确的类型

我们的DTO在F#中定义如下:

[]
类型查询=
{状态:字符串
偏移量:int
限制:int}
这使得Newtonsoft序列化和nswag生成swagger文档变得非常简单

但是。。!我对空/选项“不匹配”感到非常困难。C#/Newtonsoft/NSwag坚持使用
null
,并且不会理解F#的
选项
。因此,在我的F#中,我必须检查空值并将其转换为选项;当从域转换回DTO时,还可以将我的选项转换回null

但是F#坚持认为null是不可能的,甚至不允许我检查:编译器给了我:“类型{…}没有'null'作为正确的值”。但事实是,运行时是空的,因为Newtonsoft就是这样工作的。Newtonsoft似乎是.NET标准,所以我不认为使用其他东西是可行的


即使F#认为它不可能为null,我怎么能检查null呢?

克服这一问题的一个简单方法(通常)是在检查null之前将值框起来

让isReallyNull value=value |>box |>isNull

然后,您可以在正常逻辑中检查Newtonsoft返回的对象实例:

if dto |> isReallyNull
then None
else Some dto
下面是一个完整的示例,使用
Unchecked.defaultof
为编译器说不能为null的类型生成null值:

[<CLIMutable>]
type MyDto =
    {
        Status: string
        Offset: int
        Limit: int
    }

let isReallyNull value = value |> box |> isNull

let dto = Unchecked.defaultof<MyDto>

// if dto |> isNull (* Compiler complains that MyDto does not have null as a proper value *)
if dto |> isReallyNull
then printfn "The DTO is null"
else printfn "The DTO is non-null"
[]
类型MyDto=
{
状态:字符串
偏移量:int
限制:int
}
让isReallyNull值=值|>框|>isNull
设dto=Unchecked.defaultof
//如果dto |>isNull(*编译器抱怨MyDto没有将null作为正确的值*)
如果dto |>isReallyNull
然后打印fn“DTO为空”
else printfn“DTO为非空”
正如Aaron所建议的,如果dto是一种记录类型,那么您需要执行以下操作:

let optionalValue = dto |> box |> Option.ofObj

现在没有时间给出一个完整的答案,但是有你需要的答案。TL;DR:对您的类型使用
[]
属性。您是否确实尝试过
选项
?最后我检查了一下,JSON.NET确实支持它。我尝试了这个选项,它使最可怕的JSON变得可以想象(仍然)。你确定它适合你(开箱即用)吗@rmunn:我已经尝试过使用[],但它不允许:“记录、联合、缩写和结构类型不能有'AllowNullLiteral'属性”也没有时间给出完整的答案,但是一个经常使用的实用程序是FSharpLU.jsonSorry,我认为如果DTO类型是F#Record,这将不起作用。如果不先将其装箱,您将遇到与OP相同的问题。如果您在我上面发布的示例中通过添加行
let maybeDto=dto |>Option.ofObj
,尝试此操作,您将得到编译器错误,说明
MyDto没有将null作为正确的值
。请注意,使用AllowNullLiteral反序列化到类中的所有操作都与您预期的一样有效。无需告诉编译器它不明白发生了什么:)
let optionalValue = Option.ofObj dto
let optionalValue = dto |> box |> Option.ofObj