可为 Null 运算符是二进制算术或比较运算符,它们适用于一端或两端的可为 null 的算术类型。 使用数据源(例如允许 null 代替实际值的数据库)时,会出现可以为 null 的类型。 查询表达式中使用可为 Null 的运算符。 除了算术和比较的可为 null 运算符外,转换运算符还可用于在可以为 null 的类型之间进行转换。 某些查询运算符也有可为 null 的版本。
注释
可以为 null 的运算符通常用于 查询表达式。 如果不使用查询表达式,则无需知道或使用这些运算符。
可为 Null 运算符的表
下表列出了 F# 中支持的可为 null 运算符。
左侧可为 Null | 右侧可为 Null | 双方可为 null |
---|---|---|
?>= | >=? | ?>=? |
?> | >? | ?>? |
?<= | <=? | ?<=? |
?< | <? | ?<? |
?= | =? | ?=? |
?<> | <>? | ?<>? |
?+ | +? | ?+? |
?- | -? | ?-? |
?* | *? | ?*? |
?/ | /? | ?/? |
?% | %? | ?%? |
注解
可以为 null 的运算符包含在命名空间 FSharp.Linq 的 NullableOperators 模块中。 可为 null 数据的类型为 System.Nullable<'T>
。
在查询表达式中,从允许 null 而不是值的数据选择数据源中的数据时,会出现可以为 null 的类型。 在 SQL Server 数据库中,表中的每个数据列都有一个属性,指示是否允许 null。 如果允许 null,则从数据库返回的数据可以包含不能由基元数据类型(例如 int
, float
等)表示的 null 值。 因此,数据将作为替代int
返回System.Nullable<int>
,System.Nullable<float>
而不是float
返回。 实际值可以通过使用属性从System.Nullable<'T>
对象中获取,并且可以通过调用HasValue
方法来确定对象是否System.Nullable<'T>
具有Value
值。 另一个有用的方法是该方法 System.Nullable<'T>.GetValueOrDefault
,该方法允许获取相应类型的值或默认值。 默认值是某种形式的“零”值,例如 0、0.0 或 false
。
可以使用通常的转换运算符(如 int
或 float
)将可以为 null 的类型转换为不可为 null 的基元类型。 也可以使用可为 null 类型的转换运算符从一个可以为 null 的类型转换为另一个可以为 null 的类型。 适当的转换运算符与标准运算符同名,但它们位于单独的模块中,即 FSharp.Linq 命名空间中的可为 Null 模块。 通常,在使用查询表达式时打开此命名空间。 在这种情况下,可以通过将前缀 Nullable.
添加到适当的转换运算符来使用可为 null 的转换运算符,如以下代码所示。
open Microsoft.FSharp.Linq
let nullableInt = new System.Nullable<int>(10)
// Use the Nullable.float conversion operator to convert from one nullable type to another nullable type.
let nullableFloat = Nullable.float nullableInt
// Use the regular non-nullable float operator to convert to a non-nullable float.
printfn $"%f{float nullableFloat}"
输出为 10.000000
。
对于可为 null 的数据字段(例如 sumByNullable
)的查询运算符,也可用于查询表达式。 不可为 null 类型的查询运算符与可以为 null 的类型不兼容,因此在使用可以为 null 的数据值时,必须使用相应查询运算符的可为 null 版本。 有关详细信息,请参阅 查询表达式。
以下示例演示如何在 F# 查询表达式中使用可以为 null 的运算符。 第一个查询演示如何在没有可为 null 运算符的情况下编写查询;第二个查询显示使用可为 null 运算符的等效查询。 有关完整上下文,包括如何设置数据库以使用此示例代码,请参阅 演练:使用类型提供程序访问 SQL 数据库。
open System
open System.Data
open System.Data.Linq
open Microsoft.FSharp.Data.TypeProviders
open Microsoft.FSharp.Linq
[<Generate>]
type dbSchema = SqlDataConnection<"Data Source=MYSERVER\INSTANCE;Initial Catalog=MyDatabase;Integrated Security=SSPI;">
let db = dbSchema.GetDataContext()
query {
for row in db.Table2 do
where (row.TestData1.HasValue && row.TestData1.Value > 2)
select row
} |> Seq.iter (fun row -> printfn $"%d{row.TestData1.Value} %s{row.Name}")
query {
for row in db.Table2 do
// Use a nullable operator ?>
where (row.TestData1 ?> 2)
select row
} |> Seq.iter (fun row -> printfn "%d{row.TestData1.GetValueOrDefault()} %s{row.Name}")