This article provides supplementary remarks to the reference documentation for this API.
The AppContext class enables library writers to provide a uniform opt-out mechanism for new functionality for their users. It establishes a loosely coupled contract between components in order to communicate an opt-out request. This capability is typically important when a change is made to existing functionality. Conversely, there is already an implicit opt-in for new functionality.
AppContext for library developers
Libraries use the AppContext class to define and expose compatibility switches, while library users can set those switches to affect the library behavior. By default, libraries provide the new functionality, and they only alter it (that is, they provide the previous functionality) if the switch is set. This allows libraries to provide new behavior for an existing API while continuing to support callers who depend on the previous behavior.
Define the switch name
The most common way to allow consumers of your library to opt out of a change of behavior is to define a named switch. Its value element is a name/value pair that consists of the name of a switch and its Boolean value. By default, the switch is always implicitly false, which provides the new behavior (and makes the new behavior opt-in by default). Setting the switch to true enables it, which provides the legacy behavior. Explicitly setting the switch to false also provides the new behavior.
It's beneficial to use a consistent format for switch names, since they're a formal contract exposed by a library. The following are two obvious formats:
Switch.namespace.switchname
Switch.library.switchname
Once you define and document the switch, callers can use it by calling the AppContext.SetSwitch(String, Boolean) method programmatically. .NET Framework apps can also use the switch by adding an <AppContextSwitchOverrides> element to their application configuration file or by using the registry. For more information about how callers use and set the value of AppContext configuration switches, see the AppContext for library consumers section.
In .NET Framework, when the common language runtime runs an application, it automatically reads the registry's compatibility settings and loads the application configuration file to populate the application's AppContext instance. Because the AppContext instance is populated either programmatically by the caller or by the runtime, .NET Framework apps don't have to take any action, such as calling the SetSwitch method, to configure the AppContext instance.
Check the setting
You can check if a consumer has declared the value of the switch and act appropriately by calling the AppContext.TryGetSwitch method. The method returns true if the switchName argument is found, and its isEnabled argument indicates the value of the switch. Otherwise, the method returns false.
Example
The following example illustrates the use of the 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.
C#
using System;
using System.Reflection;
[assembly: AssemblyVersion("1.0.0.0")]
publicstaticclassStringLibrary1
{
publicstaticintSubstringStartsAt(string fullString, string substr)
{
return fullString.IndexOf(substr, StringComparison.Ordinal);
}
}
open System
open System.Reflection
[<assembly: AssemblyVersion("1.0.0.0")>]
do ()
module StringLibrary =
let substringStartsAt (fullString: string) (substr: string) =
fullString.IndexOf(substr, StringComparison.Ordinal)
Imports System.Reflection
<Assembly: AssemblyVersion("1.0.0.0")>
Public Class StringLibrary
Public Shared Function SubstringStartsAt(fullString As String, substr As String) As Integer
Return fullString.IndexOf(substr, StringComparison.Ordinal)
End Function
End Class
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.
C#
using System;
publicclassExample1
{
publicstaticvoidMain()
{
stringvalue = "The archaeologist";
string substring = "archæ";
int position = StringLibrary1.SubstringStartsAt(value, substring);
if (position >= 0)
Console.WriteLine("'{0}' found in '{1}' starting at position {2}",
substring, value, position);
else
Console.WriteLine("'{0}' not found in '{1}'", substring, value);
}
}
// The example displays the following output:// 'archæ' not found in 'The archaeologist'
let value = "The archaeologist"
let substring = "archæ"
let position =
StringLibrary.substringStartsAt value substring
if position >= 0 then
printfn $"'{substring}' found in '{value}' starting at position {position}"
else
printfn $"'{substring}' not found in '{value}'"
// The example displays the following output:
// 'archæ' not found in 'The archaeologist'
Public Module Example4
Public Sub Main()
Dim value As String = "The archaeologist"
Dim substring As String = "archæ"
Dim position As Integer = StringLibrary.SubstringStartsAt(value, substring)
If position >= 0 Then
Console.WriteLine("'{0}' found in '{1}' starting at position {2}",
substring, value, position)
Else
Console.WriteLine("'{0}' not found in '{1}'", substring, value)
End If
End Sub
End Module
' The example displays the following output:
' 'archæ' not found in 'The archaeologist'
Version 2.0 of the library, however, changes the SubstringStartsAt method to use culture-sensitive comparison.
C#
using System;
using System.Reflection;
[assembly: AssemblyVersion("2.0.0.0")]
publicstaticclassStringLibrary2
{
publicstaticintSubstringStartsAt(string fullString, string substr)
{
return fullString.IndexOf(substr, StringComparison.CurrentCulture);
}
}
open System
open System.Reflection
[<assembly: AssemblyVersion("2.0.0.0")>]
do ()
module StringLibrary =
let substringStartsAt (fullString: string) (substr: string) =
fullString.IndexOf(substr, StringComparison.CurrentCulture)
Imports System.Reflection
<Assembly: AssemblyVersion("2.0.0.0")>
Public Class StringLibrary
Public Shared Function SubstringStartsAt(fullString As String, substr As String) As Integer
Return fullString.IndexOf(substr, StringComparison.CurrentCulture)
End Function
End Class
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".
C#
using System;
publicclassExample2
{
publicstaticvoidMain()
{
stringvalue = "The archaeologist";
string substring = "archæ";
int position = StringLibrary2.SubstringStartsAt(value, substring);
if (position >= 0)
Console.WriteLine("'{0}' found in '{1}' starting at position {2}",
substring, value, position);
else
Console.WriteLine("'{0}' not found in '{1}'", substring, value);
}
}
// The example displays the following output:// 'archæ' found in 'The archaeologist' starting at position 4
let value = "The archaeologist"
let substring = "archæ"
let position =
StringLibrary.substringStartsAt value substring
if position >= 0 then
printfn $"'{substring}' found in '{value}' starting at position {position}"
else
printfn $"'{substring}' not found in '{value}'"
// The example displays the following output:
// 'archæ' found in 'The archaeologist' starting at position 4
Public Module Example6
Public Sub Main()
Dim value As String = "The archaeologist"
Dim substring As String = "archæ"
Dim position As Integer = StringLibrary.SubstringStartsAt(value, substring)
If position >= 0 Then
Console.WriteLine("'{0}' found in '{1}' starting at position {2}",
substring, value, position)
Else
Console.WriteLine("'{0}' not found in '{1}'", substring, value)
End If
End Sub
End Module
' The example displays the following output:
' 'archæ' found in 'The archaeologist' starting at position 4
This change can be prevented from breaking the applications that depend on the original behavior by defining a 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.
C#
using System;
using System.Reflection;
[assembly: AssemblyVersion("2.0.0.0")]
publicstaticclassStringLibrary
{
publicstaticintSubstringStartsAt(string fullString, string substr)
{
bool flag;
if (AppContext.TryGetSwitch("StringLibrary.DoNotUseCultureSensitiveComparison", out flag) && flag == true)
return fullString.IndexOf(substr, StringComparison.Ordinal);
elsereturn fullString.IndexOf(substr, StringComparison.CurrentCulture);
}
}
open System
open System.Reflection
[<assembly: AssemblyVersion("2.0.0.0")>]
do ()
AppContext.SetSwitch("StringLibrary.DoNotUseCultureSensitiveComparison",true)
module StringLibrary =
let substringStartsAt (fullString: string) (substr: string) =
match AppContext.TryGetSwitch "StringLibrary.DoNotUseCultureSensitiveComparison" with
| true, true -> fullString.IndexOf(substr, StringComparison.Ordinal)
| _ -> fullString.IndexOf(substr, StringComparison.CurrentCulture)
Imports System.Reflection
<Assembly: AssemblyVersion("2.0.0.0")>
Public Class StringLibrary
Public Shared Function SubstringStartsAt(fullString As String, substr As String) As Integer
Dim flag As Boolean
If AppContext.TryGetSwitch("StringLibrary.DoNotUseCultureSensitiveComparison", flag) AndAlso flag = True Then
Return fullString.IndexOf(substr, StringComparison.Ordinal)
Else
Return fullString.IndexOf(substr, StringComparison.CurrentCulture)
End If
End Function
End Class
A .NET Framework application can then use the following configuration file to restore the version 1.0 behavior.
When the application is run with the configuration file present, it produces the following output:
Output
'archæ' not found in 'The archaeologist'
AppContext for library consumers
If you're the consumer of a library, the AppContext class allows you to take advantage of a library or library method's opt-out mechanism for new functionality. Individual methods of the class library that you are calling define particular switches that enable or disable a new behavior. The value of the switch is a Boolean. If it is false, which is typically the default value, the new behavior is enabled; if it is true, the new behavior is disabled, and the member behaves as it did previously.
You can set the value of a switch by calling the AppContext.SetSwitch(String, Boolean) method in your code. The switchName argument defines the switch name, and the isEnabled property defines the value of the switch. Because AppContext is a static class, it is available on a per-application domain basis. Calling the AppContext.SetSwitch(String, Boolean) has application scope; that is, it affects only the application.
.NET Framework apps have additional ways to set the value of a switch:
By adding an <AppContextSwitchOverrides> element to the <runtime> section of the app.config file. The switch has a single attribute, value, whose value is a string that represents a key/value pair containing both the switch name and its value.
To define multiple switches, separate each switch's key/value pair in the <AppContextSwitchOverrides> element's value attribute with a semicolon. In that case, the <AppContextSwitchOverrides> element has the following format:
By adding an entry to the registry. Add a new string value to the HKLM\SOFTWARE\Microsoft\.NETFramework\AppContext subkey. Set the name of the entry to the name of the switch. Set its value to one of the following options: True, true, False, or false. If the runtime encounters any other value, it ignores the switch.
On a 64-bit operating system, you must also add the same entry to the HKLM\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\AppContext subkey.
Using the registry to define an AppContext switch has machine scope; that is, it affects every application running on the machine.
For ASP.NET and ASP.NET Core applications, you set a switch by adding an <Add> element to the <appSettings> section of the web.config file. For example:
Šī satura avotu var atrast vietnē GitHub, kur varat arī izveidot un pārskatīt problēmas un atgādāšanas pieprasījumus. Lai iegūtu papildinformāciju, skatiet mūsu līdzstrādnieku rokasgrāmatu.
.NET atsauksmes
.NET ir atklātā pirmkoda projekts. Atlasiet saiti, lai sniegtu atsauksmes:
Pievienojieties meetup sērijai, lai kopā ar citiem izstrādātājiem un ekspertiem izveidotu mērogojamus AI risinājumus, kuru pamatā ir reālas lietošanas gadījumi.