Значения NULL (F#)
В этом разделе описывается использование значения NULL в языке F#.
Значение NULL
Обычно значение NULL не используется в языке F# для значений или переменных. Тем не менее, NULL появляется в качестве ненормального значения в определенных ситуациях. Если тип определен в языке F#, значение NULL не допускается в качестве регулярного значения, кроме случая, когда к этому типу применен атрибут AllowNullLiteral. Если тип определен на каком-либо ином языке .NET, NULL является возможным значением, и при взаимодействии с такими типами код F# может столкнуться со значениями NULL.
Для типа, определенного на языке F# и используемого только из среды языка F#, единственным способом создать значение NULL, непосредственно используя библиотеку F#, является использование функции Unchecked.defaultof или Array.zeroCreate. Однако в случае типа F#, используемого из других языков .NET или используемого в сочетании с написанным не на F# API, таком как платформа .NET Framework, могут возникать значения NULL.
Если используется ссылочная переменная с возможным значением NULL в другом языке .NET, в F# можно использовать тип option. При использовании типа option языка F# вместо NULL при отсутствии объекта используется значение-вариант None. При наличии объекта используется значение типа option Some(obj) с объектом obj. Дополнительные сведения см. в разделе Параметры (F#).
Ключевое слово null — допустимое ключевое слово в языке F#, и его необходимо использовать при работе с API платформы .NET Framework или другими API, написанными на другом языке .NET. Существует две ситуации, в которых может понадобиться значение NULL: при вызове API .NET и передаче значения NULL в качестве аргумента, и при интерпретации возвращаемого значения или выходного параметра из вызова метода .NET.
Для передачи значения NULL методу .NET в вызывающем коде просто указывается ключевое слово null. Это показано в следующем примере кода.
open System
// Pass a null value to a .NET method.
let ParseDateTime (str: string) =
let (success, res) = DateTime.TryParse(str, null, System.Globalization.DateTimeStyles.AssumeUniversal)
if success then
Some(res)
else
None
Для интерпретации значения NULL, полученного от метода .NET, по возможности следует использовать подбор шаблона. В следующем примере кода показано использование подбора шаблона для интерпретации значения NULL, возвращаемого методом ReadLine при попытке чтения после конца входного потока.
// Open a file and create a stream reader.
let fileStream1 =
try
System.IO.File.OpenRead("TextFile1.txt")
with
| :? System.IO.FileNotFoundException -> printfn "Error: TextFile1.txt not found."; exit(1)
let streamReader = new System.IO.StreamReader(fileStream1)
// ProcessNextLine returns false when there is no more input;
// it returns true when there is more input.
let ProcessNextLine nextLine =
match nextLine with
| null -> false
| inputString ->
match ParseDateTime inputString with
| Some(date) -> printfn "%s" (date.ToLocalTime().ToString())
| None -> printfn "Failed to parse the input."
true
// A null value returned from .NET method ReadLine when there is
// no more input.
while ProcessNextLine (streamReader.ReadLine()) do ()
Значения NULL для типов F# могут формироваться и другими способами, например при использовании функции Array.zeroCreate, которая вызывает функцию Unchecked.defaultof. При работе с таким кодом необходимо соблюдать осторожность: значения NULL должны всегда быть инкапсулированы. В библиотеке, предназначенной только для F#, не обязательно проверять каждую функцию на значения NULL. При написании библиотеки для взаимодействия с другими языками .NET может понадобиться добавить проверки на пустые входные параметры и создавать исключение ArgumentNullException — точно так же, как в коде на C# или Visual Basic.
Для проверки, не имеет ли произвольная величина значение NULL, можно использовать следующий код.
match box value with
| null -> printf "The value is null."
| _ -> printf "The value is not null."