This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Note
Access to this page requires authorization. You can trysigning in orchanging directories.
Access to this page requires authorization. You can trychanging directories.
This article provides supplementary remarks to the reference documentation for this API.
TheAppContext 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.
Libraries use theAppContext 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.
The most common way to allow consumers of your library to opt out of a change of behavior is to define a named switch. Itsvalue element is a name/value pair that consists of the name of a switch and itsBoolean value. By default, the switch is always implicitlyfalse, which provides the new behavior (and makes the new behavior opt-in by default). Setting the switch totrue enables it, which provides the legacy behavior. Explicitly setting the switch tofalse 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:
Once you define and document the switch, callers can use it by calling theAppContext.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 ofAppContext configuration switches, see theAppContext 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'sAppContext instance. Because theAppContext 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 theSetSwitch method, to configure theAppContext instance.
You can check if a consumer has declared the value of the switch and act appropriately by calling theAppContext.TryGetSwitch method. The method returnstrue if theswitchName argument is found, and itsisEnabled argument indicates the value of the switch. Otherwise, the method returnsfalse.
The following example illustrates the use of theAppContext class to allow the customer to choose the original behavior of a library method. The following is version 1.0 of a library namedStringLibrary. It defines aSubstringStartsAt method that performs an ordinal comparison to determine the starting index of a substring within a larger string.
using System;using System.Reflection;[assembly: AssemblyVersion("1.0.0.0")]public static class StringLibrary1{ public static int SubstringStartsAt(string fullString, string substr) { return fullString.IndexOf(substr, StringComparison.Ordinal); }}open Systemopen 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 FunctionEnd ClassThe 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.
using System;public class Example1{ public static void Main() { string value = "The archaeologist"; string substring = "archæ"; int position = StringLibrary1.SubstringStartsAt(value, substring); if (position >= 0) Console.WriteLine($"'{substring}' found in '{value}' starting at position {position}"); else Console.WriteLine($"'{substring}' not found in '{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 substringif 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 SubEnd Module' The example displays the following output:' 'archæ' not found in 'The archaeologist'Version 2.0 of the library, however, changes theSubstringStartsAt method to use culture-sensitive comparison.
using System;using System.Reflection;[assembly: AssemblyVersion("2.0.0.0")]public static class StringLibrary2{ public static int SubstringStartsAt(string fullString, string substr) { return fullString.IndexOf(substr, StringComparison.CurrentCulture); }}open Systemopen 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 FunctionEnd ClassWhen 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".
using System;public class Example2{ public static void Main() { string value = "The archaeologist"; string substring = "archæ"; int position = StringLibrary2.SubstringStartsAt(value, substring); if (position >= 0) Console.WriteLine($"'{substring}' found in '{value}' starting at position {position}"); else Console.WriteLine($"'{substring}' not found in '{value}'"); }}// The example displays the following output:// 'archæ' found in 'The archaeologist' starting at position 4let value = "The archaeologist"let substring = "archæ"let position = StringLibrary.substringStartsAt value substringif 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 4Public 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 SubEnd Module' The example displays the following output:' 'archæ' found in 'The archaeologist' starting at position 4This change can be prevented from breaking the applications that depend on the original behavior by defining a switch. In this case, the switch is namedStringLibrary.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.
using System;using System.Reflection;[assembly: AssemblyVersion("2.0.0.0")]public static class StringLibrary{ public static int SubstringStartsAt(string fullString, string substr) { bool flag; if (AppContext.TryGetSwitch("StringLibrary.DoNotUseCultureSensitiveComparison", out flag) && flag == true) return fullString.IndexOf(substr, StringComparison.Ordinal); else return fullString.IndexOf(substr, StringComparison.CurrentCulture); }}open Systemopen 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 FunctionEnd ClassA .NET Framework application can then use the following configuration file to restore the version 1.0 behavior.
<configuration> <runtime> <AppContextSwitchOverrides value="StringLibrary.DoNotUseCultureSensitiveComparison=true" /> </runtime></configuration>When the application is run with the configuration file present, it produces the following output:
'archæ' not found in 'The archaeologist'If you're the consumer of a library, theAppContext 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 isfalse, which is typically the default value, the new behavior is enabled; if it istrue, the new behavior is disabled, and the member behaves as it did previously.
You can set the value of a switch by calling theAppContext.SetSwitch(String, Boolean) method in your code. TheswitchName argument defines the switch name, and theisEnabled property defines the value of the switch. BecauseAppContext is a static class, it is available on a per-application domain basis. Calling theAppContext.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'svalue attribute with a semicolon. In that case, the<AppContextSwitchOverrides> element has the following format:
<AppContextSwitchOverrides value="switchName1=value1;switchName2=value2" />Using the<AppContextSwitchOverrides> element to define a configuration setting has application scope; that is, it affects only the application.
Note
For information on the switches defined by .NET Framework, see<AppContextSwitchOverrides> element.
By adding an entry to the registry. Add a new string value to theHKLM\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, orfalse. 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 theHKLM\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\AppContext subkey.
Using the registry to define anAppContext 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:
<appSettings> <add key="AppContext.SetSwitch:switchName1" value="switchValue1" /> <add key="AppContext.SetSwitch:switchName2" value="switchValue2" /></appSettings>If you set the same switch in more than one way, the order of precedence for determining which setting overrides the others is:
Was this page helpful?
Need help with this topic?
Want to try using Ask Learn to clarify or guide you through this topic?
Was this page helpful?
Want to try using Ask Learn to clarify or guide you through this topic?