Skip to content

Commit c544fe6

Browse files
authored
System.Exception F# snippets (#7725)
* Exception F# snippets * fix link
1 parent ce56e17 commit c544fe6

File tree

27 files changed

+1072
-3
lines changed

27 files changed

+1072
-3
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<OutputType>Exe</OutputType>
4+
<TargetFramework>net48</TargetFramework>
5+
</PropertyGroup>
6+
7+
<ItemGroup>
8+
<Compile Include="new.fs" />
9+
<Compile Include="news.fs" />
10+
<Compile Include="getobjdata.fs" />
11+
<Compile Include="newsi.fs" />
12+
</ItemGroup>
13+
14+
<ItemGroup>
15+
<Reference Include="System.Runtime.Serialization.Formatters.Soap" />
16+
</ItemGroup>
17+
</Project>
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
module NDP_UE_FS_3
2+
3+
//<Snippet1>
4+
open System
5+
open System.IO
6+
open System.Runtime.Serialization
7+
open System.Runtime.Serialization.Formatters.Soap
8+
open System.Security.Permissions
9+
10+
// Define a serializable derived exception class.
11+
[<Serializable>]
12+
type SecondLevelException =
13+
inherit Exception
14+
15+
interface ISerializable with
16+
// GetObjectData performs a custom serialization.
17+
[<SecurityPermissionAttribute(SecurityAction.Demand,SerializationFormatter=true)>]
18+
member this.GetObjectData(info: SerializationInfo, context: StreamingContext) =
19+
// Change the case of two properties, and then use the
20+
// method of the base class.
21+
this.HelpLink <- this.HelpLink.ToLower()
22+
this.Source <- this.Source.ToUpperInvariant()
23+
24+
base.GetObjectData( info, context )
25+
// This public constructor is used by class instantiators.
26+
new (message: string, inner: Exception) as this =
27+
{ inherit Exception(message, inner) }
28+
then
29+
this.HelpLink <- "http://MSDN.Microsoft.com"
30+
this.Source <- "Exception_Class_Samples"
31+
32+
// This protected constructor is used for deserialization.
33+
new (info: SerializationInfo, context: StreamingContext) =
34+
{ inherit Exception(info, context) }
35+
36+
printfn
37+
"""This example of the Exception constructor and Exception.GetObjectData
38+
with SerializationInfo and StreamingContext parameters generates
39+
the following output.
40+
"""
41+
42+
try
43+
// This code forces a division by 0 and catches the
44+
// resulting exception.
45+
try
46+
let zero = 0
47+
let ecks = 1 / zero
48+
()
49+
with ex ->
50+
// Create a new exception to throw again.
51+
let newExcept = SecondLevelException("Forced a division by 0 and threw another exception.", ex)
52+
53+
printfn "Forced a division by 0, caught the resulting exception, \nand created a derived exception:\n"
54+
printfn $"HelpLink: {newExcept.HelpLink}"
55+
printfn $"Source: {newExcept.Source}"
56+
57+
// This FileStream is used for the serialization.
58+
use stream = new FileStream("NewException.dat", FileMode.Create)
59+
60+
try
61+
// Serialize the derived exception.
62+
let formatter = SoapFormatter(null, StreamingContext StreamingContextStates.File)
63+
formatter.Serialize(stream, newExcept)
64+
65+
// Rewind the stream and deserialize the
66+
// exception.
67+
stream.Position <- 0L
68+
let deserExcept = formatter.Deserialize stream :?> SecondLevelException
69+
70+
printfn
71+
"""
72+
Serialized the exception, and then deserialized the resulting stream into a
73+
new exception. The deserialization changed the case of certain properties:
74+
"""
75+
76+
// Throw the deserialized exception again.
77+
raise deserExcept
78+
with :? SerializationException as se ->
79+
printfn $"Failed to serialize: {se}"
80+
81+
with ex ->
82+
printfn $"HelpLink: {ex.HelpLink}"
83+
printfn $"Source: {ex.Source}"
84+
printfn $"\n{ex}"
85+
86+
// This example displays the following output.
87+
// Forced a division by 0, caught the resulting exception,
88+
// and created a derived exception:
89+
//
90+
// HelpLink: http://MSDN.Microsoft.com
91+
// Source: Exception_Class_Samples
92+
//
93+
// Serialized the exception, and then deserialized the resulting stream into a
94+
// new exception. The deserialization changed the case of certain properties:
95+
//
96+
// HelpLink: http://msdn.microsoft.com
97+
// Source: EXCEPTION_CLASS_SAMPLES
98+
//
99+
// NDP_UE_FS_3+SecondLevelException: Forced a division by 0 and threw another except
100+
// ion. ---> System.DivideByZeroException: Attempted to divide by zero.
101+
// at <StartupCode$fs>.$NDP_UE_FS_3.main@()
102+
// --- End of inner exception stack trace ---
103+
// at <StartupCode$fs>.$NDP_UE_FS_3.main@()
104+
//</Snippet1>
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
module NDP_UE_FS
2+
3+
//<Snippet1>
4+
// Example for the Exception() constructor.
5+
open System
6+
7+
// Derive an exception with a predefined message.
8+
type NotEvenException() =
9+
inherit Exception "The argument to a function requiring even input is not divisible by 2."
10+
11+
// half throws a base exception if the input is not even.
12+
let half input =
13+
if input % 2 <> 0 then
14+
raise (Exception())
15+
else input / 2
16+
17+
// half2 throws a derived exception if the input is not even.
18+
let half2 input =
19+
if input % 2 <> 0 then
20+
raise (NotEvenException())
21+
else input / 2
22+
23+
// calcHalf calls Half and catches any thrown exceptions.
24+
let calcHalf input =
25+
try
26+
let halfInput = half input
27+
printfn $"Half of {input} is {halfInput}."
28+
with ex ->
29+
printfn $"{ex}"
30+
31+
// calcHalf2 calls Half2 and catches any thrown exceptions.
32+
let calcHalf2 input =
33+
try
34+
let halfInput = half2 input
35+
printfn $"Half of {input} is {halfInput}."
36+
with ex ->
37+
printfn $"{ex}"
38+
39+
printfn "This example of the Exception() constructor generates the following output."
40+
printfn "\nHere, an exception is thrown using the \nparameterless constructor of the base class.\n"
41+
42+
calcHalf 12
43+
calcHalf 15
44+
45+
printfn "\nHere, an exception is thrown using the \nparameterless constructor of a derived class.\n"
46+
47+
calcHalf2 24
48+
calcHalf2 27
49+
50+
51+
// This example of the Exception() constructor generates the following output.
52+
// Here, an exception is thrown using the
53+
// parameterless constructor of the base class.
54+
//
55+
// Half of 12 is 6.
56+
// System.Exception: Exception of type 'System.Exception' was thrown.
57+
// at NDP_UE_FS.half(Int32 input)
58+
// at at NDP_UE_FS.calcHalf(Int32 input)
59+
//
60+
// Here, an exception is thrown using the
61+
// parameterless constructor of a derived class.
62+
//
63+
// Half of 24 is 12.
64+
// NDP_UE_FS+NotEvenException: The argument to a function requiring even input is
65+
// not divisible by 2.
66+
// at NDP_UE_FS.half2(Int32 input)
67+
// at NDP_UE_FS.calcHalf2(Int32 input)
68+
//</Snippet1>
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
module NDP_UE_FS_2
2+
3+
//<Snippet2>
4+
// Example for the Exception(string) constructor.
5+
open System
6+
7+
let notEvenMessage = "The argument to a function requiring even input is not divisible by 2."
8+
9+
// Derive an exception with a specifiable message.
10+
type NotEvenException =
11+
inherit Exception
12+
new () = { inherit Exception(notEvenMessage) }
13+
new (auxMessage) = { inherit Exception($"{auxMessage} - {notEvenMessage}") }
14+
15+
// half throws a base exception if the input is not even.
16+
let half input =
17+
if input % 2 <> 0 then
18+
raise (Exception $"The argument {input} is not divisible by 2.")
19+
else input / 2
20+
21+
// half2 throws a derived exception if the input is not even.
22+
let half2 input =
23+
if input % 2 <> 0 then
24+
raise (NotEvenException $"Invalid argument: {input}")
25+
else input / 2
26+
27+
// calcHalf calls Half and catches any thrown exceptions.
28+
let calcHalf input =
29+
try
30+
let halfInput = half input
31+
printfn $"Half of {input} is {halfInput}."
32+
with ex ->
33+
printfn $"{ex}"
34+
35+
// calcHalf2 calls Half2 and catches any thrown exceptions.
36+
let calcHalf2 input =
37+
try
38+
let halfInput = half2 input
39+
printfn $"Half of {input} is {halfInput}."
40+
with ex ->
41+
printfn $"{ex}"
42+
43+
printfn "This example of the Exception(string)\nconstructor generates the following output."
44+
printfn "\nHere, an exception is thrown using the \nconstructor of the base class.\n"
45+
46+
calcHalf 18
47+
calcHalf 21
48+
49+
printfn "\nHere, an exception is thrown using the \nconstructor of a derived class.\n"
50+
51+
calcHalf2 30
52+
calcHalf2 33
53+
54+
55+
// This example of the Exception(string)
56+
// constructor generates the following output.
57+
//
58+
// Here, an exception is thrown using the
59+
// constructor of the base class.
60+
//
61+
// Half of 18 is 9.
62+
// System.Exception: The argument 21 is not divisible by 2.
63+
// at NDP_UE_FS_2.half(Int32 input)
64+
// at NDP_UE_FS_2.calcHalf(Int32 input)
65+
//
66+
// Here, an exception is thrown using the
67+
// constructor of a derived class.
68+
//
69+
// Half of 30 is 15.
70+
// NDP_UE_FS_2+NotEvenException: Invalid argument: 33 - The argument to a function r
71+
// equiring even input is not divisible by 2.
72+
// at NDP_UE_FS_2.half2(Int32 input)
73+
// at NDP_UE_FS_2.calcHalf2(Int32 input)
74+
//</Snippet2>
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
module NDP_UE_FS_4
2+
3+
//<Snippet3>
4+
// Example for the Exception(string, Exception) constructor.
5+
open System
6+
7+
let overflowMessage = "The log table has overflowed."
8+
9+
// Derive an exception with a specifiable message and inner exception.
10+
type LogTableOverflowException =
11+
inherit Exception
12+
13+
new () = { inherit Exception(overflowMessage) }
14+
15+
new (auxMessage: string) =
16+
{ inherit Exception($"{overflowMessage} - {auxMessage}") }
17+
18+
new (auxMessage: string, inner: Exception) =
19+
{ inherit Exception($"{overflowMessage} - {auxMessage}", inner ) }
20+
21+
type LogTable(numElements: int) =
22+
let mutable logArea = Array.zeroCreate<string> numElements
23+
let mutable elemInUse = 0
24+
25+
// The AddRecord method throws a derived exception
26+
// if the array bounds exception is caught.
27+
member _.AddRecord(newRecord: string): int =
28+
try
29+
logArea[elemInUse] <- newRecord
30+
elemInUse <- elemInUse + 1
31+
elemInUse - 1
32+
with ex ->
33+
raise (LogTableOverflowException($"Record \"{newRecord}\" was not logged.", ex ) )
34+
35+
// Create a log table and force an overflow.
36+
let log = LogTable 4
37+
38+
printfn "This example of the Exception(string, Exception)\nconstructor generates the following output."
39+
printfn "\nExample of a derived exception that references an inner exception:\n"
40+
try
41+
for count = 1 to 1000 do
42+
log.AddRecord $"Log record number {count}"
43+
|> ignore
44+
with ex ->
45+
printfn $"{ex}"
46+
47+
48+
// This example of the Exception(string, Exception)
49+
// constructor generates the following output.
50+
//
51+
// Example of a derived exception that references an inner exception:
52+
//
53+
// NDP_UE_FS_4+LogTableOverflowException: The log table has overflowed. - Record "Lo
54+
// g record number 5" was not logged. ---> System.IndexOutOfRangeException: Index
55+
// was outside the bounds of the array.
56+
// at NDP_UE_FS_4.LogTable.AddRecord(String newRecord)
57+
// --- End of inner exception stack trace ---
58+
// at NDP_UE_FS_4.LogTable.AddRecord(String newRecord)
59+
// at <StartupCode$fs>.$NDP_UE_FS_4.main@()
60+
//</Snippet3>
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
//<snippet1>
2+
// This example demonstrates the Exception.Data property.
3+
open System
4+
open System.Collections
5+
6+
let nestedRoutine2 displayDetails =
7+
let e = Exception "This statement is the original exception message."
8+
if displayDetails then
9+
let s = "Information from nestedRoutine2."
10+
let i = -903
11+
let dt = DateTime.Now
12+
e.Data.Add("stringInfo", s)
13+
e.Data["IntInfo"] <- i
14+
e.Data["DateTimeInfo"] <- dt
15+
raise e
16+
17+
let nestedRoutine1 displayDetails =
18+
try
19+
nestedRoutine2 displayDetails
20+
with e ->
21+
e.Data["ExtraInfo"] <- "Information from nestedRoutine1."
22+
e.Data.Add("MoreExtraInfo", "More information from nestedRoutine1.")
23+
reraise ()
24+
25+
let runTest displayDetails =
26+
try
27+
nestedRoutine1 displayDetails
28+
with e ->
29+
printfn "An exception was thrown."
30+
printfn $"{e.Message}"
31+
if e.Data.Count > 0 then
32+
printfn " Extra details:"
33+
for de in e.Data do
34+
let de = de :?> DictionaryEntry
35+
printfn $""" Key: {"'" + de.Key.ToString() + "'",-20} Value: {de.Value}"""
36+
37+
printfn "\nException with some extra information..."
38+
runTest false
39+
printfn "\nException with all extra information..."
40+
runTest true
41+
42+
43+
// The example displays the following output:
44+
// Exception with some extra information...
45+
// An exception was thrown.
46+
// This statement is the original exception message.
47+
// Extra details:
48+
// Key: 'ExtraInfo' Value: Information from NestedRoutine1.
49+
// Key: 'MoreExtraInfo' Value: More information from NestedRoutine1.
50+
//
51+
// Exception with all extra information...
52+
// An exception was thrown.
53+
// This statement is the original exception message.
54+
// Extra details:
55+
// Key: 'stringInfo' Value: Information from NestedRoutine2.
56+
// Key: 'IntInfo' Value: -903
57+
// Key: 'DateTimeInfo' Value: 7/29/2013 10:50:13 AM
58+
// Key: 'ExtraInfo' Value: Information from NestedRoutine1.
59+
// Key: 'MoreExtraInfo' Value: More information from NestedRoutine1.
60+
//</snippet1>

0 commit comments

Comments
 (0)