From eb907882014352edcc3d37c3f8b684717fc13e26 Mon Sep 17 00:00:00 2001 From: albert-du <52804499+albert-du@users.noreply.github.com> Date: Sun, 6 Mar 2022 11:32:12 -0800 Subject: [PATCH] NullReferenceException F# snippets --- .../NullReferenceException/Overview/Array1.fs | 14 ++++++ .../NullReferenceException/Overview/Array2.fs | 12 +++++ .../NullReferenceException/Overview/Array3.fs | 14 ++++++ .../NullReferenceException/Overview/Array4.fs | 21 ++++++++ .../NullReferenceException/Overview/Chain1.fs | 48 +++++++++++++++++++ .../NullReferenceException/Overview/Chain2.fs | 46 ++++++++++++++++++ .../Overview/example1.fs | 23 +++++++++ .../Overview/example1a.fs | 6 +++ .../Overview/example2.fs | 22 +++++++++ .../NullReferenceException/Overview/fs.fsproj | 20 ++++++++ .../Overview/nullreturn2.fs | 26 ++++++++++ .../Overview/nullreturn2a.fs | 40 ++++++++++++++++ xml/System/NullReferenceException.xml | 11 +++++ 13 files changed, 303 insertions(+) create mode 100644 snippets/fsharp/System/NullReferenceException/Overview/Array1.fs create mode 100644 snippets/fsharp/System/NullReferenceException/Overview/Array2.fs create mode 100644 snippets/fsharp/System/NullReferenceException/Overview/Array3.fs create mode 100644 snippets/fsharp/System/NullReferenceException/Overview/Array4.fs create mode 100644 snippets/fsharp/System/NullReferenceException/Overview/Chain1.fs create mode 100644 snippets/fsharp/System/NullReferenceException/Overview/Chain2.fs create mode 100644 snippets/fsharp/System/NullReferenceException/Overview/example1.fs create mode 100644 snippets/fsharp/System/NullReferenceException/Overview/example1a.fs create mode 100644 snippets/fsharp/System/NullReferenceException/Overview/example2.fs create mode 100644 snippets/fsharp/System/NullReferenceException/Overview/fs.fsproj create mode 100644 snippets/fsharp/System/NullReferenceException/Overview/nullreturn2.fs create mode 100644 snippets/fsharp/System/NullReferenceException/Overview/nullreturn2a.fs diff --git a/snippets/fsharp/System/NullReferenceException/Overview/Array1.fs b/snippets/fsharp/System/NullReferenceException/Overview/Array1.fs new file mode 100644 index 00000000000..f1d91f1dced --- /dev/null +++ b/snippets/fsharp/System/NullReferenceException/Overview/Array1.fs @@ -0,0 +1,14 @@ +module Array1 + +// +open System + +let values = [| "one"; null; "two" |] +for i = 0 to values.GetUpperBound 0 do + printfn $"""{values[i].Trim()}{if i = values.GetUpperBound 0 then "" else ", "}""" +printfn "" +// The example displays the following output: +// Unhandled Exception: +// System.NullReferenceException: Object reference not set to an instance of an object. +// at .main() +// \ No newline at end of file diff --git a/snippets/fsharp/System/NullReferenceException/Overview/Array2.fs b/snippets/fsharp/System/NullReferenceException/Overview/Array2.fs new file mode 100644 index 00000000000..3ebfa34c3fe --- /dev/null +++ b/snippets/fsharp/System/NullReferenceException/Overview/Array2.fs @@ -0,0 +1,12 @@ +module Array2 + +// +open System + +let values = [| "one"; null; "two" |] +for i = 0 to values.GetUpperBound 0 do + printf $"""{if values[i] <> null then values[i].Trim() else ""}{if i = values.GetUpperBound 0 then "" else ", "}""" +Console.WriteLine() +// The example displays the following output: +// one, , two +// diff --git a/snippets/fsharp/System/NullReferenceException/Overview/Array3.fs b/snippets/fsharp/System/NullReferenceException/Overview/Array3.fs new file mode 100644 index 00000000000..7a92686c7bb --- /dev/null +++ b/snippets/fsharp/System/NullReferenceException/Overview/Array3.fs @@ -0,0 +1,14 @@ +module Array3 + +// +let values: int[] = null +for i = 0 to 9 do + values[i] <- i * 2 + +for value in values do + printfn $"{value}" +// The example displays the following output: +// Unhandled Exception: +// System.NullReferenceException: Object reference not set to an instance of an object. +// at .main() +// \ No newline at end of file diff --git a/snippets/fsharp/System/NullReferenceException/Overview/Array4.fs b/snippets/fsharp/System/NullReferenceException/Overview/Array4.fs new file mode 100644 index 00000000000..1c95768411b --- /dev/null +++ b/snippets/fsharp/System/NullReferenceException/Overview/Array4.fs @@ -0,0 +1,21 @@ +module Array4 + +// +let values = Array.zeroCreate 10 +for i = 0 to 9 do + values[i] <- i * 2 + +for value in values do + printfn $"{value}" +// The example displays the following output: +// 0 +// 2 +// 4 +// 6 +// 8 +// 10 +// 12 +// 14 +// 16 +// 18 +// \ No newline at end of file diff --git a/snippets/fsharp/System/NullReferenceException/Overview/Chain1.fs b/snippets/fsharp/System/NullReferenceException/Overview/Chain1.fs new file mode 100644 index 00000000000..11f6751a2f5 --- /dev/null +++ b/snippets/fsharp/System/NullReferenceException/Overview/Chain1.fs @@ -0,0 +1,48 @@ +module Chain1 + +// +open System + +type Page() = + [] + val mutable public URL: Uri + [] + val mutable public Title: string + +type Pages() = + let pages = Array.zeroCreate 10 + let mutable i = 0 + + member _.CurrentPage + with get () = pages[i] + and set (value) = + // Move all the page objects down to accommodate the new one. + if i > pages.GetUpperBound 0 then + for ndx = 1 to pages.GetUpperBound 0 do + pages[ndx - 1] <- pages[ndx] + + pages[i] <- value + if i < pages.GetUpperBound 0 then + i <- i + 1 + + member _.PreviousPage = + if i = 0 then + if box pages[0] = null then + Unchecked.defaultof + else + pages[0] + else + i <- i - 1 + pages[i + 1] + +let pages = Pages() +if String.IsNullOrEmpty pages.CurrentPage.Title |> not then + let title = pages.CurrentPage.Title + printfn $"Current title: '{title}'" + + +// The example displays the following output: +// Unhandled Exception: +// System.NullReferenceException: Object reference not set to an instance of an object. +// at .main() +// \ No newline at end of file diff --git a/snippets/fsharp/System/NullReferenceException/Overview/Chain2.fs b/snippets/fsharp/System/NullReferenceException/Overview/Chain2.fs new file mode 100644 index 00000000000..32fc63e7965 --- /dev/null +++ b/snippets/fsharp/System/NullReferenceException/Overview/Chain2.fs @@ -0,0 +1,46 @@ +module Chain2 + +type Page() = + [] + val mutable public URL: System.Uri + [] + val mutable public Title: string + +type Pages() = + let pages = Array.zeroCreate 10 + let mutable i = 0 + + member _.CurrentPage + with get () = pages[i] + and set (value) = + // Move all the page objects down to accommodate the new one. + if i > pages.GetUpperBound 0 then + for ndx = 1 to pages.GetUpperBound 0 do + pages[ndx - 1] <- pages[ndx] + + pages[i] <- value + if i < pages.GetUpperBound 0 then + i <- i + 1 + + member _.PreviousPage = + if i = 0 then + if box pages[0] = null then + Unchecked.defaultof + else + pages[0] + else + i <- i - 1 + pages[i + 1] + +// +let pages = Pages() +let current = pages.CurrentPage +if box current <> null then + let title = current.Title + printfn $"Current title: '{title}'" +else + printfn "There is no page information in the cache." +// The example displays the following output: +// There is no page information in the cache. +// + diff --git a/snippets/fsharp/System/NullReferenceException/Overview/example1.fs b/snippets/fsharp/System/NullReferenceException/Overview/example1.fs new file mode 100644 index 00000000000..f4e5311329c --- /dev/null +++ b/snippets/fsharp/System/NullReferenceException/Overview/example1.fs @@ -0,0 +1,23 @@ +module Example + +// +open System + +[] +let main args = + let value = Int32.Parse args[0] + // Set names to null, don't initialize it. + let mutable names = Unchecked.defaultof> + if value > 0 then + names <- ResizeArray() + names.Add "Major Major Major" + 0 +// Compilation does not display a warning as this is an extremely rare occurance in F#. +// Creating a value without initalizing either requires using 'null' (not possible +// on types defined in F# without []) or Unchecked.defaultof. +// +// The example displays output like the following output: +// Unhandled Exception: System.NullReferenceException: Object reference +// not set to an instance of an object. +// at Example.main() +// \ No newline at end of file diff --git a/snippets/fsharp/System/NullReferenceException/Overview/example1a.fs b/snippets/fsharp/System/NullReferenceException/Overview/example1a.fs new file mode 100644 index 00000000000..419ab5ebcc6 --- /dev/null +++ b/snippets/fsharp/System/NullReferenceException/Overview/example1a.fs @@ -0,0 +1,6 @@ +module example1a + +// +let names = ResizeArray() +names.Add "Major Major Major" +// \ No newline at end of file diff --git a/snippets/fsharp/System/NullReferenceException/Overview/example2.fs b/snippets/fsharp/System/NullReferenceException/Overview/example2.fs new file mode 100644 index 00000000000..bcec44fa7d8 --- /dev/null +++ b/snippets/fsharp/System/NullReferenceException/Overview/example2.fs @@ -0,0 +1,22 @@ +module example2 + +// +let populateNames (names: ResizeArray) = + let arrNames = + [ "Dakota"; "Samuel"; "Nikita" + "Koani"; "Saya"; "Yiska"; "Yumaevsky" ] + for arrName in arrNames do + names.Add arrName + +let getData () : ResizeArray = + null + +let names = getData () +populateNames names + +// The example displays output like the following: +// Unhandled Exception: System.NullReferenceException: Object reference +// not set to an instance of an object. +// at Example.PopulateNames(List`1 names) +// at .main() +// \ No newline at end of file diff --git a/snippets/fsharp/System/NullReferenceException/Overview/fs.fsproj b/snippets/fsharp/System/NullReferenceException/Overview/fs.fsproj new file mode 100644 index 00000000000..7e9513604ee --- /dev/null +++ b/snippets/fsharp/System/NullReferenceException/Overview/fs.fsproj @@ -0,0 +1,20 @@ + + + Exe + net6.0 + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/snippets/fsharp/System/NullReferenceException/Overview/nullreturn2.fs b/snippets/fsharp/System/NullReferenceException/Overview/nullreturn2.fs new file mode 100644 index 00000000000..6b7609a57d5 --- /dev/null +++ b/snippets/fsharp/System/NullReferenceException/Overview/nullreturn2.fs @@ -0,0 +1,26 @@ +module nullreturn2 + +// +open System + +type Person(firstName) = + member _.FirstName = firstName + + static member AddRange(firstNames) = + Array.map Person firstNames + +let persons = + [| "Abigail"; "Abra"; "Abraham"; "Adrian" + "Ariella"; "Arnold"; "Aston"; "Astor" |] + |> Person.AddRange + +let nameToFind = "Robert" +let found = Array.Find(persons, fun p -> p.FirstName = nameToFind) + +printfn $"{found.FirstName}" + +// The example displays the following output: +// Unhandled Exception: System.NullReferenceException: +// Object reference not set to an instance of an object. +// at .main() +// \ No newline at end of file diff --git a/snippets/fsharp/System/NullReferenceException/Overview/nullreturn2a.fs b/snippets/fsharp/System/NullReferenceException/Overview/nullreturn2a.fs new file mode 100644 index 00000000000..219d2d5fe6b --- /dev/null +++ b/snippets/fsharp/System/NullReferenceException/Overview/nullreturn2a.fs @@ -0,0 +1,40 @@ +module nullreturn2a + +// +open System + +[] +type Person(firstName) = + member _.FirstName = firstName + + static member AddRange(firstNames) = + Array.map Person firstNames + +let persons = + [| "Abigail"; "Abra"; "Abraham"; "Adrian" + "Ariella"; "Arnold"; "Aston"; "Astor" |] + |> Person.AddRange + +let nameToFind = "Robert" +let found = Array.Find(persons, fun p -> p.FirstName = nameToFind) + +if found <> null then + printfn $"{found.FirstName}" +else + printfn $"{nameToFind} not found." + +// Using F#'s Array.tryFind function +// This does not require a null check or [] +let found2 = + persons |> Array.tryFind (fun p -> p.FirstName = nameToFind) + +match found2 with +| Some firstName -> + printfn $"{firstName}" +| None -> + printfn $"{nameToFind} not found." + +// The example displays the following output: +// Robert not found. +// Robert not found. +// \ No newline at end of file diff --git a/xml/System/NullReferenceException.xml b/xml/System/NullReferenceException.xml index 2f995d90ca4..c52966e5174 100644 --- a/xml/System/NullReferenceException.xml +++ b/xml/System/NullReferenceException.xml @@ -66,21 +66,25 @@ - You've forgotten to instantiate a reference type. In the following example, `names` is declared but never instantiated: :::code language="csharp" source="~/snippets/csharp/System/NullReferenceException/Overview/example1.cs" id="Snippet1"::: + :::code language="fsharp" source="~/snippets/fsharp/System/NullReferenceException/Overview/example1.fs" id="Snippet1"::: :::code language="vb" source="~/snippets/visualbasic/VS_Snippets_CLR_System/system.nullreferenceexception.class/vb/example1.vb" id="Snippet1"::: Some compilers issue a warning when they compile this code. Others issue an error, and the compilation fails. To address this problem, instantiate the object so that its value is no longer `null`. The following example does this by calling a type's class constructor. :::code language="csharp" source="~/snippets/csharp/System/NullReferenceException/Overview/example1a.cs" id="Snippet2"::: + :::code language="fsharp" source="~/snippets/fsharp/System/NullReferenceException/Overview/example1a.fs" id="Snippet2"::: :::code language="vb" source="~/snippets/visualbasic/VS_Snippets_CLR_System/system.nullreferenceexception.class/vb/example1a.vb" id="Snippet2"::: - You've forgotten to dimension an array before initializing it. In the following example, `values` is declared to be an integer array, but the number of elements that it contains is never specified. The attempt to initialize its values therefore thrown a exception. :::code language="csharp" source="~/snippets/csharp/System/NullReferenceException/Overview/Array3.cs" id="Snippet10"::: + :::code language="fsharp" source="~/snippets/fsharp/System/NullReferenceException/Overview/Array3.fs" id="Snippet10"::: :::code language="vb" source="~/snippets/visualbasic/VS_Snippets_CLR_System/system.nullreferenceexception.class/vb/Array3.vb" id="Snippet10"::: You can eliminate the exception by declaring the number of elements in the array before initializing it, as the following example does. :::code language="csharp" source="~/snippets/csharp/System/NullReferenceException/Overview/Array4.cs" id="Snippet11"::: + :::code language="fsharp" source="~/snippets/fsharp/System/NullReferenceException/Overview/Array4.fs" id="Snippet11"::: :::code language="vb" source="~/snippets/visualbasic/VS_Snippets_CLR_System/system.nullreferenceexception.class/vb/Array4.vb" id="Snippet11"::: For more information on declaring and initializing arrays, see [Arrays](/dotnet/csharp/programming-guide/arrays/) and [Arrays](/dotnet/visual-basic/programming-guide/language-features/arrays/). @@ -90,11 +94,13 @@ The code in the following example assumes that the method always returns `Person` object whose `FirstName` field matches a search string. Because there is no match, the runtime throws a exception. :::code language="csharp" source="~/snippets/csharp/System/NullReferenceException/Overview/nullreturn2.cs" id="Snippet4"::: + :::code language="fsharp" source="~/snippets/fsharp/System/NullReferenceException/Overview/nullreturn2.fs" id="Snippet4"::: :::code language="vb" source="~/snippets/visualbasic/VS_Snippets_CLR_System/system.nullreferenceexception.class/vb/nullreturn2.vb" id="Snippet4"::: To address this problem, test the method's return value to ensure that it is not `null` before calling any of its members, as the following example does. :::code language="csharp" source="~/snippets/csharp/System/NullReferenceException/Overview/nullreturn2a.cs" id="Snippet5"::: + :::code language="fsharp" source="~/snippets/fsharp/System/NullReferenceException/Overview/nullreturn2a.fs" id="Snippet5"::: :::code language="vb" source="~/snippets/visualbasic/VS_Snippets_CLR_System/system.nullreferenceexception.class/vb/nullreturn2a.vb" id="Snippet5"::: - You're using an expression (for example, you're chaining a list of methods or properties together) to retrieve a value and, although you're checking whether the value is `null`, the runtime still throws a exception. This occurs because one of the intermediate values in the expression returns `null`. As a result, your test for `null` is never evaluated. @@ -102,11 +108,13 @@ The following example defines a `Pages` object that caches information about web pages, which are presented by `Page` objects. The `Example.Main` method checks whether the current web page has a non-null title and, if it does, displays the title. Despite this check, however, the method throws a exception. :::code language="csharp" source="~/snippets/csharp/System/NullReferenceException/Overview/Chain1.cs" id="Snippet6"::: + :::code language="fsharp" source="~/snippets/fsharp/System/NullReferenceException/Overview/Chain1.fs" id="Snippet6"::: :::code language="vb" source="~/snippets/visualbasic/VS_Snippets_CLR_System/system.nullreferenceexception.class/vb/Chain1.vb" id="Snippet6"::: The exception is thrown because `pages.CurrentPage` returns `null` if no page information is stored in the cache. This exception can be corrected by testing the value of the `CurrentPage` property before retrieving the current `Page` object's `Title` property, as the following example does: :::code language="csharp" source="~/snippets/csharp/System/NullReferenceException/Overview/Chain2.cs" id="Snippet7"::: + :::code language="fsharp" source="~/snippets/fsharp/System/NullReferenceException/Overview/Chain2.fs" id="Snippet7"::: :::code language="vb" source="~/snippets/visualbasic/VS_Snippets_CLR_System/system.nullreferenceexception.class/vb/Chain2.vb" id="Snippet7"::: - You're enumerating the elements of an array that contains reference types, and your attempt to process one of the elements throws a exception. @@ -114,16 +122,19 @@ The following example defines a string array. A `for` statement enumerates the elements in the array and calls each string's method before displaying the string. :::code language="csharp" source="~/snippets/csharp/System/NullReferenceException/Overview/Array1.cs" id="Snippet8"::: + :::code language="fsharp" source="~/snippets/fsharp/System/NullReferenceException/Overview/Array1.fs" id="Snippet8"::: :::code language="vb" source="~/snippets/visualbasic/VS_Snippets_CLR_System/system.nullreferenceexception.class/vb/Array1.vb" id="Snippet8"::: This exception occurs if you assume that each element of the array must contain a non-null value, and the value of the array element is in fact `null`. The exception can be eliminated by testing whether the element is `null` before performing any operation on that element, as the following example shows. :::code language="csharp" source="~/snippets/csharp/System/NullReferenceException/Overview/Array2.cs" id="Snippet9"::: + :::code language="fsharp" source="~/snippets/fsharp/System/NullReferenceException/Overview/Array2.fs" id="Snippet9"::: :::code language="vb" source="~/snippets/visualbasic/VS_Snippets_CLR_System/system.nullreferenceexception.class/vb/Array2.vb" id="Snippet9"::: - A exception is thrown by a method that is passed `null`. Some methods validate the arguments that are passed to them. If they do and one of the arguments is `null`, the method throws an exception. Otherwise, it throws a exception. The following example illustrates this scenario. :::code language="csharp" source="~/snippets/csharp/System/NullReferenceException/Overview/example2.cs" id="Snippet3"::: + :::code language="fsharp" source="~/snippets/fsharp/System/NullReferenceException/Overview/example2.fs" id="Snippet3"::: :::code language="vb" source="~/snippets/visualbasic/VS_Snippets_CLR_System/system.nullreferenceexception.class/vb/example2.vb" id="Snippet3"::: To address this issue, make sure that the argument passed to the method is not `null`, or handle the thrown exception in a `try…catch…finally` block. For more information, see [Exceptions](/dotnet/standard/exceptions/).