Skip to content

Commit 47d8dff

Browse files
authored
Add F# snippets for System.AppContext (dotnet#7425)
1 parent b3e0379 commit 47d8dff

File tree

8 files changed

+163
-0
lines changed

8 files changed

+163
-0
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
module Example4
2+
3+
// <Snippet4>
4+
open System
5+
open System.Reflection
6+
7+
[<assembly: AssemblyVersion("1.0.0.0")>]
8+
do ()
9+
10+
module StringLibrary =
11+
let substringStartsAt (fullString: string) (substr: string) =
12+
fullString.IndexOf(substr, StringComparison.Ordinal)
13+
14+
// </Snippet4>
15+
16+
// <Snippet5>
17+
let value = "The archaeologist"
18+
let substring = "archæ"
19+
20+
let position =
21+
StringLibrary.substringStartsAt value substring
22+
23+
if position >= 0 then
24+
printfn $"'{substring}' found in '{value}' starting at position {position}"
25+
else
26+
printfn $"'{substring}' not found in '{value}'"
27+
28+
// The example displays the following output:
29+
// 'archæ' not found in 'The archaeologist'
30+
// </Snippet5>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
module Example6
2+
3+
// <Snippet6>
4+
open System
5+
open System.Reflection
6+
7+
[<assembly: AssemblyVersion("2.0.0.0")>]
8+
do ()
9+
10+
module StringLibrary =
11+
let substringStartsAt (fullString: string) (substr: string) =
12+
fullString.IndexOf(substr, StringComparison.CurrentCulture)
13+
14+
// </Snippet6>
15+
16+
// <Snippet7>
17+
let value = "The archaeologist"
18+
let substring = "archæ"
19+
20+
let position =
21+
StringLibrary.substringStartsAt value substring
22+
23+
if position >= 0 then
24+
printfn $"'{substring}' found in '{value}' starting at position {position}"
25+
else
26+
printfn $"'{substring}' not found in '{value}'"
27+
28+
// The example displays the following output:
29+
// 'archæ' found in 'The archaeologist' starting at position 4
30+
// </Snippet7>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
module Example8
2+
3+
// <Snippet8>
4+
open System
5+
open System.Reflection
6+
7+
[<assembly: AssemblyVersion("2.0.0.0")>]
8+
do ()
9+
10+
AppContext.SetSwitch("StringLibrary.DoNotUseCultureSensitiveComparison",true)
11+
12+
module StringLibrary =
13+
let substringStartsAt (fullString: string) (substr: string) =
14+
match AppContext.TryGetSwitch "StringLibrary.DoNotUseCultureSensitiveComparison" with
15+
| true, true -> fullString.IndexOf(substr, StringComparison.Ordinal)
16+
| _ -> fullString.IndexOf(substr, StringComparison.CurrentCulture)
17+
18+
// </Snippet8>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// <Snippet10>
2+
module Example
3+
4+
open System.IO
5+
open System.Runtime.Versioning
6+
7+
[<assembly: TargetFramework(".NETFramework,Version=v4.6.2")>]
8+
do ()
9+
10+
Path.GetDirectoryName "file://c/temp/dirlist.txt"
11+
|> printfn "%s"
12+
13+
14+
// The example displays the following output:
15+
// Unhandled Exception: System.ArgumentException: The path is not of a legal form.
16+
// at System.IO.Path.NewNormalizePathLimitedChecks(String path, Int32 maxPathLength, Boolean expandShortPaths)
17+
// at System.IO.Path.NormalizePath(String path, Boolean fullCheck, Int32 maxPathLength, Boolean expandShortPaths)
18+
// at System.IO.Path.InternalGetDirectoryName(String path)
19+
// at <StartupCode$ForConsumers1>.$Example.main@()
20+
// </Snippet10>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net6.0</TargetFramework>
6+
</PropertyGroup>
7+
8+
<ItemGroup>
9+
<Compile Include="..\ForConsumers1.fs" />
10+
</ItemGroup>
11+
12+
</Project>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
module TestValue1
2+
3+
open System
4+
5+
// <Snippet1>
6+
AppContext.SetSwitch("Switch.AmazingLib.ThrowOnException", true)
7+
// </Snippet1>
8+
9+
// <Snippet2>
10+
module AmazingLib =
11+
let performAnOperation () =
12+
match AppContext.TryGetSwitch "Switch.AmazingLib.ThrowOnException" with
13+
| false, _ ->
14+
// This is the case where the switch value was not set by the application.
15+
// The library can choose to get the value of shouldThrow by other means.
16+
// If no overrides or default values are specified, the value should be 'false'.
17+
// A false value implies the latest behavior.
18+
()
19+
| true, shouldThrow ->
20+
// The library can use the value of shouldThrow to throw exceptions or not.
21+
if shouldThrow then
22+
// old code
23+
()
24+
else
25+
// new code
26+
()
27+
// </Snippet2>
28+
29+
AmazingLib.performAnOperation ()
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net6.0</TargetFramework>
6+
</PropertyGroup>
7+
8+
<ItemGroup>
9+
<Compile Include="TestValue1.fs" />
10+
<Compile Include="Example4.fs" />
11+
<Compile Include="Example6.fs" />
12+
<Compile Include="Example8.fs" />
13+
<Compile Include="ForConsumers1.fs" />
14+
</ItemGroup>
15+
16+
</Project>

xml/System/AppContext.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,26 +73,31 @@
7373
The following example illustrates the use of the <xref:System.AppContext> class to allow the customer to choose the original behavior of a library method. The following is version 1.0 of a library named `StringLibrary`. It defines a `SubstringStartsAt` method that performs an ordinal comparison to determine the starting index of a substring within a larger string.
7474
7575
:::code language="csharp" source="~/samples/snippets/csharp/VS_Snippets_CLR_System/System.AppContext.Class/cs/Example4.cs" id="Snippet4":::
76+
:::code language="fsharp" source="~/samples/snippets/fsharp/VS_Snippets_CLR_System/System.AppContext.Class/fs/Example4.fs" id="Snippet4":::
7677
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR_System/System.AppContext.Class/vb/Example4.vb" id="Snippet4":::
7778
7879
The following example then uses the library to find the starting index of the substring "archæ" in "The archaeologist". Because the method performs an ordinal comparison, the substring cannot be found.
7980
8081
:::code language="csharp" source="~/samples/snippets/csharp/VS_Snippets_CLR_System/System.AppContext.Class/cs/Example4.cs" id="Snippet5":::
82+
:::code language="fsharp" source="~/samples/snippets/fsharp/VS_Snippets_CLR_System/System.AppContext.Class/fs/Example4.fs" id="Snippet5":::
8183
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR_System/System.AppContext.Class/vb/Example4.vb" id="Snippet5":::
8284
8385
Version 2 of the library, however, changes the `SubstringStartsAt` method to use culture-sensitive comparison.
8486
8587
:::code language="csharp" source="~/samples/snippets/csharp/VS_Snippets_CLR_System/System.AppContext.Class/cs/Example6.cs" id="Snippet6":::
88+
:::code language="fsharp" source="~/samples/snippets/fsharp/VS_Snippets_CLR_System/System.AppContext.Class/fs/Example6.fs" id="Snippet6":::
8689
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR_System/System.AppContext.Class/vb/Example6.vb" id="Snippet6":::
8790
8891
When the app is recompiled to run against the new version of the library, it now reports that the substring "archæ" is found at index 4 in "The archaeologist".
8992
9093
:::code language="csharp" source="~/samples/snippets/csharp/VS_Snippets_CLR_System/System.AppContext.Class/cs/Example6.cs" id="Snippet7":::
94+
:::code language="fsharp" source="~/samples/snippets/fsharp/VS_Snippets_CLR_System/System.AppContext.Class/fs/Example6.fs" id="Snippet7":::
9195
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR_System/System.AppContext.Class/vb/Example6.vb" id="Snippet7":::
9296
9397
This change can be prevented from breaking the applications that depend on the original behavior by defining an [\<AppContextSwitchOverrides>](/dotnet/framework/configure-apps/file-schema/runtime/appcontextswitchoverrides-element) switch. In this case, the switch is named `StringLibrary.DoNotUseCultureSensitiveComparison`. Its default value, `false`, indicates that the library should perform its version 2.0 culture-sensitive comparison. `true` indicates that the library should perform its version 1.0 ordinal comparison. A slight modification of the previous code allows the library consumer to set the switch to determine the kind of comparison the method performs.
9498
9599
:::code language="csharp" source="~/samples/snippets/csharp/VS_Snippets_CLR_System/System.AppContext.Class/cs/Example8.cs" id="Snippet8":::
100+
:::code language="fsharp" source="~/samples/snippets/fsharp/VS_Snippets_CLR_System/System.AppContext.Class/fs/Example8.fs" id="Snippet8":::
96101
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR_System/System.AppContext.Class/vb/Example8.vb" id="Snippet8":::
97102
98103
If application can then use the following configuration file to restore the version 1.0 behavior.
@@ -162,6 +167,7 @@ If you set the same switch in more than one way, the order of precedence for det
162167
The following is a simple application that passes a file URI to the <xref:System.IO.Path.GetDirectoryName%2A?displayProperty=nameWithType> method. When run under the .NET Framework 4.6, it throws an <xref:System.ArgumentException> because `file://` is no longer a valid part of a file path.
163168
164169
:::code language="csharp" source="~/samples/snippets/csharp/VS_Snippets_CLR_System/System.AppContext.Class/cs/ForConsumers1.cs" id="Snippet10":::
170+
:::code language="fsharp" source="~/samples/snippets/fsharp/VS_Snippets_CLR_System/System.AppContext.Class/fs/ForConsumers1.fs" id="Snippet10":::
165171
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR_System/System.AppContext.Class/vb/ForConsumers1.vb" id="Snippet10":::
166172
167173
To restore the method's previous behavior and prevent the exception, you can add the `Switch.System.IO.UseLegacyPathHandling` switch to the application configuration file for the example:
@@ -370,6 +376,7 @@ In .NET 5 and later versions, for bundled assemblies, the value returned is the
370376
The following line of code sets a switch named `Switch.AmazingLib.ThrowOnException` to `true`, which enables a legacy behavior. The library can then check whether a library consumer has set the value of the switch by calling the <xref:System.AppContext.TryGetSwitch%2A> method.
371377
372378
:::code language="csharp" source="~/samples/snippets/csharp/VS_Snippets_CLR_System/System.AppContext.Class/cs/TestValue1.cs" id="Snippet1":::
379+
:::code language="fsharp" source="~/samples/snippets/fsharp/VS_Snippets_CLR_System/System.AppContext.Class/fs/TestValue1.fs" id="Snippet1":::
373380
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR_System/System.AppContext.Class/vb/TestValue1.vb" id="Snippet1":::
374381
375382
]]></format>
@@ -494,6 +501,7 @@ In .NET 5 and later versions, for bundled assemblies, the value returned is the
494501
The following example determines whether a library consumer has set a switch named `Switch.AmazingLib.ThrowOnException`.
495502
496503
:::code language="csharp" source="~/samples/snippets/csharp/VS_Snippets_CLR_System/System.AppContext.Class/cs/TestValue1.cs" id="Snippet2":::
504+
:::code language="fsharp" source="~/samples/snippets/fsharp/VS_Snippets_CLR_System/System.AppContext.Class/fs/TestValue1.fs" id="Snippet2":::
497505
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR_System/System.AppContext.Class/vb/TestValue1.vb" id="Snippet2":::
498506
499507
]]></format>

0 commit comments

Comments
 (0)