可以为 null 的运算符 (F#)
可以为 null 的运算符与一个可以为 null 的算术类型。使用的二元算术或比较运算符或两侧。可以为 null 的类型通常出现,当您与源使用的数据 (如允许在实际值位置 null 的数据库时。可以为 null 的运算符在查询表达式中最常用。除了算术和比较可以为 null 的运算符,转换运算符可用于将可以为 null 的类型。还具有某些查询运算符可以为 null 的版本。
可以为 null 的运算符表
下表列出了 F# 语言支持可以为 null 的运算符。
在左侧的可以为 null |
在右侧的可以为 null |
可以为 null 的双方 |
备注
可以为 null 的运算符在命名空间 Microsoft.FSharp.Linq的 NullableOperators 模块中。可以为 null 的数据的类型是 Nullable<T>。
在查询表达式中,可以为 null 的类型出现,当选择数据从允许空值而不是值的数据源。在 SQL Server 数据库中,每个数据行在表中具有指定的特性是否允许 null。如果为 null,允许从不能由基元数据类型表示例如 int, float的数据库返回的数据可以包含 NULL,等等。因此,数据会作为 System.Nullable<int> 而不是 int和 System.Nullable<float> 而不是 float。使用 Value 属性,则实际值可以从 Nullable<T> 对象获取,因此,您可以确定 Nullable<T> 对象是否具有值通过调用 HasValue 方法。另一个有用的方法是 GetValueOrDefault 方法,使您可以获取值或适当类型的默认值。默认值为 “零”值的某种形式,例如 0, 0.0 或 false。
使用常用转换运算符例如 int 或 float,可以为 null 的类型可以转换为不可为 null 的基元类型。从一个可以为 null 的类型转换为另一个可以为 null 的类型使用可以为 null 的类型的,转换运算符也是可能的。相应的转换运算符与标准节相同,但是,它们是在单独的模块,在 Microsoft.FSharp.Linq 命名空间的 Null 模块。通常,那么,当用查询表达式时,您打开此命名空间。如下面的代码所示,在这种情况,您可以通过添加前缀使用可以为 null 的转换运算符 Nullable. 到适当的转换运算符,。
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#)。
下面的示例在 F# 查询表达式显示使用可以为 null 的运算符。第一个查询演示如何将编写查询,而无需可以为 null 的运算符;第二个查询显示使用可以为 null 的运算符的一个等效查询。有关完整的上下文,包括如何将数据库使用此代码示例,请参见 演练:使用类型提供程序访问 SQL 数据库 (F#)。
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 %s" row.TestData1.Value 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 %s" (row.TestData1.GetValueOrDefault()) row.Name)