diff --git a/docs/standard/analyzers/platform-compat-analyzer.md b/docs/standard/analyzers/platform-compat-analyzer.md index fbe380085633d..6f97a609f7104 100644 --- a/docs/standard/analyzers/platform-compat-analyzer.md +++ b/docs/standard/analyzers/platform-compat-analyzer.md @@ -216,11 +216,11 @@ The following code snippet shows how you can combine attributes to set the right The recommended way to deal with these diagnostics is to make sure you only call platform-specific APIs when running on an appropriate platform. Following are the options you can use to address the warnings; choose whichever is most appropriate for your situation: -- **Guard the call**. You can achieve this by conditionally calling the code at run time. Check whether you're running on a desired `Platform` by using one of platform-check methods, for example, `OperatingSystem.Is()` or `OperatingSystem.IsVersionAtLeast(int major, int minor = 0, int build = 0, int revision = 0)`. [Example](#guard-platform-specific-apis-with-guard-methods). +- **Guard the call**. You can achieve this by conditionally calling the code at runtime. Check whether you're running on a desired `Platform` by using one of platform-check methods, for example, `OperatingSystem.Is()` or `OperatingSystem.IsVersionAtLeast(int major, int minor = 0, int build = 0, int revision = 0)`. [Example](#guard-platform-specific-apis-with-guard-methods). - **Mark the call site as platform-specific**. You can also choose to mark your own APIs as being platform-specific, thus effectively just forwarding the requirements to your callers. Mark the containing method or type or the entire assembly with the same attributes as the referenced platform-dependent call. [Examples](#mark-call-site-as-platform-specific). -- **Assert the call site with platform check**. If you don't want the overhead of an additional `if` statement at run time, use . [Example](#assert-the-call-site-with-platform-check). +- **Assert the call site with platform check**. If you don't want the overhead of an additional `if` statement at runtime, use . [Example](#assert-the-call-site-with-platform-check). - **Delete the code**. Generally not what you want because it means you lose fidelity when your code is used by Windows users. For cases where a cross-platform alternative exists, you're likely better off using that over platform-specific APIs. diff --git a/docs/standard/assembly/create-use-strong-named.md b/docs/standard/assembly/create-use-strong-named.md index 7591a33bdf995..b7edfb08b4ff5 100644 --- a/docs/standard/assembly/create-use-strong-named.md +++ b/docs/standard/assembly/create-use-strong-named.md @@ -40,7 +40,7 @@ The following scenario outlines the process of signing an assembly with a strong 3. Assembly B is a consumer of Assembly A. The reference section of Assembly B's manifest includes a token that represents Assembly A's public key. A token is a portion of the full public key and is used rather than the key itself to save space. -4. The common language runtime verifies the strong name signature when the assembly is placed in the global assembly cache. When binding by strong name at run time, the common language runtime compares the key stored in Assembly B's manifest with the key used to generate the strong name for Assembly A. If the .NET security checks pass and the bind succeeds, Assembly B has a guarantee that Assembly A's bits have not been tampered with and that these bits actually come from the developers of Assembly A. +4. The common language runtime verifies the strong name signature when the assembly is placed in the global assembly cache. When binding by strong name at runtime, the common language runtime compares the key stored in Assembly B's manifest with the key used to generate the strong name for Assembly A. If the .NET security checks pass and the bind succeeds, Assembly B has a guarantee that Assembly A's bits have not been tampered with and that these bits actually come from the developers of Assembly A. > [!NOTE] > This scenario doesn't address trust issues. Assemblies can carry full Microsoft Authenticode signatures in addition to a strong name. Authenticode signatures include a certificate that establishes trust. It's important to note that strong names don't require code to be signed in this way. Strong names only provide a unique identity. @@ -68,7 +68,7 @@ This feature can be disabled for individual applications or for a computer. See |[How to: Create a public-private key pair](create-public-private-key-pair.md)|Describes how to create a cryptographic key pair for signing an assembly.| |[How to: Sign an assembly with a strong name](sign-strong-name.md)|Describes how to create a strong-named assembly.| |[Enhanced strong naming](enhanced-strong-naming.md)|Describes enhancements to strong-names in the .NET Framework 4.5.| -|[How to: Reference a strong-named assembly](reference-strong-named.md)|Describes how to reference types or resources in a strong-named assembly at compile time or run time.| +|[How to: Reference a strong-named assembly](reference-strong-named.md)|Describes how to reference types or resources in a strong-named assembly at compile time or runtime.| |[How to: Disable the strong-name bypass feature](disable-strong-name-bypass-feature.md)|Describes how to disable the feature that bypasses the validation of strong-name signatures. This feature can be disabled for all or for specific applications.| |[Create assemblies](create.md)|Provides an overview of single-file and multifile assemblies.| |[How to delay sign an assembly in Visual Studio](/visualstudio/ide/managing-assembly-and-manifest-signing#how-to-sign-an-assembly-in-visual-studio)|Explains how to sign an assembly with a strong name after the assembly has been created.| diff --git a/docs/standard/assembly/file-format.md b/docs/standard/assembly/file-format.md index 32e9617eefe61..8669d8f2beb40 100644 --- a/docs/standard/assembly/file-format.md +++ b/docs/standard/assembly/file-format.md @@ -28,4 +28,4 @@ Assembly Headers from ECMA 335 II.25.1, Structure of the runtime file format. ## Process the assemblies -It is possible to write tools or APIs to process assemblies. Assembly information enables making programmatic decisions at run time, rewriting assemblies, providing API IntelliSense in an editor, and generating documentation. , , and [Mono.Cecil](https://www.mono-project.com/docs/tools+libraries/libraries/Mono.Cecil/) are good examples of tools that are frequently used for this purpose. +It is possible to write tools or APIs to process assemblies. Assembly information enables making programmatic decisions at runtime, rewriting assemblies, providing API IntelliSense in an editor, and generating documentation. , , and [Mono.Cecil](https://www.mono-project.com/docs/tools+libraries/libraries/Mono.Cecil/) are good examples of tools that are frequently used for this purpose. diff --git a/docs/standard/assembly/index.md b/docs/standard/assembly/index.md index 59f180512dcc2..6d5fb3b678666 100644 --- a/docs/standard/assembly/index.md +++ b/docs/standard/assembly/index.md @@ -103,7 +103,7 @@ In C#, you can use two versions of the same assembly in a single application. Fo |[Assembly placement](../../framework/app-domains/assembly-placement.md)|Where to locate assemblies.| |[Assemblies and side-by-side execution](side-by-side-execution.md)|Use multiple versions of the runtime or an assembly simultaneously.| |[Emit dynamic methods and assemblies](../../fundamentals/reflection/emitting-dynamic-methods-and-assemblies.md)|How to create dynamic assemblies.| -|[How the runtime locates assemblies](../../framework/deployment/how-the-runtime-locates-assemblies.md)|How the .NET Framework resolves assembly references at run time.| +|[How the runtime locates assemblies](../../framework/deployment/how-the-runtime-locates-assemblies.md)|How the .NET Framework resolves assembly references at runtime.| ## Reference diff --git a/docs/standard/assembly/reference-strong-named.md b/docs/standard/assembly/reference-strong-named.md index 562135bc04d31..3d68f7a9d4728 100644 --- a/docs/standard/assembly/reference-strong-named.md +++ b/docs/standard/assembly/reference-strong-named.md @@ -2,55 +2,55 @@ title: "How to: Reference a strong-named assembly" description: This article shows you how to reference types or resources in a strong-named .NET assembly, either at compile time or runtime. ms.date: "08/20/2019" -helpviewer_keywords: +helpviewer_keywords: - "strong-named assemblies, compile-time references" - "compile-time assembly referencing" - "assemblies [.NET], strong-named" - "assembly binding, strong-named" ms.topic: how-to -dev_langs: +dev_langs: - "csharp" - "vb" - "cpp" --- # How to: Reference a strong-named assembly -The process for referencing types or resources in a strong-named assembly is usually transparent. You can make the reference either at compile time (early binding) or at run time. - +The process for referencing types or resources in a strong-named assembly is usually transparent. You can make the reference either at compile time (early binding) or at runtime. + A compile-time reference occurs when you indicate to the compiler that the assembly to be compiled explicitly references another assembly. When you use compile-time referencing, the compiler automatically gets the public key of the targeted strong-named assembly and places it in the assembly reference of the assembly being compiled. - + > [!NOTE] -> A strong-named assembly can only use types from other strong-named assemblies. Otherwise, the security of the strong-named assembly would be compromised. - -## Make a compile-time reference to a strong-named assembly +> A strong-named assembly can only use types from other strong-named assemblies. Otherwise, the security of the strong-named assembly would be compromised. + +## Make a compile-time reference to a strong-named assembly -At a command prompt, type the following command: +At a command prompt, type the following command: -\<*compiler command*> **/reference:**\<*assembly name*> +\<*compiler command*> **/reference:**\<*assembly name*> -In this command, *compiler command* is the compiler command for the language you are using, and *assembly name* is the name of the strong-named assembly being referenced. You can also use other compiler options, such as the **/t:library** option for creating a library assembly. +In this command, *compiler command* is the compiler command for the language you are using, and *assembly name* is the name of the strong-named assembly being referenced. You can also use other compiler options, such as the **/t:library** option for creating a library assembly. -The following example creates an assembly called *myAssembly.dll* that references a strong-named assembly called *myLibAssembly.dll* from a code module called *myAssembly.cs*. +The following example creates an assembly called *myAssembly.dll* that references a strong-named assembly called *myLibAssembly.dll* from a code module called *myAssembly.cs*. ```cmd -csc /t:library myAssembly.cs /reference:myLibAssembly.dll -``` +csc /t:library myAssembly.cs /reference:myLibAssembly.dll +``` + +## Make a runtime reference to a strong-named assembly -## Make a run-time reference to a strong-named assembly - -When you make a run-time reference to a strong-named assembly, for example by using the or method, you must use the display name of the referenced strong-named assembly. The syntax of a display name is as follows: +When you make a runtime reference to a strong-named assembly, for example by using the or method, you must use the display name of the referenced strong-named assembly. The syntax of a display name is as follows: -\<*assembly name*>**,** \<*version number*>**,** \<*culture*>**,** \<*public key token*> +\<*assembly name*>**,** \<*version number*>**,** \<*culture*>**,** \<*public key token*> -For example: +For example: ```console myDll, Version=1.1.0.0, Culture=en, PublicKeyToken=03689116d3a4ae33 -``` +``` -In this example, `PublicKeyToken` is the hexadecimal form of the public key token. If there is no culture value, use `Culture=neutral`. +In this example, `PublicKeyToken` is the hexadecimal form of the public key token. If there is no culture value, use `Culture=neutral`. -The following code example shows how to use this information with the method. +The following code example shows how to use this information with the method. ```cpp Assembly^ myDll = @@ -67,13 +67,13 @@ Dim myDll As Assembly = _ Assembly.Load("myDll, Version=1.0.0.1, Culture=neutral, PublicKeyToken=9b35aa32c18d4fb1") ``` -You can print the hexadecimal format of the public key and public key token for a specific assembly by using the following [Strong Name (Sn.exe)](../../framework/tools/sn-exe-strong-name-tool.md) command: +You can print the hexadecimal format of the public key and public key token for a specific assembly by using the following [Strong Name (Sn.exe)](../../framework/tools/sn-exe-strong-name-tool.md) command: -**sn -Tp \<** *assembly* **>** +**sn -Tp \<** *assembly* **>** -If you have a public key file, you can use the following command instead (note the difference in case on the command-line option): +If you have a public key file, you can use the following command instead (note the difference in case on the command-line option): -**sn -tp \<** *public key file* **>** +**sn -tp \<** *public key file* **>** ## See also diff --git a/docs/standard/assembly/set-attributes.md b/docs/standard/assembly/set-attributes.md index ab174e4c9624a..f9acd5a6c0155 100644 --- a/docs/standard/assembly/set-attributes.md +++ b/docs/standard/assembly/set-attributes.md @@ -68,7 +68,7 @@ You can use informational attributes to provide additional company or product in | | String value specifying a company name. | | | String value specifying copyright information. | | | String value specifying the Win32 file version number. This normally defaults to the assembly version. | -| | String value specifying version information that is not used by the common language runtime, such as a full product version number. **Note:** If this attribute is applied to an assembly, the string it specifies can be obtained at run time by using the property. The string is also used in the path and registry key provided by the and properties. | +| | String value specifying version information that is not used by the common language runtime, such as a full product version number. **Note:** If this attribute is applied to an assembly, the string it specifies can be obtained at runtime by using the property. The string is also used in the path and registry key provided by the and properties. | | | String value specifying product information. | | | String value specifying trademark information. | diff --git a/docs/standard/assembly/side-by-side-execution.md b/docs/standard/assembly/side-by-side-execution.md index 89f50b5727d5c..b06a6e337ddb8 100644 --- a/docs/standard/assembly/side-by-side-execution.md +++ b/docs/standard/assembly/side-by-side-execution.md @@ -2,19 +2,19 @@ title: "Assemblies and side-by-side execution" description: Learn about side-by-side execution, which is the ability to store and run multiple versions of an application or component on the same computer. ms.date: "08/20/2019" -helpviewer_keywords: +helpviewer_keywords: - "side-by-side execution [.NET]" - "assemblies [.NET], side-by-side execution" ms.assetid: e42036ee-7590-47d1-b884-cc856e39bd5d --- # Assemblies and side-by-side execution -Side-by-side execution is the ability to store and execute multiple versions of an application or component on the same computer. This means that you can have multiple versions of the runtime, and multiple versions of applications and components that use a version of the runtime, on the same computer at the same time. Side-by-side execution gives you more control over what versions of a component an application binds to, and more control over what version of the runtime an application uses. - -Support for side-by-side storage and execution of different versions of the same assembly is an integral part of strong naming and is built into the infrastructure of the runtime. Because the strong-named assembly's version number is part of its identity, the runtime can store multiple versions of the same assembly in the global assembly cache and load those assemblies at run time. - -Although the runtime provides you with the ability to create side-by-side applications, side-by-side execution is not automatic. For more information on creating applications for side-by-side execution, see [Guidelines for creating components for side-by-side execution](../../framework/deployment/guidelines-for-creating-components-for-side-by-side-execution.md). - +Side-by-side execution is the ability to store and execute multiple versions of an application or component on the same computer. This means that you can have multiple versions of the runtime, and multiple versions of applications and components that use a version of the runtime, on the same computer at the same time. Side-by-side execution gives you more control over what versions of a component an application binds to, and more control over what version of the runtime an application uses. + +Support for side-by-side storage and execution of different versions of the same assembly is an integral part of strong naming and is built into the infrastructure of the runtime. Because the strong-named assembly's version number is part of its identity, the runtime can store multiple versions of the same assembly in the global assembly cache and load those assemblies at runtime. + +Although the runtime provides you with the ability to create side-by-side applications, side-by-side execution is not automatic. For more information on creating applications for side-by-side execution, see [Guidelines for creating components for side-by-side execution](../../framework/deployment/guidelines-for-creating-components-for-side-by-side-execution.md). + ## See also - [How the runtime locates assemblies](../../framework/deployment/how-the-runtime-locates-assemblies.md) diff --git a/docs/standard/assembly/versioning.md b/docs/standard/assembly/versioning.md index 996819add92f3..4b92e5d26ebad 100644 --- a/docs/standard/assembly/versioning.md +++ b/docs/standard/assembly/versioning.md @@ -2,7 +2,7 @@ title: "Assembly versioning" description: Learn about versioning of .NET assemblies. All versioning of assemblies that use the CLR is done at the assembly level. ms.date: "08/20/2019" -helpviewer_keywords: +helpviewer_keywords: - "informational versions" - "version numbers, assemblies" - "assemblies [.NET], versioning" @@ -12,57 +12,57 @@ ms.assetid: 775ad4fb-914f-453c-98ef-ce1089b6f903 --- # Assembly versioning -All versioning of assemblies that use the common language runtime is done at the assembly level. The specific version of an assembly and the versions of dependent assemblies are recorded in the assembly's manifest. The default version policy for the runtime is that applications run only with the versions they were built and tested with, unless overridden by explicit version policy in configuration files (the application configuration file, the publisher policy file, and the computer's administrator configuration file). - -The runtime performs several steps to resolve an assembly binding request: - -1. Checks the original assembly reference to determine the version of the assembly to be bound. - -2. Checks for all applicable configuration files to apply version policy. - -3. Determines the correct assembly from the original assembly reference and any redirection specified in the configuration files, and determines the version that should be bound to the calling assembly. - -4. Checks the global assembly cache, codebases specified in configuration files, and then checks the application's directory and subdirectories using the probing rules explained in [How the runtime locates assemblies](../../framework/deployment/how-the-runtime-locates-assemblies.md). - -The following illustration shows these steps: - +All versioning of assemblies that use the common language runtime is done at the assembly level. The specific version of an assembly and the versions of dependent assemblies are recorded in the assembly's manifest. The default version policy for the runtime is that applications run only with the versions they were built and tested with, unless overridden by explicit version policy in configuration files (the application configuration file, the publisher policy file, and the computer's administrator configuration file). + +The runtime performs several steps to resolve an assembly binding request: + +1. Checks the original assembly reference to determine the version of the assembly to be bound. + +2. Checks for all applicable configuration files to apply version policy. + +3. Determines the correct assembly from the original assembly reference and any redirection specified in the configuration files, and determines the version that should be bound to the calling assembly. + +4. Checks the global assembly cache, codebases specified in configuration files, and then checks the application's directory and subdirectories using the probing rules explained in [How the runtime locates assemblies](../../framework/deployment/how-the-runtime-locates-assemblies.md). + +The following illustration shows these steps: + ![Diagram that shows steps in assembly binding request resolution.](./media/versioning/resolve-assembly-binding-request.gif) - -For more information about configuring applications, see [Configure apps](../../framework/configure-apps/index.md). For more information about binding policy, see [How the runtime locates assemblies](../../framework/deployment/how-the-runtime-locates-assemblies.md). - -## Version information - -Each assembly has two distinct ways of expressing version information: - -- The assembly's version number, which, together with the assembly name and culture information, is part of the assembly's identity. This number is used by the runtime to enforce version policy and plays a key part in the type resolution process at run time. - -- An informational version, which is a string that represents additional version information included for informational purposes only. - -### Assembly version number - -Each assembly has a version number as part of its identity. As such, two assemblies that differ by version number are considered by the runtime to be completely different assemblies. This version number is physically represented as a four-part string with the following format: - -\<*major version*>.\<*minor version*>.\<*build number*>.\<*revision*> - -For example, version 1.5.1254.0 indicates 1 as the major version, 5 as the minor version, 1254 as the build number, and 0 as the revision number. - -The version number is stored in the assembly manifest along with other identity information, including the assembly name and public key, as well as information on relationships and identities of other assemblies connected with the application. - -When an assembly is built, the development tool records dependency information for each assembly that is referenced in the assembly manifest. The runtime uses these version numbers, in conjunction with configuration information set by an administrator, an application, or a publisher, to load the proper version of a referenced assembly. - -The runtime distinguishes between regular and strong-named assemblies for the purposes of versioning. Version checking only occurs with strong-named assemblies. - -For information about specifying version binding policies, see [Configure apps](../../framework/configure-apps/index.md). For information about how the runtime uses version information to find a particular assembly, see [How the runtime locates assemblies](../../framework/deployment/how-the-runtime-locates-assemblies.md). - -### Assembly informational version - -The informational version is a string that attaches additional version information to an assembly for informational purposes only; this information is not used at run time. The text-based informational version corresponds to the product's marketing literature, packaging, or product name and is not used by the runtime. For example, an informational version could be "Common Language Runtime version 1.0" or "NET Control SP 2". On the Version tab of the file properties dialog in Microsoft Windows, this information appears in the item "Product Version". - + +For more information about configuring applications, see [Configure apps](../../framework/configure-apps/index.md). For more information about binding policy, see [How the runtime locates assemblies](../../framework/deployment/how-the-runtime-locates-assemblies.md). + +## Version information + +Each assembly has two distinct ways of expressing version information: + +- The assembly's version number, which, together with the assembly name and culture information, is part of the assembly's identity. This number is used by the runtime to enforce version policy and plays a key part in the type resolution process at runtime. + +- An informational version, which is a string that represents additional version information included for informational purposes only. + +### Assembly version number + +Each assembly has a version number as part of its identity. As such, two assemblies that differ by version number are considered by the runtime to be completely different assemblies. This version number is physically represented as a four-part string with the following format: + +\<*major version*>.\<*minor version*>.\<*build number*>.\<*revision*> + +For example, version 1.5.1254.0 indicates 1 as the major version, 5 as the minor version, 1254 as the build number, and 0 as the revision number. + +The version number is stored in the assembly manifest along with other identity information, including the assembly name and public key, as well as information on relationships and identities of other assemblies connected with the application. + +When an assembly is built, the development tool records dependency information for each assembly that is referenced in the assembly manifest. The runtime uses these version numbers, in conjunction with configuration information set by an administrator, an application, or a publisher, to load the proper version of a referenced assembly. + +The runtime distinguishes between regular and strong-named assemblies for the purposes of versioning. Version checking only occurs with strong-named assemblies. + +For information about specifying version binding policies, see [Configure apps](../../framework/configure-apps/index.md). For information about how the runtime uses version information to find a particular assembly, see [How the runtime locates assemblies](../../framework/deployment/how-the-runtime-locates-assemblies.md). + +### Assembly informational version + +The informational version is a string that attaches additional version information to an assembly for informational purposes only; this information is not used at runtime. The text-based informational version corresponds to the product's marketing literature, packaging, or product name and is not used by the runtime. For example, an informational version could be "Common Language Runtime version 1.0" or "NET Control SP 2". On the Version tab of the file properties dialog in Microsoft Windows, this information appears in the item "Product Version". + > [!NOTE] -> Although you can specify any text, a warning message appears on compilation if the string is not in the format used by the assembly version number, or if it is in that format but contains wildcards. This warning is harmless. - -The informational version is represented using the custom attribute . For more information about the informational version attribute, see [Set assembly attributes](set-attributes.md). - +> Although you can specify any text, a warning message appears on compilation if the string is not in the format used by the assembly version number, or if it is in that format but contains wildcards. This warning is harmless. + +The informational version is represented using the custom attribute . For more information about the informational version attribute, see [Set assembly attributes](set-attributes.md). + ## See also - [How the runtime locates assemblies](../../framework/deployment/how-the-runtime-locates-assemblies.md) diff --git a/docs/standard/base-types/common-type-system.md b/docs/standard/base-types/common-type-system.md index 52a4b0e269021..674a50546974a 100644 --- a/docs/standard/base-types/common-type-system.md +++ b/docs/standard/base-types/common-type-system.md @@ -154,7 +154,7 @@ A type definition includes the following: ### Attributes -Attributes provide additional user-defined metadata. Most commonly, they are used to store additional information about a type in its assembly, or to modify the behavior of a type member in either the design-time or run-time environment. +Attributes provide additional user-defined metadata. Most commonly, they are used to store additional information about a type in its assembly, or to modify the behavior of a type member in either the design-time or runtime environment. Attributes are themselves classes that inherit from . Languages that support the use of attributes each have their own syntax for applying attributes to a language element. Attributes can be applied to almost any language element; the specific elements to which an attribute can be applied are defined by the that is applied to that attribute class. @@ -268,7 +268,7 @@ The common type system allows type members to have a variety of characteristics; |literal|Fields|The value assigned to the field is a fixed value, known at compile time, of a built-in value type. Literal fields are sometimes referred to as constants.| |newslot or override|All|Defines how the member interacts with inherited members that have the same signature:

newslot
Hides inherited members that have the same signature.

override
Replaces the definition of an inherited virtual method.

The default is newslot.| |static|Fields, methods, properties, and events|The member belongs to the type it is defined on, not to a particular instance of the type; the member exists even if an instance of the type is not created, and it is shared among all instances of the type.| -|virtual|Methods, properties, and events|The method can be implemented by a derived type and can be invoked either statically or dynamically. If dynamic invocation is used, the type of the instance that makes the call at run time (rather than the type known at compile time) determines which implementation of the method is called. To invoke a virtual method statically, the variable might have to be cast to a type that uses the desired version of the method.| +|virtual|Methods, properties, and events|The method can be implemented by a derived type and can be invoked either statically or dynamically. If dynamic invocation is used, the type of the instance that makes the call at runtime (rather than the type known at compile time) determines which implementation of the method is called. To invoke a virtual method statically, the variable might have to be cast to a type that uses the desired version of the method.| ### Overloading @@ -283,7 +283,7 @@ A derived type inherits all members of its base type; that is, these members are - A derived type can hide an inherited member by defining a new member with the same signature. This might be done to make a previously public member private or to define new behavior for an inherited method that is marked as `sealed`. -- A derived type can override an inherited virtual method. The overriding method provides a new definition of the method that will be invoked based on the type of the value at run time rather than the type of the variable known at compile time. A method can override a virtual method only if the virtual method is not marked as `sealed` and the new method is at least as accessible as the virtual method. +- A derived type can override an inherited virtual method. The overriding method provides a new definition of the method that will be invoked based on the type of the value at runtime rather than the type of the variable known at compile time. A method can override a virtual method only if the virtual method is not marked as `sealed` and the new method is at least as accessible as the virtual method. ## See also diff --git a/docs/standard/base-types/composite-formatting.md b/docs/standard/base-types/composite-formatting.md index 19430f835a054..4a4be55abd5b5 100644 --- a/docs/standard/base-types/composite-formatting.md +++ b/docs/standard/base-types/composite-formatting.md @@ -64,7 +64,7 @@ Multiple format items can refer to the same element in the list of objects by sp :::code language="csharp" source="./snippets/composite-formatting/net/csharp/Program.cs" id="multiple"::: :::code language="vb" source="./snippets/composite-formatting/net/vb/Program.vb" id="multiple"::: -Each format item can refer to any object in the list. For example, if there are three objects, you can format the second, first, and third object by specifying a composite format string such as `{1} {0} {2}`. An object that isn't referenced by a format item is ignored. A is thrown at run time if a parameter specifier designates an item outside the bounds of the list of objects. +Each format item can refer to any object in the list. For example, if there are three objects, you can format the second, first, and third object by specifying a composite format string such as `{1} {0} {2}`. An object that isn't referenced by a format item is ignored. A is thrown at runtime if a parameter specifier designates an item outside the bounds of the list of objects. ### Width component diff --git a/docs/standard/base-types/regular-expression-options.md b/docs/standard/base-types/regular-expression-options.md index 911d9ca8a6c87..02eca90d7eeee 100644 --- a/docs/standard/base-types/regular-expression-options.md +++ b/docs/standard/base-types/regular-expression-options.md @@ -228,9 +228,9 @@ Finally, you can use the inline group element `(?n:)` to suppress automatic capt > [!NOTE] > Where possible, use [source-generated regular expressions](regular-expression-source-generators.md) instead of compiling regular expressions using the option. Source generation can help your app start faster, run more quickly and be more trimmable. To learn when source generation is possible, see [When to use it](regular-expression-source-generators.md#when-to-use-it). -By default, regular expressions in .NET are interpreted. When a object is instantiated or a static method is called, the regular expression pattern is parsed into a set of custom opcodes, and an interpreter uses these opcodes to run the regular expression. This involves a tradeoff: the cost of initializing the regular expression engine is minimized at the expense of run-time performance. +By default, regular expressions in .NET are interpreted. When a object is instantiated or a static method is called, the regular expression pattern is parsed into a set of custom opcodes, and an interpreter uses these opcodes to run the regular expression. This involves a tradeoff: the cost of initializing the regular expression engine is minimized at the expense of runtime performance. -You can use compiled instead of interpreted regular expressions by using the option. In this case, when a pattern is passed to the regular expression engine, it is parsed into a set of opcodes and then converted to common intermediate language (CIL), which can be passed directly to the common language runtime. Compiled regular expressions maximize run-time performance at the expense of initialization time. +You can use compiled instead of interpreted regular expressions by using the option. In this case, when a pattern is passed to the regular expression engine, it is parsed into a set of opcodes and then converted to common intermediate language (CIL), which can be passed directly to the common language runtime. Compiled regular expressions maximize runtime performance at the expense of initialization time. > [!NOTE] > A regular expression can be compiled only by supplying the value to the `options` parameter of a class constructor or a static pattern-matching method. It's not available as an inline option. @@ -266,9 +266,9 @@ However, in the following cases, white-space characters in a regular expression - White space isn't allowed within a character sequence that introduces a language element. For example: - - The language element `(?:`*subexpression*`)` represents a noncapturing group, and the `(?:` portion of the element can't have embedded spaces. The pattern `(? :`*subexpression*`)` throws an at run time because the regular expression engine can't parse the pattern, and the pattern `( ?:`*subexpression*`)` fails to match *subexpression*. + - The language element `(?:`*subexpression*`)` represents a noncapturing group, and the `(?:` portion of the element can't have embedded spaces. The pattern `(? :`*subexpression*`)` throws an at runtime because the regular expression engine can't parse the pattern, and the pattern `( ?:`*subexpression*`)` fails to match *subexpression*. - - The language element `\p{`*name*`}`, which represents a Unicode category or named block, can't include embedded spaces in the `\p{` portion of the element. If you do include a white space, the element throws an at run time. + - The language element `\p{`*name*`}`, which represents a Unicode category or named block, can't include embedded spaces in the `\p{` portion of the element. If you do include a white space, the element throws an at runtime. Enabling this option helps simplify regular expressions that are often difficult to parse and to understand. It improves readability, and makes it possible to document a regular expression. diff --git a/docs/standard/base-types/regular-expression-source-generators.md b/docs/standard/base-types/regular-expression-source-generators.md index b87579359ef0e..bcde7e299f5ea 100644 --- a/docs/standard/base-types/regular-expression-source-generators.md +++ b/docs/standard/base-types/regular-expression-source-generators.md @@ -368,7 +368,7 @@ Also, neither `RegexCompiler` nor the source generator supports the new `RegexOp The general guidance is if you can use the source generator, use it. If you're using `Regex` today in C# with arguments known at compile time, and especially if you're already using `RegexOptions.Compiled` (because the regex has been identified as a hot spot that would benefit from faster throughput), you should prefer to use the source generator. The source generator will give your regex the following benefits: - All the throughput benefits of `RegexOptions.Compiled`. -- The startup benefits of not having to do all the regex parsing, analysis, and compilation at run time. +- The startup benefits of not having to do all the regex parsing, analysis, and compilation at runtime. - The option of using ahead-of-time compilation with the code generated for the regex. - Better debuggability and understanding of the regex. - The possibility to reduce the size of your trimmed app by trimming out large swaths of code associated with `RegexCompiler` (and potentially even reflection emit itself). diff --git a/docs/standard/base-types/standard-date-and-time-format-strings.md b/docs/standard/base-types/standard-date-and-time-format-strings.md index b5bd0d22c9c42..54abb1eb1ab0d 100644 --- a/docs/standard/base-types/standard-date-and-time-format-strings.md +++ b/docs/standard/base-types/standard-date-and-time-format-strings.md @@ -49,7 +49,7 @@ A standard date and time format string uses a single character as the format spe |"u"|Universal sortable date/time pattern.

More information: [The universal sortable ("u") format specifier](#UniversalSortable).|With a value: 2009-06-15T13:45:30 -> 2009-06-15 13:45:30Z

With a value: 2009-06-15T13:45:30 -> 2009-06-15 20:45:30Z| |"U"|Universal full date/time pattern.

More information: [The universal full ("U") format specifier](#UniversalFull).|2009-06-15T13:45:30 -> Monday, June 15, 2009 8:45:30 PM (en-US)

2009-06-15T13:45:30 -> den 15 juni 2009 20:45:30 (sv-SE)

2009-06-15T13:45:30 -> Δευτέρα, 15 Ιουνίου 2009 8:45:30 μμ (el-GR)| |"Y", "y"|Year month pattern.

More information: [The year month ("Y") format specifier](#YearMonth).|2009-06-15T13:45:30 -> June 2009 (en-US)

2009-06-15T13:45:30 -> juni 2009 (da-DK)

2009-06-15T13:45:30 -> Juni 2009 (id-ID)| -|Any other single character|Unknown specifier.|Throws a run-time .| +|Any other single character|Unknown specifier.|Throws a runtime .| ## How standard format strings work diff --git a/docs/standard/base-types/standard-numeric-format-strings.md b/docs/standard/base-types/standard-numeric-format-strings.md index b084452518e0b..2a2848c077043 100644 --- a/docs/standard/base-types/standard-numeric-format-strings.md +++ b/docs/standard/base-types/standard-numeric-format-strings.md @@ -63,7 +63,7 @@ The following table describes the standard numeric format specifiers and display | "P" or "p" | Percent | Result: Number multiplied by 100 and displayed with a percent symbol.

Supported by: All numeric types.

Precision specifier: Desired number of decimal places.

Default precision specifier: Defined by .

More information: [The Percent ("P") Format Specifier](#PFormatString). | 1 ("P", en-US)
-> 100.00 %

1 ("P", fr-FR)
-> 100,00 %

-0.39678 ("P1", en-US)
-> -39.7 %

-0.39678 ("P1", fr-FR)
-> -39,7 % | | "R" or "r" | Round-trip | Result: A string that can round-trip to an identical number.

Supported by: , , and .

Note: Recommended for the type only. For types, use "G17"; for types, use "G9".
Precision specifier: Ignored.

More information: [The Round-trip ("R") Format Specifier](#RFormatString). | 123456789.12345678 ("R")
-> 123456789.12345678

-1234567890.12345678 ("R")
-> -1234567890.1234567 | | "X" or "x" | Hexadecimal | Result: A hexadecimal string.

Supported by: Integral types only.

Precision specifier: Number of digits in the result string.

More information: [The Hexadecimal ("X") Format Specifier](#XFormatString). | 255 ("X")
-> FF

-1 ("x")
-> ff

255 ("x4")
-> 00ff

-1 ("X4")
-> 00FF | -| Any other single character | Unknown specifier | Result: Throws a at run time. | | +| Any other single character | Unknown specifier | Result: Throws a at runtime. | | ## Use standard numeric format strings diff --git a/docs/standard/base-types/type-conversion.md b/docs/standard/base-types/type-conversion.md index 1482b1f5c8a02..abef4340b59e6 100644 --- a/docs/standard/base-types/type-conversion.md +++ b/docs/standard/base-types/type-conversion.md @@ -3,10 +3,10 @@ title: "Type Conversion in .NET" description: Read about type conversion in .NET, which creates a value in a new type that's equivalent to the old type's value, but may not keep the original's identity. ms.topic: article ms.date: 03/30/2017 -dev_langs: +dev_langs: - "csharp" - "vb" -helpviewer_keywords: +helpviewer_keywords: - "widening conversions" - "explicit conversions" - "narrowing conversions" @@ -28,171 +28,171 @@ ms.assetid: ba36154f-064c-47d3-9f05-72f93a7ca96d --- # Type conversion in .NET -Every value has an associated type, which defines attributes such as the amount of space allocated to the value, the range of possible values it can have, and the members that it makes available. Many values can be expressed as more than one type. For example, the value 4 can be expressed as an integer or a floating-point value. Type conversion creates a value in a new type that is equivalent to the value of an old type, but does not necessarily preserve the identity (or exact value) of the original object. - -.NET automatically supports the following conversions: - -- Conversion from a derived class to a base class. This means, for example, that an instance of any class or structure can be converted to an instance. This conversion does not require a casting or conversion operator. - -- Conversion from a base class back to the original derived class. In C#, this conversion requires a casting operator. In Visual Basic, it requires the `CType` operator if `Option Strict` is on. - -- Conversion from a type that implements an interface to an interface object that represents that interface. This conversion does not require a casting or conversion operator. - -- Conversion from an interface object back to the original type that implements that interface. In C#, this conversion requires a casting operator. In Visual Basic, it requires the `CType` operator if `Option Strict` is on. - -In addition to these automatic conversions, .NET provides several features that support custom type conversion. These include the following: - -- The `Implicit` operator, which defines the available widening conversions between types. For more information, see the [Implicit Conversion with the Implicit Operator](#implicit-conversion-with-the-implicit-operator) section. - -- The `Explicit` operator, which defines the available narrowing conversions between types. For more information, see the [Explicit Conversion with the Explicit Operator](#explicit-conversion-with-the-explicit-operator) section. - -- The interface, which defines conversions to each of the base .NET data types. For more information, see [The IConvertible Interface](#the-iconvertible-interface) section. - -- The class, which provides a set of methods that implement the methods in the interface. For more information, see [The Convert Class](#the-convert-class) section. - -- The class, which is a base class that can be extended to support the conversion of a specified type to any other type. For more information, see [The TypeConverter Class](#the-typeconverter-class) section. +Every value has an associated type, which defines attributes such as the amount of space allocated to the value, the range of possible values it can have, and the members that it makes available. Many values can be expressed as more than one type. For example, the value 4 can be expressed as an integer or a floating-point value. Type conversion creates a value in a new type that is equivalent to the value of an old type, but does not necessarily preserve the identity (or exact value) of the original object. + +.NET automatically supports the following conversions: + +- Conversion from a derived class to a base class. This means, for example, that an instance of any class or structure can be converted to an instance. This conversion does not require a casting or conversion operator. + +- Conversion from a base class back to the original derived class. In C#, this conversion requires a casting operator. In Visual Basic, it requires the `CType` operator if `Option Strict` is on. + +- Conversion from a type that implements an interface to an interface object that represents that interface. This conversion does not require a casting or conversion operator. + +- Conversion from an interface object back to the original type that implements that interface. In C#, this conversion requires a casting operator. In Visual Basic, it requires the `CType` operator if `Option Strict` is on. + +In addition to these automatic conversions, .NET provides several features that support custom type conversion. These include the following: + +- The `Implicit` operator, which defines the available widening conversions between types. For more information, see the [Implicit Conversion with the Implicit Operator](#implicit-conversion-with-the-implicit-operator) section. + +- The `Explicit` operator, which defines the available narrowing conversions between types. For more information, see the [Explicit Conversion with the Explicit Operator](#explicit-conversion-with-the-explicit-operator) section. + +- The interface, which defines conversions to each of the base .NET data types. For more information, see [The IConvertible Interface](#the-iconvertible-interface) section. + +- The class, which provides a set of methods that implement the methods in the interface. For more information, see [The Convert Class](#the-convert-class) section. + +- The class, which is a base class that can be extended to support the conversion of a specified type to any other type. For more information, see [The TypeConverter Class](#the-typeconverter-class) section. ## Implicit conversion with the implicit operator -Widening conversions involve the creation of a new value from the value of an existing type that has either a more restrictive range or a more restricted member list than the target type. Widening conversions cannot result in data loss (although they may result in a loss of precision). Because data cannot be lost, compilers can handle the conversion implicitly or transparently, without requiring the use of an explicit conversion method or a casting operator. - +Widening conversions involve the creation of a new value from the value of an existing type that has either a more restrictive range or a more restricted member list than the target type. Widening conversions cannot result in data loss (although they may result in a loss of precision). Because data cannot be lost, compilers can handle the conversion implicitly or transparently, without requiring the use of an explicit conversion method or a casting operator. + > [!NOTE] -> Although code that performs an implicit conversion can call a conversion method or use a casting operator, their use is not required by compilers that support implicit conversions. - - For example, the type supports implicit conversions from , , , , , , , , and values. The following example illustrates some of these implicit conversions in assigning values to a variable. - +> Although code that performs an implicit conversion can call a conversion method or use a casting operator, their use is not required by compilers that support implicit conversions. + + For example, the type supports implicit conversions from , , , , , , , , and values. The following example illustrates some of these implicit conversions in assigning values to a variable. + [!code-csharp[Conceptual.Conversion#1](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.conversion/cs/implicit1.cs#1)] - [!code-vb[Conceptual.Conversion#1](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.conversion/vb/implicit1.vb#1)] - - If a particular language compiler supports custom operators, you can also define implicit conversions in your own custom types. The following example provides a partial implementation of a signed byte data type named `ByteWithSign` that uses sign-and-magnitude representation. It supports implicit conversion of and values to `ByteWithSign` values. - + [!code-vb[Conceptual.Conversion#1](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.conversion/vb/implicit1.vb#1)] + + If a particular language compiler supports custom operators, you can also define implicit conversions in your own custom types. The following example provides a partial implementation of a signed byte data type named `ByteWithSign` that uses sign-and-magnitude representation. It supports implicit conversion of and values to `ByteWithSign` values. + [!code-csharp[Conceptual.Conversion#2](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.conversion/cs/implicit1.cs#2)] - [!code-vb[Conceptual.Conversion#2](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.conversion/vb/implicit1.vb#2)] - - Client code can then declare a `ByteWithSign` variable and assign it and values without performing any explicit conversions or using any casting operators, as the following example shows. - + [!code-vb[Conceptual.Conversion#2](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.conversion/vb/implicit1.vb#2)] + + Client code can then declare a `ByteWithSign` variable and assign it and values without performing any explicit conversions or using any casting operators, as the following example shows. + [!code-csharp[Conceptual.Conversion#3](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.conversion/cs/implicit1.cs#3)] - [!code-vb[Conceptual.Conversion#3](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.conversion/vb/implicit1.vb#3)] + [!code-vb[Conceptual.Conversion#3](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.conversion/vb/implicit1.vb#3)] ## Explicit conversion with the explicit operator -Narrowing conversions involve the creation of a new value from the value of an existing type that has either a greater range or a larger member list than the target type. Because a narrowing conversion can result in a loss of data, compilers often require that the conversion be made explicit through a call to a conversion method or a casting operator. That is, the conversion must be handled explicitly in developer code. - +Narrowing conversions involve the creation of a new value from the value of an existing type that has either a greater range or a larger member list than the target type. Because a narrowing conversion can result in a loss of data, compilers often require that the conversion be made explicit through a call to a conversion method or a casting operator. That is, the conversion must be handled explicitly in developer code. + > [!NOTE] -> The major purpose of requiring a conversion method or casting operator for narrowing conversions is to make the developer aware of the possibility of data loss or an so that it can be handled in code. However, some compilers can relax this requirement. For example, in Visual Basic, if `Option Strict` is off (its default setting), the Visual Basic compiler tries to perform narrowing conversions implicitly. - - For example, the , , and data types have ranges that exceed that the data type, as the following table shows. - -|Type|Comparison with range of Int32| -|----------|------------------------------------| -|| is greater than , and is less than (has a greater negative range than) .| -|| is greater than .| -|| is greater than .| - - To handle such narrowing conversions, .NET allows types to define an `Explicit` operator. Individual language compilers can then implement this operator using their own syntax, or a member of the class can be called to perform the conversion. (For more information about the class, see [The Convert Class](#the-convert-class) later in this topic.) The following example illustrates the use of language features to handle the explicit conversion of these potentially out-of-range integer values to values. - +> The major purpose of requiring a conversion method or casting operator for narrowing conversions is to make the developer aware of the possibility of data loss or an so that it can be handled in code. However, some compilers can relax this requirement. For example, in Visual Basic, if `Option Strict` is off (its default setting), the Visual Basic compiler tries to perform narrowing conversions implicitly. + + For example, the , , and data types have ranges that exceed that the data type, as the following table shows. + +|Type|Comparison with range of Int32| +|----------|------------------------------------| +|| is greater than , and is less than (has a greater negative range than) .| +|| is greater than .| +|| is greater than .| + + To handle such narrowing conversions, .NET allows types to define an `Explicit` operator. Individual language compilers can then implement this operator using their own syntax, or a member of the class can be called to perform the conversion. (For more information about the class, see [The Convert Class](#the-convert-class) later in this topic.) The following example illustrates the use of language features to handle the explicit conversion of these potentially out-of-range integer values to values. + [!code-csharp[Conceptual.Conversion#4](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.conversion/cs/explicit1.cs#4)] - [!code-vb[Conceptual.Conversion#4](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.conversion/vb/explicit1.vb#4)] - - Explicit conversions can produce different results in different languages, and these results can differ from the value returned by the corresponding method. For example, if the value 12.63251 is converted to an , both the Visual Basic `CInt` method and the .NET method round the to return a value of 13, but the C# `(int)` operator truncates the to return a value of 12. Similarly, the C# `(int)` operator does not support Boolean-to-integer conversion, but the Visual Basic `CInt` method converts a value of `true` to -1. On the other hand, the method converts a value of `true` to 1. - - Most compilers allow explicit conversions to be performed in a checked or unchecked manner. When a checked conversion is performed, an is thrown when the value of the type to be converted is outside the range of the target type. When an unchecked conversion is performed under the same conditions, the conversion might not throw an exception, but the exact behavior becomes undefined and an incorrect value might result. - + [!code-vb[Conceptual.Conversion#4](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.conversion/vb/explicit1.vb#4)] + + Explicit conversions can produce different results in different languages, and these results can differ from the value returned by the corresponding method. For example, if the value 12.63251 is converted to an , both the Visual Basic `CInt` method and the .NET method round the to return a value of 13, but the C# `(int)` operator truncates the to return a value of 12. Similarly, the C# `(int)` operator does not support Boolean-to-integer conversion, but the Visual Basic `CInt` method converts a value of `true` to -1. On the other hand, the method converts a value of `true` to 1. + + Most compilers allow explicit conversions to be performed in a checked or unchecked manner. When a checked conversion is performed, an is thrown when the value of the type to be converted is outside the range of the target type. When an unchecked conversion is performed under the same conditions, the conversion might not throw an exception, but the exact behavior becomes undefined and an incorrect value might result. + > [!NOTE] -> In C#, checked conversions can be performed by using the `checked` keyword together with a casting operator, or by specifying the `/checked+` compiler option. Conversely, unchecked conversions can be performed by using the `unchecked` keyword together with the casting operator, or by specifying the `/checked-` compiler option. By default, explicit conversions are unchecked. In Visual Basic, checked conversions can be performed by clearing the **Remove integer overflow checks** check box in the project's **Advanced Compiler Settings** dialog box, or by specifying the `/removeintchecks-` compiler option. Conversely, unchecked conversions can be performed by selecting the **Remove integer overflow checks** check box in the project's **Advanced Compiler Settings** dialog box or by specifying the `/removeintchecks+` compiler option. By default, explicit conversions are checked. - - The following C# example uses the `checked` and `unchecked` keywords to illustrate the difference in behavior when a value outside the range of a is converted to a . The checked conversion throws an exception, but the unchecked conversion assigns to the variable. - - [!code-csharp[Conceptual.Conversion#12](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.conversion/cs/explicit1.cs#12)] - - If a particular language compiler supports custom overloaded operators, you can also define explicit conversions in your own custom types. The following example provides a partial implementation of a signed byte data type named `ByteWithSign` that uses sign-and-magnitude representation. It supports explicit conversion of and values to `ByteWithSign` values. - +> In C#, checked conversions can be performed by using the `checked` keyword together with a casting operator, or by specifying the `/checked+` compiler option. Conversely, unchecked conversions can be performed by using the `unchecked` keyword together with the casting operator, or by specifying the `/checked-` compiler option. By default, explicit conversions are unchecked. In Visual Basic, checked conversions can be performed by clearing the **Remove integer overflow checks** check box in the project's **Advanced Compiler Settings** dialog box, or by specifying the `/removeintchecks-` compiler option. Conversely, unchecked conversions can be performed by selecting the **Remove integer overflow checks** check box in the project's **Advanced Compiler Settings** dialog box or by specifying the `/removeintchecks+` compiler option. By default, explicit conversions are checked. + + The following C# example uses the `checked` and `unchecked` keywords to illustrate the difference in behavior when a value outside the range of a is converted to a . The checked conversion throws an exception, but the unchecked conversion assigns to the variable. + + [!code-csharp[Conceptual.Conversion#12](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.conversion/cs/explicit1.cs#12)] + + If a particular language compiler supports custom overloaded operators, you can also define explicit conversions in your own custom types. The following example provides a partial implementation of a signed byte data type named `ByteWithSign` that uses sign-and-magnitude representation. It supports explicit conversion of and values to `ByteWithSign` values. + [!code-csharp[Conceptual.Conversion#5](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.conversion/cs/explicit1.cs#5)] - [!code-vb[Conceptual.Conversion#5](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.conversion/vb/explicit1.vb#5)] - - Client code can then declare a `ByteWithSign` variable and assign it and values if the assignments include a casting operator or a conversion method, as the following example shows. - + [!code-vb[Conceptual.Conversion#5](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.conversion/vb/explicit1.vb#5)] + + Client code can then declare a `ByteWithSign` variable and assign it and values if the assignments include a casting operator or a conversion method, as the following example shows. + [!code-csharp[Conceptual.Conversion#6](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.conversion/cs/explicit1.cs#6)] - [!code-vb[Conceptual.Conversion#6](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.conversion/vb/explicit1.vb#6)] + [!code-vb[Conceptual.Conversion#6](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.conversion/vb/explicit1.vb#6)] ## The IConvertible interface -To support the conversion of any type to a common language runtime base type, .NET provides the interface. The implementing type is required to provide the following: - -- A method that returns the of the implementing type. - -- Methods to convert the implementing type to each common language runtime base type (, , , , , and so on). - -- A generalized conversion method to convert an instance of the implementing type to another specified type. Conversions that are not supported should throw an . - - Each common language runtime base type (that is, the , , , , , , , , , , , , , , and ), as well as the and types, implement the interface. However, these are explicit interface implementations; the conversion method can be called only through an interface variable, as the following example shows. This example converts an value to its equivalent value. - +To support the conversion of any type to a common language runtime base type, .NET provides the interface. The implementing type is required to provide the following: + +- A method that returns the of the implementing type. + +- Methods to convert the implementing type to each common language runtime base type (, , , , , and so on). + +- A generalized conversion method to convert an instance of the implementing type to another specified type. Conversions that are not supported should throw an . + + Each common language runtime base type (that is, the , , , , , , , , , , , , , , and ), as well as the and types, implement the interface. However, these are explicit interface implementations; the conversion method can be called only through an interface variable, as the following example shows. This example converts an value to its equivalent value. + [!code-csharp[Conceptual.Conversion#7](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.conversion/cs/iconvertible1.cs#7)] - [!code-vb[Conceptual.Conversion#7](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.conversion/vb/iconvertible1.vb#7)] - - The requirement to call the conversion method on its interface rather than on the implementing type makes explicit interface implementations relatively expensive. Instead, we recommend that you call the appropriate member of the class to convert between common language runtime base types. For more information, see the next section, [The Convert Class](#the-convert-class). - + [!code-vb[Conceptual.Conversion#7](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.conversion/vb/iconvertible1.vb#7)] + + The requirement to call the conversion method on its interface rather than on the implementing type makes explicit interface implementations relatively expensive. Instead, we recommend that you call the appropriate member of the class to convert between common language runtime base types. For more information, see the next section, [The Convert Class](#the-convert-class). + > [!NOTE] -> In addition to the interface and the class provided by .NET, individual languages may also provide ways to perform conversions. For example, C# uses casting operators; Visual Basic uses compiler-implemented conversion functions such as `CType`, `CInt`, and `DirectCast`. - +> In addition to the interface and the class provided by .NET, individual languages may also provide ways to perform conversions. For example, C# uses casting operators; Visual Basic uses compiler-implemented conversion functions such as `CType`, `CInt`, and `DirectCast`. + For the most part, the interface is designed to support conversion between the base types in .NET. However, the interface can also be implemented by a custom type to support conversion of that type to other custom types. For more information, see the section [Custom Conversions with the ChangeType Method](#custom-conversions-with-the-changetype-method) later in this topic. ## The Convert class -Although each base type's interface implementation can be called to perform a type conversion, calling the methods of the class is the recommended language-neutral way to convert from one base type to another. In addition, the method can be used to convert from a specified custom type to another type. - +Although each base type's interface implementation can be called to perform a type conversion, calling the methods of the class is the recommended language-neutral way to convert from one base type to another. In addition, the method can be used to convert from a specified custom type to another type. + ### Conversions between base types -The class provides a language-neutral way to perform conversions between base types and is available to all languages that target the common language runtime. It provides a complete set of methods for both widening and narrowing conversions, and throws an for conversions that are not supported (such as the conversion of a value to an integer value). Narrowing conversions are performed in a checked context, and an is thrown if the conversion fails. - +The class provides a language-neutral way to perform conversions between base types and is available to all languages that target the common language runtime. It provides a complete set of methods for both widening and narrowing conversions, and throws an for conversions that are not supported (such as the conversion of a value to an integer value). Narrowing conversions are performed in a checked context, and an is thrown if the conversion fails. + > [!IMPORTANT] -> Because the class includes methods to convert to and from each base type, it eliminates the need to call each base type's explicit interface implementation. - - The following example illustrates the use of the class to perform several widening and narrowing conversions between .NET base types. - +> Because the class includes methods to convert to and from each base type, it eliminates the need to call each base type's explicit interface implementation. + + The following example illustrates the use of the class to perform several widening and narrowing conversions between .NET base types. + [!code-csharp[Conceptual.Conversion#8](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.conversion/cs/convert1.cs#8)] - [!code-vb[Conceptual.Conversion#8](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.conversion/vb/convert1.vb#8)] - - In some cases, particularly when converting to and from floating-point values, a conversion may involve a loss of precision, even though it does not throw an . The following example illustrates this loss of precision. In the first case, a value has less precision (fewer significant digits) when it is converted to a . In the second case, a value is rounded from 42.72 to 43 in order to complete the conversion. - + [!code-vb[Conceptual.Conversion#8](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.conversion/vb/convert1.vb#8)] + + In some cases, particularly when converting to and from floating-point values, a conversion may involve a loss of precision, even though it does not throw an . The following example illustrates this loss of precision. In the first case, a value has less precision (fewer significant digits) when it is converted to a . In the second case, a value is rounded from 42.72 to 43 in order to complete the conversion. + [!code-csharp[Conceptual.Conversion#9](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.conversion/cs/convert1.cs#9)] - [!code-vb[Conceptual.Conversion#9](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.conversion/vb/convert1.vb#9)] - - For a table that lists both the widening and narrowing conversions supported by the class, see [Type Conversion Tables](conversion-tables.md). + [!code-vb[Conceptual.Conversion#9](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.conversion/vb/convert1.vb#9)] + + For a table that lists both the widening and narrowing conversions supported by the class, see [Type Conversion Tables](conversion-tables.md). ### Custom conversions with the ChangeType method -In addition to supporting conversions to each of the base types, the class can be used to convert a custom type to one or more predefined types. This conversion is performed by the method, which in turn wraps a call to the method of the `value` parameter. This means that the object represented by the `value` parameter must provide an implementation of the interface. - +In addition to supporting conversions to each of the base types, the class can be used to convert a custom type to one or more predefined types. This conversion is performed by the method, which in turn wraps a call to the method of the `value` parameter. This means that the object represented by the `value` parameter must provide an implementation of the interface. + > [!NOTE] -> Because the and methods use a object to specify the target type to which `value` is converted, they can be used to perform a dynamic conversion to an object whose type is not known at compile time. However, note that the implementation of `value` must still support this conversion. - - The following example illustrates a possible implementation of the interface that allows a `TemperatureCelsius` object to be converted to a `TemperatureFahrenheit` object and vice versa. The example defines a base class, `Temperature`, that implements the interface and overrides the method. The derived `TemperatureCelsius` and `TemperatureFahrenheit` classes each override the `ToType` and the `ToString` methods of the base class. - +> Because the and methods use a object to specify the target type to which `value` is converted, they can be used to perform a dynamic conversion to an object whose type is not known at compile time. However, note that the implementation of `value` must still support this conversion. + + The following example illustrates a possible implementation of the interface that allows a `TemperatureCelsius` object to be converted to a `TemperatureFahrenheit` object and vice versa. The example defines a base class, `Temperature`, that implements the interface and overrides the method. The derived `TemperatureCelsius` and `TemperatureFahrenheit` classes each override the `ToType` and the `ToString` methods of the base class. + [!code-csharp[Conceptual.Conversion#10](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.conversion/cs/iconvertible2.cs#10)] - [!code-vb[Conceptual.Conversion#10](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.conversion/vb/iconvertible2.vb#10)] - - The following example illustrates several calls to these implementations to convert `TemperatureCelsius` objects to `TemperatureFahrenheit` objects and vice versa. - + [!code-vb[Conceptual.Conversion#10](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.conversion/vb/iconvertible2.vb#10)] + + The following example illustrates several calls to these implementations to convert `TemperatureCelsius` objects to `TemperatureFahrenheit` objects and vice versa. + [!code-csharp[Conceptual.Conversion#11](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.conversion/cs/iconvertible2.cs#11)] - [!code-vb[Conceptual.Conversion#11](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.conversion/vb/iconvertible2.vb#11)] + [!code-vb[Conceptual.Conversion#11](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.conversion/vb/iconvertible2.vb#11)] ## The TypeConverter class -.NET also allows you to define a type converter for a custom type by extending the class and associating the type converter with the type through a attribute. The following table highlights the differences between this approach and implementing the interface for a custom type. - +.NET also allows you to define a type converter for a custom type by extending the class and associating the type converter with the type through a attribute. The following table highlights the differences between this approach and implementing the interface for a custom type. + > [!NOTE] -> Design-time support can be provided for a custom type only if it has a type converter defined for it. - -|Conversion using TypeConverter|Conversion using IConvertible| -|------------------------------------|-----------------------------------| -|Is implemented for a custom type by deriving a separate class from . This derived class is associated with the custom type by applying a attribute.|Is implemented by a custom type to perform conversion. A user of the type invokes an conversion method on the type.| -|Can be used both at design time and at run time.|Can be used only at run time.| -|Uses reflection; therefore, is slower than conversion enabled by .|Does not use reflection.| -|Allows two-way type conversions from the custom type to other data types, and from other data types to the custom type. For example, a defined for `MyType` allows conversions from `MyType` to , and from to `MyType`.|Allows conversion from a custom type to other data types, but not from other data types to the custom type.| - - For more information about using type converters to perform conversions, see . - +> Design-time support can be provided for a custom type only if it has a type converter defined for it. + +|Conversion using TypeConverter|Conversion using IConvertible| +|------------------------------------|-----------------------------------| +|Is implemented for a custom type by deriving a separate class from . This derived class is associated with the custom type by applying a attribute.|Is implemented by a custom type to perform conversion. A user of the type invokes an conversion method on the type.| +|Can be used both at design time and at runtime.|Can be used only at runtime.| +|Uses reflection; therefore, is slower than conversion enabled by .|Does not use reflection.| +|Allows two-way type conversions from the custom type to other data types, and from other data types to the custom type. For example, a defined for `MyType` allows conversions from `MyType` to , and from to `MyType`.|Allows conversion from a custom type to other data types, but not from other data types to the custom type.| + + For more information about using type converters to perform conversions, see . + ## See also - diff --git a/docs/standard/clr.md b/docs/standard/clr.md index b1948b3380f71..baea559dcc2bc 100644 --- a/docs/standard/clr.md +++ b/docs/standard/clr.md @@ -1,10 +1,10 @@ --- title: "Common Language Runtime (CLR) overview - .NET" titleSuffix: "" -description: Get started with common language runtime (CLR), .NET's run-time environment. The CLR runs code and provides services to make the development process easier. +description: Get started with common language runtime (CLR), .NET's runtime environment. The CLR runs code and provides services to make the development process easier. ms.date: 10/21/2025 ms.custom: devdivchpfy22 -helpviewer_keywords: +helpviewer_keywords: - "compiling source code, runtime functionality" - "code, execution" - "managed data" @@ -21,14 +21,14 @@ ai-usage: ai-assisted --- # Common Language Runtime (CLR) overview -.NET provides a run-time environment called the common language runtime that runs the code and provides services that make the development process easier. +.NET provides a runtime environment called the common language runtime that runs the code and provides services that make the development process easier. Compilers and tools expose the common language runtime's functionality and enable you to write code that benefits from the managed execution environment. Code that you develop with a language compiler that targets the runtime is called managed code. Managed code benefits from features such as cross-language integration, cross-language exception handling, enhanced security, versioning and deployment support, a simplified model for component interaction, and debugging and profiling services. > [!NOTE] -> Compilers and tools can produce output that the common language runtime can consume because the type system, the format of metadata, and the run-time environment (the virtual execution system) are all defined by a public standard, the ECMA Common Language Infrastructure specification. For more information, see [ECMA C# and Common Language Infrastructure Specifications](../fundamentals/standards.md). +> Compilers and tools can produce output that the common language runtime can consume because the type system, the format of metadata, and the runtime environment (the virtual execution system) are all defined by a public standard, the ECMA Common Language Infrastructure specification. For more information, see [ECMA C# and Common Language Infrastructure Specifications](../fundamentals/standards.md). -To enable the runtime to provide services to managed code, language compilers must emit metadata that describes the types, members, and references in your code. Metadata is stored with the code; every loadable common language runtime portable executable (PE) file contains metadata. The runtime uses metadata to locate and load classes, lay out instances in memory, resolve method invocations, generate native code, enforce security, and set run-time context boundaries. +To enable the runtime to provide services to managed code, language compilers must emit metadata that describes the types, members, and references in your code. Metadata is stored with the code; every loadable common language runtime portable executable (PE) file contains metadata. The runtime uses metadata to locate and load classes, lay out instances in memory, resolve method invocations, generate native code, enforce security, and set runtime context boundaries. The runtime automatically handles object layout and manages references to objects, releasing them when they're no longer being used. Objects whose lifetimes are managed this way are called managed data. Garbage collection eliminates memory leaks and some other common programming errors. If your code is managed, you can use managed data, unmanaged data, or both in your .NET application. Because language compilers supply their own types, such as primitive types, you might not always know or need to know whether your data is being managed. diff --git a/docs/standard/commandline/migration-guide-2.0.0-beta5.md b/docs/standard/commandline/migration-guide-2.0.0-beta5.md index b594d74eee971..0de1ab3faef50 100644 --- a/docs/standard/commandline/migration-guide-2.0.0-beta5.md +++ b/docs/standard/commandline/migration-guide-2.0.0-beta5.md @@ -100,7 +100,7 @@ Option beta5 = new("--help", "-h", "/h") ## Default values and custom parsing -In 2.0.0-beta4, you could set default values for options and arguments by using the `SetDefaultValue` methods. Those methods accepted an `object` value, which wasn't type safe and could lead to run-time errors if the value wasn't compatible with the option or argument type: +In 2.0.0-beta4, you could set default values for options and arguments by using the `SetDefaultValue` methods. Those methods accepted an `object` value, which wasn't type safe and could lead to runtime errors if the value wasn't compatible with the option or argument type: ```csharp Option option = new("--number"); diff --git a/docs/standard/data/sqlite/extensions.md b/docs/standard/data/sqlite/extensions.md index d19b879f7937e..e039a5c4cba37 100644 --- a/docs/standard/data/sqlite/extensions.md +++ b/docs/standard/data/sqlite/extensions.md @@ -5,7 +5,7 @@ description: Learn how to load SQLite extensions. --- # Extensions -SQLite supports loading extensions at run time. Extensions include things like additional SQL functions, collations, virtual tables, and more. +SQLite supports loading extensions at runtime. Extensions include things like additional SQL functions, collations, virtual tables, and more. .NET includes additional logic for locating native libraries in additional places like referenced NuGet packages. Unfortunately, SQLite can't leverage this logic; it calls the platform API directly to load libraries. Because of this, you may need to modify the `PATH`, `LD_LIBRARY_PATH`, or `DYLD_LIBRARY_PATH` environment variables before loading SQLite extensions. There's [a sample](https://github.com/dotnet/docs/blob/main/samples/snippets/standard/data/sqlite/ExtensionsSample/Program.cs) on GitHub that demonstrates finding binaries for the current runtime inside a referenced NuGet package. diff --git a/docs/standard/data/xml/script-blocks-using-msxsl-script.md b/docs/standard/data/xml/script-blocks-using-msxsl-script.md index 37a862edff588..9ffa8834eac27 100644 --- a/docs/standard/data/xml/script-blocks-using-msxsl-script.md +++ b/docs/standard/data/xml/script-blocks-using-msxsl-script.md @@ -12,14 +12,14 @@ ms.assetid: fde6f43f-c594-486f-abcb-2211197fae20 > [!NOTE] > Script blocks are supported only in .NET Framework. They are _not_ supported on .NET Core or .NET 5 or later. -The class supports embedded scripts using the `msxsl:script` element. When the style sheet is loaded, any defined functions are compiled to common intermediate language (CIL) by the Code Document Object Model (CodeDOM) and are executed during run time. The assembly generated from the embedded script block is separate than the assembly generated for the style sheet. +The class supports embedded scripts using the `msxsl:script` element. When the style sheet is loaded, any defined functions are compiled to common intermediate language (CIL) by the Code Document Object Model (CodeDOM) and are executed during runtime. The assembly generated from the embedded script block is separate than the assembly generated for the style sheet. ## Enable XSLT script Support for embedded scripts is an optional XSLT setting on the class. Script support is disabled by default. To enable script support, create an object with the property set to `true` and pass the object to the method. > [!WARNING] -> Starting in .NET 10, the property is marked as obsolete and generates warning SYSLIB0062. Since script blocks aren't supported on .NET Core or .NET 5+, this property has no effect and setting it to `true` throws a at run time. +> Starting in .NET 10, the property is marked as obsolete and generates warning SYSLIB0062. Since script blocks aren't supported on .NET Core or .NET 5+, this property has no effect and setting it to `true` throws a at runtime. > [!NOTE] > XSLT scripting should be enabled only if you require script support and you are working in a fully trusted environment. diff --git a/docs/standard/data/xml/user-defined-functions-and-variables.md b/docs/standard/data/xml/user-defined-functions-and-variables.md index 84f27f82ee459..a08a11f474413 100644 --- a/docs/standard/data/xml/user-defined-functions-and-variables.md +++ b/docs/standard/data/xml/user-defined-functions-and-variables.md @@ -2,45 +2,45 @@ description: "Learn more about: User Defined Functions and Variables" title: "User Defined Functions and Variables" ms.date: "03/30/2017" -dev_langs: +dev_langs: - "csharp" - "vb" ms.assetid: 4772f20e-1e7f-496e-93c2-1484473be555 --- # User Defined Functions and Variables -The class provides a set of methods that are used to interact with data. You can supplement the standard XPath functions by implementing extension functions and variables for use by XPath query expressions. The method can accept a user defined context derived from . User defined functions are resolved by the custom context. - - Extension functions and variables can be useful in prevention of XML injection attacks. In these scenarios user input is assigned to custom variables and processed by extension functions, not as raw input concatenated with processing instructions. Extension functions and variables contain user input so that it only acts on XML data as intended by the designer. - - To use extensions you implement a custom class along with the interfaces and that support extension functions and variables. An adds user input with its to the custom . - - The represents a compiled query that uses to find and process the nodes identified by the expression. - - The following example shows implementation of a custom context class derived from . Comments in the code describe class members and their use in custom functions. Function and variable implementations and a sample application that uses these implementations follow this code segment. - +The class provides a set of methods that are used to interact with data. You can supplement the standard XPath functions by implementing extension functions and variables for use by XPath query expressions. The method can accept a user defined context derived from . User defined functions are resolved by the custom context. + + Extension functions and variables can be useful in prevention of XML injection attacks. In these scenarios user input is assigned to custom variables and processed by extension functions, not as raw input concatenated with processing instructions. Extension functions and variables contain user input so that it only acts on XML data as intended by the designer. + + To use extensions you implement a custom class along with the interfaces and that support extension functions and variables. An adds user input with its to the custom . + + The represents a compiled query that uses to find and process the nodes identified by the expression. + + The following example shows implementation of a custom context class derived from . Comments in the code describe class members and their use in custom functions. Function and variable implementations and a sample application that uses these implementations follow this code segment. + [!code-csharp[XPathExtensionFunctions#2](../../../../samples/snippets/csharp/VS_Snippets_Data/xpathextensionfunctions/cs/xpathextensionfunctions.cs#2)] - [!code-vb[XPathExtensionFunctions#2](../../../../samples/snippets/visualbasic/VS_Snippets_Data/xpathextensionfunctions/vb/xpathextensionfunctions.vb#2)] - - The following code implements . The class that implements resolves and executes user-defined functions. This example uses the function identified by the declaration: `private int CountChar(string title, char charToCount)`. - - Code comments describe class members. - + [!code-vb[XPathExtensionFunctions#2](../../../../samples/snippets/visualbasic/VS_Snippets_Data/xpathextensionfunctions/vb/xpathextensionfunctions.vb#2)] + + The following code implements . The class that implements resolves and executes user-defined functions. This example uses the function identified by the declaration: `private int CountChar(string title, char charToCount)`. + + Code comments describe class members. + [!code-csharp[XPathExtensionFunctions#3](../../../../samples/snippets/csharp/VS_Snippets_Data/xpathextensionfunctions/cs/xpathextensionfunctions.cs#3)] - [!code-vb[XPathExtensionFunctions#3](../../../../samples/snippets/visualbasic/VS_Snippets_Data/xpathextensionfunctions/vb/xpathextensionfunctions.vb#3)] - - The following code implements . This class resolves references to user-defined variables in XPath query expressions at run time. An instance of this class is created and returned by the overridden method of the custom class. - - Code comments describe the class members. - + [!code-vb[XPathExtensionFunctions#3](../../../../samples/snippets/visualbasic/VS_Snippets_Data/xpathextensionfunctions/vb/xpathextensionfunctions.vb#3)] + + The following code implements . This class resolves references to user-defined variables in XPath query expressions at runtime. An instance of this class is created and returned by the overridden method of the custom class. + + Code comments describe the class members. + [!code-csharp[XPathExtensionFunctions#4](../../../../samples/snippets/csharp/VS_Snippets_Data/xpathextensionfunctions/cs/xpathextensionfunctions.cs#4)] - [!code-vb[XPathExtensionFunctions#4](../../../../samples/snippets/visualbasic/VS_Snippets_Data/xpathextensionfunctions/vb/xpathextensionfunctions.vb#4)] - - With the previous class definitions in scope, the following code uses the custom function to count characters in the elements of the `Tasks.xml` document. Comments in the code describe the code that compiles the custom function and runs it against the `Tasks.xml` document. - + [!code-vb[XPathExtensionFunctions#4](../../../../samples/snippets/visualbasic/VS_Snippets_Data/xpathextensionfunctions/vb/xpathextensionfunctions.vb#4)] + + With the previous class definitions in scope, the following code uses the custom function to count characters in the elements of the `Tasks.xml` document. Comments in the code describe the code that compiles the custom function and runs it against the `Tasks.xml` document. + [!code-csharp[XPathExtensionFunctions#1](../../../../samples/snippets/csharp/VS_Snippets_Data/xpathextensionfunctions/cs/xpathextensionfunctions.cs#1)] - [!code-vb[XPathExtensionFunctions#1](../../../../samples/snippets/visualbasic/VS_Snippets_Data/xpathextensionfunctions/vb/xpathextensionfunctions.vb#1)] - - This example uses the following XML data. - + [!code-vb[XPathExtensionFunctions#1](../../../../samples/snippets/visualbasic/VS_Snippets_Data/xpathextensionfunctions/vb/xpathextensionfunctions.vb#1)] + + This example uses the following XML data. + [!code-xml[XPathExtensionFunctions#5](../../../../samples/snippets/xml/VS_Snippets_Data/xpathextensionfunctions/XML/tasks.xml#5)] diff --git a/docs/standard/design-guidelines/attributes.md b/docs/standard/design-guidelines/attributes.md index 58a5fe5e6dd00..1f59d9766d42a 100644 --- a/docs/standard/design-guidelines/attributes.md +++ b/docs/standard/design-guidelines/attributes.md @@ -13,7 +13,7 @@ ms.assetid: ee0038ef-b247-4747-a650-3c5c5cd58d8b is a base class used to define custom attributes. - Attributes are annotations that can be added to programming elements such as assemblies, types, members, and parameters. They are stored in the metadata of the assembly and can be accessed at run time using the reflection APIs. For example, the Framework defines the , which can be applied to a type or a member to indicate that the type or member has been deprecated. + Attributes are annotations that can be added to programming elements such as assemblies, types, members, and parameters. They are stored in the metadata of the assembly and can be accessed at runtime using the reflection APIs. For example, the Framework defines the , which can be applied to a type or a member to indicate that the type or member has been deprecated. Attributes can have one or more properties that carry additional data related to the attribute. For example, `ObsoleteAttribute` could carry additional information about the release in which a type or a member got deprecated and the description of the new APIs replacing the obsolete API. diff --git a/docs/standard/design-guidelines/events-and-callbacks.md b/docs/standard/design-guidelines/events-and-callbacks.md index 12c365827f27b..9e2e361e2ddd7 100644 --- a/docs/standard/design-guidelines/events-and-callbacks.md +++ b/docs/standard/design-guidelines/events-and-callbacks.md @@ -27,7 +27,7 @@ Callbacks are extensibility points that allow a framework to call back into user ✔️ DO use the new `Func<...>`, `Action<...>`, or `Expression<...>` types instead of custom delegates, when defining APIs with callbacks. - `Func<...>` and `Action<...>` represent generic delegates. `Expression<...>` represents function definitions that can be compiled and subsequently invoked at run time but can also be serialized and passed to remote processes. + `Func<...>` and `Action<...>` represent generic delegates. `Expression<...>` represents function definitions that can be compiled and subsequently invoked at runtime but can also be serialized and passed to remote processes. ✔️ DO measure and understand performance implications of using `Expression<...>`, instead of using `Func<...>` and `Action<...>` delegates. diff --git a/docs/standard/design-guidelines/extension-methods.md b/docs/standard/design-guidelines/extension-methods.md index c37995e61e045..e3bfc54e18113 100644 --- a/docs/standard/design-guidelines/extension-methods.md +++ b/docs/standard/design-guidelines/extension-methods.md @@ -24,7 +24,7 @@ Extension methods are a language feature that allows static methods to be called ❌ AVOID defining extension methods on . - VB users will not be able to call such methods on object references using the extension method syntax. VB does not support calling such methods because, in VB, declaring a reference as Object forces all method invocations on it to be late bound (actual member called is determined at run time), while bindings to extension methods are determined at compile-time (early bound). + VB users will not be able to call such methods on object references using the extension method syntax. VB does not support calling such methods because, in VB, declaring a reference as Object forces all method invocations on it to be late bound (actual member called is determined at runtime), while bindings to extension methods are determined at compile-time (early bound). Note that the guideline applies to other languages where the same binding behavior is present, or where extension methods are not supported. diff --git a/docs/standard/design-guidelines/virtual-members.md b/docs/standard/design-guidelines/virtual-members.md index 8d75ba3f701f6..8a976ba28ddba 100644 --- a/docs/standard/design-guidelines/virtual-members.md +++ b/docs/standard/design-guidelines/virtual-members.md @@ -16,7 +16,7 @@ Virtual members can be overridden, thus changing the behavior of the subclass. T Virtual members perform better than callbacks and events, but do not perform better than non-virtual methods. - The main disadvantage of virtual members is that the behavior of a virtual member can only be modified at the time of compilation. The behavior of a callback can be modified at run time. + The main disadvantage of virtual members is that the behavior of a virtual member can only be modified at the time of compilation. The behavior of a callback can be modified at runtime. Virtual members, like callbacks (and maybe more than callbacks), are costly to design, test, and maintain because any call to a virtual member can be overridden in unpredictable ways and can execute arbitrary code. Also, much more effort is usually required to clearly define the contract of virtual members, so the cost of designing and documenting them is higher. diff --git a/docs/standard/events/index.md b/docs/standard/events/index.md index 7d31120ede1ef..dd763be6dc2b5 100644 --- a/docs/standard/events/index.md +++ b/docs/standard/events/index.md @@ -4,10 +4,10 @@ description: Learn to handle and raise .NET events, which are based on the deleg ms.date: 03/17/2025 ms.topic: concept-article ms.custom: devdivchpfy22 -dev_langs: +dev_langs: - "csharp" - "vb" -helpviewer_keywords: +helpviewer_keywords: - "delegate model for events" - "application development [.NET], events" - "application development [.NET], events" @@ -22,72 +22,72 @@ ms.assetid: b6f65241-e0ad-4590-a99f-200ce741bb1f # Handle and raise events Events in .NET are based on the delegate model. The delegate model follows the [observer design pattern](observer-design-pattern.md), which enables a subscriber to register with and receive notifications from a provider. An event sender pushes a notification when an event occurs. An event receiver defines the response. This article describes the major components of the delegate model, how to consume events in applications, and how to implement events in your code. - + ## Raise events with an event sender -An event is a message sent by an object to signal the occurrence of an action. The action might be user interaction, such as a button press, or it might result from other program logic, such as a property value change. The object that raises the event is called the *event sender*. The event sender doesn't know the object or method that receives (handles) the events it raises. The event is typically a member of the event sender. For example, the event is a member of the class, and the event is a member of the class that implements the interface. - -To define an event, you use the C# [event](../../csharp/language-reference/keywords/event.md) or the Visual Basic [Event](../../visual-basic/language-reference/statements/event-statement.md) keyword in the signature of your event class, and specify the type of delegate for the event. Delegates are described in the next section. - -Typically, to raise an event, you add a method that is marked as `protected` and `virtual` (in C#) or `Protected` and `Overridable` (in Visual Basic). The naming convention for the method is `On`, such as `OnDataReceived`. The method should take one parameter that specifies an event data object, which is an object of type or a derived type. You provide this method to enable derived classes to override the logic for raising the event. A derived class should always call the `On` method of the base class to ensure registered delegates receive the event. +An event is a message sent by an object to signal the occurrence of an action. The action might be user interaction, such as a button press, or it might result from other program logic, such as a property value change. The object that raises the event is called the *event sender*. The event sender doesn't know the object or method that receives (handles) the events it raises. The event is typically a member of the event sender. For example, the event is a member of the class, and the event is a member of the class that implements the interface. + +To define an event, you use the C# [event](../../csharp/language-reference/keywords/event.md) or the Visual Basic [Event](../../visual-basic/language-reference/statements/event-statement.md) keyword in the signature of your event class, and specify the type of delegate for the event. Delegates are described in the next section. + +Typically, to raise an event, you add a method that is marked as `protected` and `virtual` (in C#) or `Protected` and `Overridable` (in Visual Basic). The naming convention for the method is `On`, such as `OnDataReceived`. The method should take one parameter that specifies an event data object, which is an object of type or a derived type. You provide this method to enable derived classes to override the logic for raising the event. A derived class should always call the `On` method of the base class to ensure registered delegates receive the event. The following example shows how to declare an event named `ThresholdReached`. The event is associated with the delegate and raised in a method named `OnThresholdReached`: - + [!code-csharp[EventsOverview#1](~/samples/snippets/csharp/VS_Snippets_CLR/eventsoverview/cs/programtruncated.cs#1)] -[!code-vb[EventsOverview#1](~/samples/snippets/visualbasic/VS_Snippets_CLR/eventsoverview/vb/module1truncated.vb#1)] - +[!code-vb[EventsOverview#1](~/samples/snippets/visualbasic/VS_Snippets_CLR/eventsoverview/vb/module1truncated.vb#1)] + ## Declare delegate signatures for event handlers -A delegate is a type that holds a reference to a method. A delegate is declared with a signature that shows the return type and parameters for the methods it references. It can hold references only to methods that match its signature. A delegate is equivalent to a type-safe function pointer or a callback. A delegate declaration is sufficient to define a delegate class. - -Delegates have many uses in .NET. In the context of events, a delegate is an intermediary (or pointer-like mechanism) between the event source and the code that handles the event. You associate a delegate with an event by including the delegate type in the event declaration, as shown in the example in the previous section. For more information about delegates, see the class. - -.NET provides the and delegates to support most event scenarios. Use the delegate for all events that don't include event data. Use the delegate for events that include data about the event. These delegates have no return type value and take two parameters (an object for the source of the event and an object for event data). - -Delegates are [multicast](xref:System.MulticastDelegate) class objects, which means they can hold references to more than one event-handling method. For more information, see the reference page. Delegates provide flexibility and fine-grained control in event handling. A delegate acts as an event dispatcher for the class that raises the event by maintaining a list of registered event handlers for the event. - -Use the and delegate types to define the needed delegate. You mark a delegate with the `delegate` type in [C#](../../csharp/language-reference/builtin-types/reference-types.md#the-delegate-type) or the `Delegate` type in [Visual Basic](../../visual-basic/language-reference/statements/delegate-statement.md) in the declaration. The following example shows how to declare a delegate named `ThresholdReachedEventHandler`: - +A delegate is a type that holds a reference to a method. A delegate is declared with a signature that shows the return type and parameters for the methods it references. It can hold references only to methods that match its signature. A delegate is equivalent to a type-safe function pointer or a callback. A delegate declaration is sufficient to define a delegate class. + +Delegates have many uses in .NET. In the context of events, a delegate is an intermediary (or pointer-like mechanism) between the event source and the code that handles the event. You associate a delegate with an event by including the delegate type in the event declaration, as shown in the example in the previous section. For more information about delegates, see the class. + +.NET provides the and delegates to support most event scenarios. Use the delegate for all events that don't include event data. Use the delegate for events that include data about the event. These delegates have no return type value and take two parameters (an object for the source of the event and an object for event data). + +Delegates are [multicast](xref:System.MulticastDelegate) class objects, which means they can hold references to more than one event-handling method. For more information, see the reference page. Delegates provide flexibility and fine-grained control in event handling. A delegate acts as an event dispatcher for the class that raises the event by maintaining a list of registered event handlers for the event. + +Use the and delegate types to define the needed delegate. You mark a delegate with the `delegate` type in [C#](../../csharp/language-reference/builtin-types/reference-types.md#the-delegate-type) or the `Delegate` type in [Visual Basic](../../visual-basic/language-reference/statements/delegate-statement.md) in the declaration. The following example shows how to declare a delegate named `ThresholdReachedEventHandler`: + [!code-csharp[EventsOverview#4](~/samples/snippets/csharp/VS_Snippets_CLR/eventsoverview/cs/programtruncated.cs#4)] -[!code-vb[EventsOverview#4](~/samples/snippets/visualbasic/VS_Snippets_CLR/eventsoverview/vb/module1truncated.vb#4)] - +[!code-vb[EventsOverview#4](~/samples/snippets/visualbasic/VS_Snippets_CLR/eventsoverview/vb/module1truncated.vb#4)] + ## Work with event data classes -Data associated with an event can be provided through an event data class. .NET provides many event data classes that you can use in your applications. For example, the class is the event data class for the event. .NET follows a naming pattern where all event data classes end with the `EventArgs` suffix. You determine which event data class is associated with an event by looking at the delegate for the event. For example, the delegate includes the class as a parameter. - -The class is typically the base type for event data classes. You also use this class if an event doesn't have any data associated with it. When you create an event that notifies subscribers that something happened without any additional data, include the class as the second parameter in the delegate. You can pass the value when no data is provided. The delegate includes the class as a parameter. - -You can create a class that derives from the class to provide any members needed to pass data related to the event. Typically, you should use the same naming pattern as .NET and end your event data class name with the `EventArgs` suffix. - +Data associated with an event can be provided through an event data class. .NET provides many event data classes that you can use in your applications. For example, the class is the event data class for the event. .NET follows a naming pattern where all event data classes end with the `EventArgs` suffix. You determine which event data class is associated with an event by looking at the delegate for the event. For example, the delegate includes the class as a parameter. + +The class is typically the base type for event data classes. You also use this class if an event doesn't have any data associated with it. When you create an event that notifies subscribers that something happened without any additional data, include the class as the second parameter in the delegate. You can pass the value when no data is provided. The delegate includes the class as a parameter. + +You can create a class that derives from the class to provide any members needed to pass data related to the event. Typically, you should use the same naming pattern as .NET and end your event data class name with the `EventArgs` suffix. + The following example shows an event data class named `ThresholdReachedEventArgs` that contains properties that are specific to the event being raised: - + [!code-csharp[EventsOverview#3](~/samples/snippets/csharp/VS_Snippets_CLR/eventsoverview/cs/programtruncated.cs#3)] -[!code-vb[EventsOverview#3](~/samples/snippets/visualbasic/VS_Snippets_CLR/eventsoverview/vb/module1truncated.vb#3)] - +[!code-vb[EventsOverview#3](~/samples/snippets/visualbasic/VS_Snippets_CLR/eventsoverview/vb/module1truncated.vb#3)] + ## Respond to events with handlers -To respond to an event, you define an event handler method in the event receiver. This method must match the signature of the delegate for the event you're handling. In the event handler, you perform the actions that are required when the event is raised, such as collecting user input after the user presses a button. To receive notifications when the event occurs, your event handler method must subscribe to the event. - +To respond to an event, you define an event handler method in the event receiver. This method must match the signature of the delegate for the event you're handling. In the event handler, you perform the actions that are required when the event is raised, such as collecting user input after the user presses a button. To receive notifications when the event occurs, your event handler method must subscribe to the event. + The following example shows an event handler method named `c_ThresholdReached` that matches the signature for the delegate. The method subscribes to the `ThresholdReached` event: - + [!code-csharp[EventsOverview#2](~/samples/snippets/csharp/VS_Snippets_CLR/eventsoverview/cs/programtruncated.cs#2)] -[!code-vb[EventsOverview#2](~/samples/snippets/visualbasic/VS_Snippets_CLR/eventsoverview/vb/module1truncated.vb#2)] +[!code-vb[EventsOverview#2](~/samples/snippets/visualbasic/VS_Snippets_CLR/eventsoverview/vb/module1truncated.vb#2)] + +## Use static and dynamic event handlers -## Use static and dynamic event handlers +.NET allows subscribers to register for event notifications either statically or dynamically. Static event handlers are in effect for the entire life of the class whose events they handle. Dynamic event handlers are explicitly activated and deactivated during program execution, usually in response to some conditional program logic. You can use dynamic handlers when event notifications are needed only under certain conditions, or when runtime conditions determine the specific handler to call. The example in the previous section shows how to dynamically add an event handler. For more information, see [Events](../../visual-basic/programming-guide/language-features/events/index.md) (in Visual Basic) and [Events](../../csharp/programming-guide/events/index.md) (in C#). -.NET allows subscribers to register for event notifications either statically or dynamically. Static event handlers are in effect for the entire life of the class whose events they handle. Dynamic event handlers are explicitly activated and deactivated during program execution, usually in response to some conditional program logic. You can use dynamic handlers when event notifications are needed only under certain conditions, or when run-time conditions determine the specific handler to call. The example in the previous section shows how to dynamically add an event handler. For more information, see [Events](../../visual-basic/programming-guide/language-features/events/index.md) (in Visual Basic) and [Events](../../csharp/programming-guide/events/index.md) (in C#). - ## Raise multiple events -If your class raises multiple events, the compiler generates one field per event delegate instance. If the number of events is large, the storage cost of one field per delegate might not be acceptable. For these scenarios, .NET provides event properties that you can use with another data structure of your choice to store event delegates. - +If your class raises multiple events, the compiler generates one field per event delegate instance. If the number of events is large, the storage cost of one field per delegate might not be acceptable. For these scenarios, .NET provides event properties that you can use with another data structure of your choice to store event delegates. + Event properties consist of event declarations accompanied by event accessors. Event accessors are methods that you define to add or remove event delegate instances from the storage data structure. > [!NOTE] > The event properties are slower than the event fields because each event delegate must be retrieved before it can be invoked. -The trade-off is between memory and speed. If your class defines many events that are infrequently raised, you should implement event properties. For more information, see [Handle multiple events by using event properties](how-to-handle-multiple-events-using-event-properties.md). - +The trade-off is between memory and speed. If your class defines many events that are infrequently raised, you should implement event properties. For more information, see [Handle multiple events by using event properties](how-to-handle-multiple-events-using-event-properties.md). + ## Explore related tasks The following resources describe other tasks and concepts related to working with events: @@ -100,7 +100,7 @@ The following resources describe other tasks and concepts related to working wit Specification reference documentation is available for the APIs that support event handling: -| API name | API type | Reference | +| API name | API type | Reference | | --- | --- | --- | | EventHandler | Delegate | | | EventHandler\ | Delegate | | diff --git a/docs/standard/exceptions/how-to-create-localized-exception-messages.md b/docs/standard/exceptions/how-to-create-localized-exception-messages.md index 836f9a77ab071..9819c618e45a6 100644 --- a/docs/standard/exceptions/how-to-create-localized-exception-messages.md +++ b/docs/standard/exceptions/how-to-create-localized-exception-messages.md @@ -122,7 +122,7 @@ Throw New StudentNotFoundException("The student cannot be found.", "John") ``` The problem with the previous line is that `"The student cannot be found."` is just a constant string. In a localized application, you want to have different messages depending on user culture. -[Satellite assemblies](../../core/extensions/create-satellite-assemblies.md) are a good way to do that. A satellite assembly is a DLL that contains resources for a specific language. When you ask for a specific resources at run time, the CLR finds that resource depending on user culture. If no satellite assembly is found for that culture, the resources of the default culture are used. +[Satellite assemblies](../../core/extensions/create-satellite-assemblies.md) are a good way to do that. A satellite assembly is a DLL that contains resources for a specific language. When you ask for a specific resources at runtime, the CLR finds that resource depending on user culture. If no satellite assembly is found for that culture, the resources of the default culture are used. To create the localized exception messages: diff --git a/docs/standard/frameworks.md b/docs/standard/frameworks.md index c6fcc14740dd9..82dea61268b4b 100644 --- a/docs/standard/frameworks.md +++ b/docs/standard/frameworks.md @@ -99,7 +99,7 @@ Use these guidelines to determine which TFM to use in your app: #### OS version in TFMs -You can also specify an optional OS version at the end of an OS-specific TFM, for example, `net8.0-ios17.2`. The version indicates which APIs are available to your app or library. It doesn't control the OS version that your app or library supports at run time. It's used to select the reference assemblies that your project compiles against, and to select assets from NuGet packages. Think of this version as the "platform version" or "OS API version" to disambiguate it from the run-time OS version. +You can also specify an optional OS version at the end of an OS-specific TFM, for example, `net8.0-ios17.2`. The version indicates which APIs are available to your app or library. It doesn't control the OS version that your app or library supports at runtime. It's used to select the reference assemblies that your project compiles against, and to select assets from NuGet packages. Think of this version as the "platform version" or "OS API version" to disambiguate it from the runtime OS version. The .NET SDK is designed to be able to support newly released APIs for an individual platform without a new version of the base TFM. This enables you to access platform-specific functionality without waiting for a major release of .NET. You can gain access to these newly released APIs by incrementing the platform version in the TFM. For example, if the Android platform added API level 34 APIs in a .NET 8.0.x SDK update, you could access them by using the TFM `net8.0-android34.0`. @@ -130,7 +130,7 @@ If your app references a package that has multiple assets for different TFMs, th #### Support older OS versions -Although a platform-specific app or library is compiled against APIs from a specific version of that OS, you can make it compatible with earlier OS versions by adding the `SupportedOSPlatformVersion` property to your project file. The `SupportedOSPlatformVersion` property indicates the minimum OS version required to run your app or library. If you don't explicitly specify this minimum run-time OS version in the project, it defaults to the platform version from the TFM. +Although a platform-specific app or library is compiled against APIs from a specific version of that OS, you can make it compatible with earlier OS versions by adding the `SupportedOSPlatformVersion` property to your project file. The `SupportedOSPlatformVersion` property indicates the minimum OS version required to run your app or library. If you don't explicitly specify this minimum runtime OS version in the project, it defaults to the platform version from the TFM. For your app to run correctly on an older OS version, it can't call APIs that don't exist on that version of the OS. However, you can add guards around calls to newer APIs so they are only called when running on a version of the OS that supports them. This pattern allows you to design your app or library to support running on older OS versions while taking advantage of newer OS functionality when running on newer OS versions. diff --git a/docs/standard/garbage-collection/using-objects.md b/docs/standard/garbage-collection/using-objects.md index f687222e4a0a1..864d33d2f3576 100644 --- a/docs/standard/garbage-collection/using-objects.md +++ b/docs/standard/garbage-collection/using-objects.md @@ -56,7 +56,7 @@ Instead of wrapping a `try/finally` block in a `using` statement, you may choose - To include a `catch` block to handle exceptions thrown in the `try` block. Otherwise, any exceptions thrown within the `using` statement are unhandled. - To instantiate an object that implements whose scope is not local to the block within which it is declared. -The following example is similar to the previous example, except that it uses a `try/catch/finally` block to instantiate, use, and dispose of a object, and to handle any exceptions thrown by the constructor and its method. The code in the `finally` block checks that the object that implements isn't `null` before it calls the method. Failure to do this can result in a exception at run time. +The following example is similar to the previous example, except that it uses a `try/catch/finally` block to instantiate, use, and dispose of a object, and to handle any exceptions thrown by the constructor and its method. The code in the `finally` block checks that the object that implements isn't `null` before it calls the method. Failure to do this can result in a exception at runtime. :::code language="csharp" source="../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.disposable/cs/TryExplicitCatchFinally.cs"::: :::code language="vb" source="../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.disposable/vb/TryExplicitCatchFinally.vb"::: diff --git a/docs/standard/generics.md b/docs/standard/generics.md index a9642d87761d6..b4a2622d32c3e 100644 --- a/docs/standard/generics.md +++ b/docs/standard/generics.md @@ -13,9 +13,9 @@ First introduced in .NET Framework 2.0, generics are essentially a "code templat To understand why generics are useful, let's take a look at a specific class before and after adding generics: . In .NET Framework 1.0, the `ArrayList` elements were of type . Any element added to the collection was silently converted into an `Object`. The same would happen when reading elements from the list. This process is known as [boxing and unboxing](../csharp/programming-guide/types/boxing-and-unboxing.md), and it impacts performance. Aside from performance, however, there's no way to determine the type of data in the list at compile time, which makes for some fragile code. Generics solve this problem by defining the type of data each instance of list will contain. For example, you can only add integers to `List` and only add Persons to `List`. -Generics are also available at run time. The runtime knows what type of data structure you're using and can store it in memory more efficiently. +Generics are also available at runtime. The runtime knows what type of data structure you're using and can store it in memory more efficiently. -The following example is a small program that illustrates the efficiency of knowing the data structure type at run time: +The following example is a small program that illustrates the efficiency of knowing the data structure type at runtime: ```csharp using System; diff --git a/docs/standard/generics/index.md b/docs/standard/generics/index.md index d341bc8491dc2..c88990c75c8da 100644 --- a/docs/standard/generics/index.md +++ b/docs/standard/generics/index.md @@ -74,7 +74,7 @@ The following terms are used to discuss generics in .NET: There are many advantages to using generic collections and delegates: -- Type safety. Generics shift the burden of type safety from you to the compiler. There is no need to write code to test for the correct data type because it is enforced at compile time. The need for type casting and the possibility of run-time errors are reduced. +- Type safety. Generics shift the burden of type safety from you to the compiler. There is no need to write code to test for the correct data type because it is enforced at compile time. The need for type casting and the possibility of runtime errors are reduced. - Less code and code is more easily reused. There is no need to inherit from a base type and override members. For example, the is ready for immediate use. For example, you can create a linked list of strings with the following variable declaration: diff --git a/docs/standard/glossary.md b/docs/standard/glossary.md index f3e4e043ee1ae..7a96c5ed33ffc 100644 --- a/docs/standard/glossary.md +++ b/docs/standard/glossary.md @@ -12,7 +12,7 @@ The primary goal of this glossary is to clarify meanings of selected terms and a Ahead-of-time compiler. -Similar to [JIT](#jit), this compiler also translates [IL](#il) to machine code. In contrast to JIT compilation, AOT compilation happens before the application is executed and is usually performed on a different machine. Because AOT tool chains don't compile at run time, they don't have to minimize time spent compiling. That means they can spend more time optimizing. Since the context of AOT is the entire application, the AOT compiler also performs cross-module linking and whole-program analysis, which means that all references are followed and a single executable is produced. +Similar to [JIT](#jit), this compiler also translates [IL](#il) to machine code. In contrast to JIT compilation, AOT compilation happens before the application is executed and is usually performed on a different machine. Because AOT tool chains don't compile at runtime, they don't have to minimize time spent compiling. That means they can spend more time optimizing. Since the context of AOT is the entire application, the AOT compiler also performs cross-module linking and whole-program analysis, which means that all references are followed and a single executable is produced. See [CoreRT](#corert) and [.NET Native](#net-native). @@ -86,7 +86,7 @@ See [CLR](#clr). ## CoreRT -In contrast to the [CLR](#clr), CoreRT is not a virtual machine, which means it doesn't include the facilities to generate and run code on-the-fly because it doesn't include a [JIT](#jit). It does, however, include the [GC](#gc) and the ability for run-time type identification (RTTI) and reflection. However, its type system is designed so that metadata for reflection isn't required. Not requiring metadata enables having an [AOT](#aot) tool chain that can link away superfluous metadata and (more importantly) identify code that the app doesn't use. CoreRT is in development. +In contrast to the [CLR](#clr), CoreRT is not a virtual machine, which means it doesn't include the facilities to generate and run code on-the-fly because it doesn't include a [JIT](#jit). It does, however, include the [GC](#gc) and the ability for runtime type identification (RTTI) and reflection. However, its type system is designed so that metadata for reflection isn't required. Not requiring metadata enables having an [AOT](#aot) tool chain that can link away superfluous metadata and (more importantly) identify code that the app doesn't use. CoreRT is in development. See [Intro to CoreRT](https://github.com/dotnet/corert/blob/master/Documentation/intro-to-corert.md) and [.NET Runtime Lab](https://github.com/dotnet/runtimelab/blob/docs/README.md). @@ -141,7 +141,7 @@ Higher-level .NET languages, such as C#, compile down to a hardware-agnostic ins Just-in-time compiler. -Similar to [AOT](#aot), this compiler translates [IL](#il) to machine code that the processor understands. Unlike AOT, JIT compilation happens on demand and is performed on the same machine that the code needs to run on. Since JIT compilation occurs during execution of the application, the compile time is part of the run time. Thus, JIT compilers have to balance time spent optimizing code against the savings that the resulting code can produce. But a JIT knows the actual hardware and can free developers from having to ship different implementations. +Similar to [AOT](#aot), this compiler translates [IL](#il) to machine code that the processor understands. Unlike AOT, JIT compilation happens on demand and is performed on the same machine that the code needs to run on. Since JIT compilation occurs during execution of the application, the compile time is part of the runtime. Thus, JIT compilers have to balance time spent optimizing code against the savings that the resulting code can produce. But a JIT knows the actual hardware and can free developers from having to ship different implementations. ## implementation of .NET @@ -181,7 +181,7 @@ For more information, see the [Mono documentation](https://www.mono-project.com/ ## Native AOT -A deployment mode where the app is self-contained and is [ahead-of-time](#aot) compiled to native code at the time of publish. Native AOT apps don't use a [JIT](#jit) compiler at run time. They can run on machines that don't have the .NET runtime installed. +A deployment mode where the app is self-contained and is [ahead-of-time](#aot) compiled to native code at the time of publish. Native AOT apps don't use a [JIT](#jit) compiler at runtime. They can run on machines that don't have the .NET runtime installed. For more information, see [Native AOT deployment](../core/deploying/native-aot/index.md). diff --git a/docs/standard/library-guidance/cross-platform-targeting.md b/docs/standard/library-guidance/cross-platform-targeting.md index 50cb2593205fd..b2f7b750423c0 100644 --- a/docs/standard/library-guidance/cross-platform-targeting.md +++ b/docs/standard/library-guidance/cross-platform-targeting.md @@ -70,7 +70,7 @@ To shield your consumers from having to build for individual frameworks, you sho > Targeting .NET implementations allows you to call platform-specific APIs that are outside of .NET Standard. > -> Do not drop support for .NET Standard when you do this. Instead, throw from the implementation and offer capability APIs. This way, your library can be used anywhere and supports run-time light-up of features. +> Do not drop support for .NET Standard when you do this. Instead, throw from the implementation and offer capability APIs. This way, your library can be used anywhere and supports runtime light-up of features. ```csharp public static class GpsLocation diff --git a/docs/standard/library-guidance/dependencies.md b/docs/standard/library-guidance/dependencies.md index c4e65b7303739..a7c156baae98d 100644 --- a/docs/standard/library-guidance/dependencies.md +++ b/docs/standard/library-guidance/dependencies.md @@ -18,7 +18,7 @@ At build time, NuGet analyzes all the packages that a project depends on, includ Most diamond dependencies are easily resolved; however, they can create issues in certain circumstances: - **Conflicting NuGet package references** prevent a version from being resolved during package restore. -- **Breaking changes between the versions** cause bugs and exceptions at run time. +- **Breaking changes between the versions** cause bugs and exceptions at runtime. - **The package assembly is strong named**, the assembly version changed, and the app is running on .NET Framework. Assembly binding redirects are required. It's not possible to know what packages will be used alongside your own. A good way to reduce the likelihood of a diamond dependency breaking your library is to minimize the number of packages you depend on. diff --git a/docs/standard/library-guidance/versioning.md b/docs/standard/library-guidance/versioning.md index cdb1f473532b0..f27777a3ee7e2 100644 --- a/docs/standard/library-guidance/versioning.md +++ b/docs/standard/library-guidance/versioning.md @@ -42,15 +42,15 @@ Because the NuGet package version is the most visible version to developers, it' ### Assembly version -The assembly version is what the CLR uses at run time to select which version of an assembly to load. Selecting an assembly using versioning only applies to assemblies with a strong name. +The assembly version is what the CLR uses at runtime to select which version of an assembly to load. Selecting an assembly using versioning only applies to assemblies with a strong name. ```xml 1.0.0.0 ``` -The .NET Framework CLR demands an exact match to load a strong-named assembly. For example, `Library1, Version=1.0.0.0` was compiled with a reference to `Newtonsoft.Json, Version=11.0.0.0`. .NET Framework will only load that exact version `11.0.0.0`. To load a different version at run time, a binding redirect must be added to the .NET application's config file. +The .NET Framework CLR demands an exact match to load a strong-named assembly. For example, `Library1, Version=1.0.0.0` was compiled with a reference to `Newtonsoft.Json, Version=11.0.0.0`. .NET Framework will only load that exact version `11.0.0.0`. To load a different version at runtime, a binding redirect must be added to the .NET application's config file. -Strong naming combined with assembly version enables [strict assembly version loading](../assembly/versioning.md). While strong naming a library has a number of benefits, it often results in run-time exceptions that an assembly can't be found and [requires binding redirects](../../framework/configure-apps/redirect-assembly-versions.md) in `app.config` or `web.config` to be fixed. In .NET (Core), assembly loading is more relaxed. The .NET (Core) runtime automatically loads assemblies with a higher version at run time. +Strong naming combined with assembly version enables [strict assembly version loading](../assembly/versioning.md). While strong naming a library has a number of benefits, it often results in runtime exceptions that an assembly can't be found and [requires binding redirects](../../framework/configure-apps/redirect-assembly-versions.md) in `app.config` or `web.config` to be fixed. In .NET (Core), assembly loading is more relaxed. The .NET (Core) runtime automatically loads assemblies with a higher version at runtime. ✔️ CONSIDER only including a major version in the AssemblyVersion. @@ -66,7 +66,7 @@ Strong naming combined with assembly version enables [strict assembly version lo ### Assembly file version -The assembly file version is used to display a file version in Windows and has no effect on run-time behavior. Setting this version is optional. It's visible in the File Properties dialog in Windows Explorer: +The assembly file version is used to display a file version in Windows and has no effect on runtime behavior. Setting this version is optional. It's visible in the File Properties dialog in Windows Explorer: ```xml 11.0.2.21924 diff --git a/docs/standard/linq/statically-compiled-queries.md b/docs/standard/linq/statically-compiled-queries.md index 2bdb3f7740efc..094192accd170 100644 --- a/docs/standard/linq/statically-compiled-queries.md +++ b/docs/standard/linq/statically-compiled-queries.md @@ -9,7 +9,7 @@ ms.assetid: 3bf558fe-0705-479d-86d4-00188f5fcf9c --- # Statically compiled queries (LINQ to XML) -One of the most important performance advantages of LINQ to XML, as compared to , is that queries in LINQ to XML are statically compiled, whereas XPath queries must be interpreted at run time. This feature is built into LINQ to XML, so you don't have to perform extra steps to take advantage of it, but it's helpful to understand the distinction when choosing between the two technologies. This article explains the difference. +One of the most important performance advantages of LINQ to XML, as compared to , is that queries in LINQ to XML are statically compiled, whereas XPath queries must be interpreted at runtime. This feature is built into LINQ to XML, so you don't have to perform extra steps to take advantage of it, but it's helpful to understand the distinction when choosing between the two technologies. This article explains the difference. ## Statically compiled queries vs. XPath diff --git a/docs/standard/managed-execution-process.md b/docs/standard/managed-execution-process.md index 635cc914c3291..2805b54af915c 100644 --- a/docs/standard/managed-execution-process.md +++ b/docs/standard/managed-execution-process.md @@ -41,13 +41,13 @@ The managed execution process includes the following steps, which are discussed ### Compilation by the JIT compiler - JIT compilation converts CIL to native code on demand at application run time, when the contents of an assembly are loaded and executed. Because the common language runtime supplies a JIT compiler for each supported CPU architecture, developers can build a set of CIL assemblies that can be JIT-compiled and run on different computers with different machine architectures. However, if your managed code calls platform-specific native APIs or a platform-specific class library, it will run only on that operating system. + JIT compilation converts CIL to native code on demand at application runtime, when the contents of an assembly are loaded and executed. Because the common language runtime supplies a JIT compiler for each supported CPU architecture, developers can build a set of CIL assemblies that can be JIT-compiled and run on different computers with different machine architectures. However, if your managed code calls platform-specific native APIs or a platform-specific class library, it will run only on that operating system. JIT compilation takes into account the possibility that some code might never be called during execution. Instead of using time and memory to convert all the CIL in a PE file to native code, it converts the CIL as needed during execution and stores the resulting native code in memory so that it is accessible for subsequent calls in the context of that process. The loader creates and attaches a stub to each method in a type when the type is loaded and initialized. When a method is called for the first time, the stub passes control to the JIT compiler, which converts the CIL for that method into native code and modifies the stub to point directly to the generated native code. Therefore, subsequent calls to the JIT-compiled method go directly to the native code. ### Install-time code generation using NGen.exe - Because the JIT compiler converts an assembly's CIL to native code when individual methods defined in that assembly are called, it affects performance adversely at run time. In most cases, that diminished performance is acceptable. More importantly, the code generated by the JIT compiler is bound to the process that triggered the compilation. It cannot be shared across multiple processes. To allow the generated code to be shared across multiple invocations of an application or across multiple processes that share a set of assemblies, the common language runtime supports an ahead-of-time compilation mode. This ahead-of-time compilation mode uses the [Ngen.exe (Native Image Generator)](../framework/tools/ngen-exe-native-image-generator.md) to convert CIL assemblies to native code much like the JIT compiler does. However, the operation of Ngen.exe differs from that of the JIT compiler in three ways: + Because the JIT compiler converts an assembly's CIL to native code when individual methods defined in that assembly are called, it affects performance adversely at runtime. In most cases, that diminished performance is acceptable. More importantly, the code generated by the JIT compiler is bound to the process that triggered the compilation. It cannot be shared across multiple processes. To allow the generated code to be shared across multiple invocations of an application or across multiple processes that share a set of assemblies, the common language runtime supports an ahead-of-time compilation mode. This ahead-of-time compilation mode uses the [Ngen.exe (Native Image Generator)](../framework/tools/ngen-exe-native-image-generator.md) to convert CIL assemblies to native code much like the JIT compiler does. However, the operation of Ngen.exe differs from that of the JIT compiler in three ways: - It performs the conversion from CIL to native code before running the application instead of while the application is running. - It compiles an entire assembly at a time, instead of one method at a time. diff --git a/docs/standard/metadata-and-self-describing-components.md b/docs/standard/metadata-and-self-describing-components.md index d6df8be656e8e..f459ce9faeff4 100644 --- a/docs/standard/metadata-and-self-describing-components.md +++ b/docs/standard/metadata-and-self-describing-components.md @@ -58,7 +58,7 @@ Metadata is the key to a simpler programming model, and eliminates the need for - Attributes. - .NET lets you declare specific kinds of metadata, called attributes, in your compiled file. Attributes can be found throughout .NET and are used to control in more detail how your program behaves at run time. Additionally, you can emit your own custom metadata into .NET files through user-defined custom attributes. For more information, see [Attributes](attributes/index.md). + .NET lets you declare specific kinds of metadata, called attributes, in your compiled file. Attributes can be found throughout .NET and are used to control in more detail how your program behaves at runtime. Additionally, you can emit your own custom metadata into .NET files through user-defined custom attributes. For more information, see [Attributes](attributes/index.md). ## Metadata and the PE File Structure @@ -92,7 +92,7 @@ When a program is compiled for the common language runtime, it is converted to a ## Run-Time Use of Metadata -To better understand metadata and its role in the common language runtime, it might be helpful to construct a simple program and illustrate how metadata affects its run-time life. The following code example shows two methods inside a class called `MyApp`. The `Main` method is the program entry point, while the `Add` method simply returns the sum of two integer arguments. +To better understand metadata and its role in the common language runtime, it might be helpful to construct a simple program and illustrate how metadata affects its runtime life. The following code example shows two methods inside a class called `MyApp`. The `Main` method is the program entry point, while the `Add` method simply returns the sum of two integer arguments. ```vb Public Class MyApp diff --git a/docs/standard/native-interop/com-callable-wrapper.md b/docs/standard/native-interop/com-callable-wrapper.md index 50453b09e6776..a3037bfb10243 100644 --- a/docs/standard/native-interop/com-callable-wrapper.md +++ b/docs/standard/native-interop/com-callable-wrapper.md @@ -170,7 +170,7 @@ public class LoanApp } ``` -To get the DispId of an interface member at run time, COM clients can call **IDispatch.GetIdsOfNames**. To invoke a method on the interface, pass the returned DispId as an argument to **IDispatch.Invoke**. +To get the DispId of an interface member at runtime, COM clients can call **IDispatch.GetIdsOfNames**. To invoke a method on the interface, pass the returned DispId as an argument to **IDispatch.Invoke**. ### Restrict using the dual interface option for the class interface. diff --git a/docs/standard/native-interop/comwrappers-source-generation.md b/docs/standard/native-interop/comwrappers-source-generation.md index 7c874770f23c3..cd0495a0e2694 100644 --- a/docs/standard/native-interop/comwrappers-source-generation.md +++ b/docs/standard/native-interop/comwrappers-source-generation.md @@ -8,9 +8,9 @@ ms.date: 08/25/2023 .NET 8 introduces a source generator that creates an implementation of the [ComWrappers](./com-wrappers.md) API for you. The generator recognizes the . -The .NET runtime's built-in (not source-generated), Windows-only, COM interop system generates an IL stub—a stream of IL instructions that's JIT-ed—at run time to facilitate the transition from managed code to COM, and vice-versa. Since this IL stub is generated at run time, it's incompatible with [NativeAOT](../../core/deploying/native-aot/index.md) and [IL trimming](../../core/deploying/trimming/trim-self-contained.md). Stub generation at run time can also make diagnosing marshalling issues difficult. +The .NET runtime's built-in (not source-generated), Windows-only, COM interop system generates an IL stub—a stream of IL instructions that's JIT-ed—at runtime to facilitate the transition from managed code to COM, and vice-versa. Since this IL stub is generated at runtime, it's incompatible with [NativeAOT](../../core/deploying/native-aot/index.md) and [IL trimming](../../core/deploying/trimming/trim-self-contained.md). Stub generation at runtime can also make diagnosing marshalling issues difficult. -Built-in interop uses attributes such as `ComImport` or `DllImport`, which rely on code generation at run time. The following code shows an example of this: +Built-in interop uses attributes such as `ComImport` or `DllImport`, which rely on code generation at runtime. The following code shows an example of this: ```csharp [ComImport] diff --git a/docs/standard/native-interop/native-library-loading.md b/docs/standard/native-interop/native-library-loading.md index 7a660f107da5d..b6b55ce512b72 100644 --- a/docs/standard/native-interop/native-library-loading.md +++ b/docs/standard/native-interop/native-library-loading.md @@ -54,7 +54,7 @@ In this case, the library name variations are tried in the following order: ## Custom import resolver -In more complex scenarios, you can use to resolve DLL imports at run time. In the following example, `nativedep` is resolved to `nativedep_avx2` if the CPU supports it. +In more complex scenarios, you can use to resolve DLL imports at runtime. In the following example, `nativedep` is resolved to `nativedep_avx2` if the CPU supports it. > [!TIP] > This functionality is only available in .NET Core 3.1 and .NET 5+. diff --git a/docs/standard/native-interop/pinvoke-source-generation.md b/docs/standard/native-interop/pinvoke-source-generation.md index 35c051e5d2596..61d8fc1210588 100644 --- a/docs/standard/native-interop/pinvoke-source-generation.md +++ b/docs/standard/native-interop/pinvoke-source-generation.md @@ -8,7 +8,7 @@ ms.date: 07/25/2022 .NET 7 introduces a [source generator](../../csharp/roslyn-sdk/index.md#source-generators) for P/Invokes that recognizes the in C# code. -When it's not using source generation, the built-in interop system in the .NET runtime generates an IL stub—a stream of IL instructions that is JIT-ed—at run time to facilitate the transition from managed to unmanaged. The following code shows defining and then calling a P/Invoke that uses this mechanism: +When it's not using source generation, the built-in interop system in the .NET runtime generates an IL stub—a stream of IL instructions that is JIT-ed—at runtime to facilitate the transition from managed to unmanaged. The following code shows defining and then calling a P/Invoke that uses this mechanism: ```csharp [DllImport( @@ -20,9 +20,9 @@ internal static extern string ToLower(string str); // string lower = ToLower("StringToConvert"); ``` -The IL stub handles [marshalling](type-marshalling.md) of parameters and return values and calling the unmanaged code while respecting settings on that affect how the unmanaged code should be invoked (for example, ). Since this IL stub is generated at run time, it isn't available for ahead-of-time (AOT) compiler or IL trimming scenarios. Generation of the IL represents an important cost to consider for marshalling. This cost can be measured in terms of application performance and support for potential target platforms that may not permit dynamic code generation. The [Native AOT](../../core/deploying/native-aot/index.md) application model addresses issues with dynamic code generation by precompiling all code ahead of time directly into native code. Using `DllImport` isn't an option for platforms that require full Native AOT scenarios and therefore using other approaches (for example, source generation) is more appropriate. Debugging the marshalling logic in `DllImport` scenarios is also a non-trivial exercise. +The IL stub handles [marshalling](type-marshalling.md) of parameters and return values and calling the unmanaged code while respecting settings on that affect how the unmanaged code should be invoked (for example, ). Since this IL stub is generated at runtime, it isn't available for ahead-of-time (AOT) compiler or IL trimming scenarios. Generation of the IL represents an important cost to consider for marshalling. This cost can be measured in terms of application performance and support for potential target platforms that may not permit dynamic code generation. The [Native AOT](../../core/deploying/native-aot/index.md) application model addresses issues with dynamic code generation by precompiling all code ahead of time directly into native code. Using `DllImport` isn't an option for platforms that require full Native AOT scenarios and therefore using other approaches (for example, source generation) is more appropriate. Debugging the marshalling logic in `DllImport` scenarios is also a non-trivial exercise. -The P/Invoke source generator, included with the .NET 7 SDK and enabled by default, looks for on a `static` and `partial` method to trigger compile-time source generation of marshalling code, removing the need for the generation of an IL stub at run time and allowing the P/Invoke to be inlined. [Analyzers](../../fundamentals/syslib-diagnostics/syslib1050-1069.md) and code fixers are also included to help with migration from the built-in system to the source generator and with usage in general. +The P/Invoke source generator, included with the .NET 7 SDK and enabled by default, looks for on a `static` and `partial` method to trigger compile-time source generation of marshalling code, removing the need for the generation of an IL stub at runtime and allowing the P/Invoke to be inlined. [Analyzers](../../fundamentals/syslib-diagnostics/syslib1050-1069.md) and code fixers are also included to help with migration from the built-in system to the source generator and with usage in general. ## Basic usage diff --git a/docs/standard/native-interop/qualify-net-types-for-interoperation.md b/docs/standard/native-interop/qualify-net-types-for-interoperation.md index bb134ed242dcb..d9dcd4cb35fc4 100644 --- a/docs/standard/native-interop/qualify-net-types-for-interoperation.md +++ b/docs/standard/native-interop/qualify-net-types-for-interoperation.md @@ -205,7 +205,7 @@ Virtual function table layouts: | 2 | `IUnknown::Release` | | 3 | `IComInterface2::Method3` | -As these virtual function tables differ from the C++ example, this will lead to serious problems at run time. The correct definition of these interfaces in .NET with is as follows: +As these virtual function tables differ from the C++ example, this will lead to serious problems at runtime. The correct definition of these interfaces in .NET with is as follows: ```csharp [ComImport] diff --git a/docs/standard/native-interop/tutorial-comwrappers.md b/docs/standard/native-interop/tutorial-comwrappers.md index dacfadd94cdc1..913ef9cbb8c32 100644 --- a/docs/standard/native-interop/tutorial-comwrappers.md +++ b/docs/standard/native-interop/tutorial-comwrappers.md @@ -248,7 +248,7 @@ return new DemoNativeStaticWrapper() #### Dynamic Native Object Wrapper -Dynamic wrappers are more flexible because they provide a way for types to be queried at run time instead of statically. To provide this support, you'll use [`IDynamicInterfaceCastable`][api_idynamicinterfacecastable]. Observe that `DemoNativeDynamicWrapper` only implements this interface. The functionality that the interface provides is a chance to determine what type is supported at run time. The source for this tutorial does a static check during creation but that is simply for code sharing since the check could be deferred until a call is made to `DemoNativeDynamicWrapper.IsInterfaceImplemented()`. +Dynamic wrappers are more flexible because they provide a way for types to be queried at runtime instead of statically. To provide this support, you'll use [`IDynamicInterfaceCastable`][api_idynamicinterfacecastable]. Observe that `DemoNativeDynamicWrapper` only implements this interface. The functionality that the interface provides is a chance to determine what type is supported at runtime. The source for this tutorial does a static check during creation but that is simply for code sharing since the check could be deferred until a call is made to `DemoNativeDynamicWrapper.IsInterfaceImplemented()`. ```csharp // See referenced sample for implementation. diff --git a/docs/standard/native-interop/tutorial-custom-marshaller.md b/docs/standard/native-interop/tutorial-custom-marshaller.md index 8b19bc32d6dde..c6f70f5c96cb0 100644 --- a/docs/standard/native-interop/tutorial-custom-marshaller.md +++ b/docs/standard/native-interop/tutorial-custom-marshaller.md @@ -19,7 +19,7 @@ All source code used in this tutorial is available in the [dotnet/samples reposi ## Overview of the `LibraryImport` source generator -The [`System.Runtime.InteropServices.LibraryImportAttribute`][api_libraryimportattribute] type is the user entry point for a source generator introduced in .NET 7. This source generator is designed to generate all marshalling code at compile time instead of at run time. Entry points have historically been specified using `DllImport`, but that approach comes with costs that may not always be acceptable—for more information, see [P/Invoke source generation][pinvoke_source_generation]. The `LibraryImport` source generator can generate all marshalling code and remove the run-time generation requirement intrinsic to `DllImport`. +The [`System.Runtime.InteropServices.LibraryImportAttribute`][api_libraryimportattribute] type is the user entry point for a source generator introduced in .NET 7. This source generator is designed to generate all marshalling code at compile time instead of at runtime. Entry points have historically been specified using `DllImport`, but that approach comes with costs that may not always be acceptable—for more information, see [P/Invoke source generation][pinvoke_source_generation]. The `LibraryImport` source generator can generate all marshalling code and remove the runtime generation requirement intrinsic to `DllImport`. To express the details needed to generated marshalling code both for the runtime and for users to customize for their own types, several types are needed. The following types are used throughout this tutorial: diff --git a/docs/standard/net-standard.md b/docs/standard/net-standard.md index 84ae857031196..a0f583af41837 100644 --- a/docs/standard/net-standard.md +++ b/docs/standard/net-standard.md @@ -132,9 +132,9 @@ Here are some problems with .NET Standard that help explain why .NET 5 and later **Solution in .NET 5+:** There's no separation between a .NET 5+ API specification and its implementation. The result is a simplified TFM scheme. There's one TFM prefix for all workloads: `net10.0` is used for libraries, console apps, and web apps. The only variation is a [suffix that specifies platform-specific APIs](frameworks.md#os-specific-tfms) for a particular platform, such as `net10.0-windows`. Thanks to this TFM naming convention, you can easily tell whether a given app can use a given library. No version number equivalents table, like the one for .NET Standard, is needed. -- Platform-unsupported exceptions at run time +- Platform-unsupported exceptions at runtime - .NET Standard exposes platform-specific APIs. Your code might compile without errors and appear to be portable to any platform even if it isn't portable. When it runs on a platform that doesn't have an implementation for a given API, you get run-time errors. + .NET Standard exposes platform-specific APIs. Your code might compile without errors and appear to be portable to any platform even if it isn't portable. When it runs on a platform that doesn't have an implementation for a given API, you get runtime errors. **Solution in .NET 5+:** The .NET 5+ SDKs include code analyzers that are enabled by default. The platform compatibility analyzer detects unintentional use of APIs that aren't supported on the platforms you intend to run on. For more information, see [Platform compatibility analyzer](analyzers/platform-compat-analyzer.md). diff --git a/docs/standard/parallel-programming/chaining-tasks-by-using-continuation-tasks.md b/docs/standard/parallel-programming/chaining-tasks-by-using-continuation-tasks.md index fcb61088422d2..ac1bc74d3d144 100644 --- a/docs/standard/parallel-programming/chaining-tasks-by-using-continuation-tasks.md +++ b/docs/standard/parallel-programming/chaining-tasks-by-using-continuation-tasks.md @@ -56,7 +56,7 @@ The following example calls the overload that takes a enumeration value to specify the conditions under which the continuation starts. For example, you can specify that the continuation is to run only if the antecedent completes successfully, or only if it completes in a faulted state. If the condition isn't true when the antecedent is ready to invoke the continuation, the continuation transitions directly to the state and can't be started later. -Many multi-task continuation methods, such as overloads of the method, also include a parameter. However, only a subset of all enumeration members is valid. You can specify values that have counterparts in the enumeration, such as , , and . If you specify any of the `NotOn` or `OnlyOn` options with a multi-task continuation, an exception will be thrown at run time. +Many multi-task continuation methods, such as overloads of the method, also include a parameter. However, only a subset of all enumeration members is valid. You can specify values that have counterparts in the enumeration, such as , , and . If you specify any of the `NotOn` or `OnlyOn` options with a multi-task continuation, an exception will be thrown at runtime. For more information on task continuation options, see the article. diff --git a/docs/standard/parallel-programming/introduction-to-plinq.md b/docs/standard/parallel-programming/introduction-to-plinq.md index 9db7d2d964ded..9e61731ab3a38 100644 --- a/docs/standard/parallel-programming/introduction-to-plinq.md +++ b/docs/standard/parallel-programming/introduction-to-plinq.md @@ -59,7 +59,7 @@ The extension method binds t ## Execution Modes -By default, PLINQ is conservative. At run time, the PLINQ infrastructure analyzes the overall structure of the query. If the query is likely to yield speedups by parallelization, PLINQ partitions the source sequence into tasks that can be run concurrently. If it is not safe to parallelize a query, PLINQ just runs the query sequentially. If PLINQ has a choice between a potentially expensive parallel algorithm or an inexpensive sequential algorithm, it chooses the sequential algorithm by default. You can use the method and the enumeration to instruct PLINQ to select the parallel algorithm. This is useful when you know by testing and measurement that a particular query executes faster in parallel. For more information, see [How to: Specify the Execution Mode in PLINQ](how-to-specify-the-execution-mode-in-plinq.md). +By default, PLINQ is conservative. At runtime, the PLINQ infrastructure analyzes the overall structure of the query. If the query is likely to yield speedups by parallelization, PLINQ partitions the source sequence into tasks that can be run concurrently. If it is not safe to parallelize a query, PLINQ just runs the query sequentially. If PLINQ has a choice between a potentially expensive parallel algorithm or an inexpensive sequential algorithm, it chooses the sequential algorithm by default. You can use the method and the enumeration to instruct PLINQ to select the parallel algorithm. This is useful when you know by testing and measurement that a particular query executes faster in parallel. For more information, see [How to: Specify the Execution Mode in PLINQ](how-to-specify-the-execution-mode-in-plinq.md). ## Degree of Parallelism @@ -123,7 +123,7 @@ In some cases, you can improve query performance by writing a custom partitioner [!code-csharp[PLINQ#2](../../../samples/snippets/csharp/VS_Snippets_Misc/plinq/cs/plinq2_cs.cs#2)] [!code-vb[PLINQ#2](../../../samples/snippets/visualbasic/VS_Snippets_Misc/plinq/vb/plinq3.vb#2)] -PLINQ supports a fixed number of partitions (although data may be dynamically reassigned to those partitions during run time for load balancing.). and support only dynamic partitioning, which means that the number of partitions changes at run time. For more information, see [Custom Partitioners for PLINQ and TPL](custom-partitioners-for-plinq-and-tpl.md). +PLINQ supports a fixed number of partitions (although data may be dynamically reassigned to those partitions during runtime for load balancing.). and support only dynamic partitioning, which means that the number of partitions changes at runtime. For more information, see [Custom Partitioners for PLINQ and TPL](custom-partitioners-for-plinq-and-tpl.md). ## Measuring PLINQ Performance diff --git a/docs/standard/security/key-security-concepts.md b/docs/standard/security/key-security-concepts.md index f0ea2e7660378..803251e93cc83 100644 --- a/docs/standard/security/key-security-concepts.md +++ b/docs/standard/security/key-security-concepts.md @@ -52,7 +52,7 @@ A variety of authentication mechanisms are used today, many of which can be used The following example requires that the active principal be an administrator. The `name` parameter is `null`, which allows any user who is an administrator to pass the demand. > [!NOTE] -> In Windows Vista, User Account Control (UAC) determines the privileges of a user. If you are a member of the Built-in Administrators group, you are assigned two run-time access tokens: a standard user access token and an administrator access token. By default, you are in the standard user role. To execute the code that requires you to be an administrator, you must first elevate your privileges from standard user to administrator. You can do this when you start an application by right-clicking the application icon and indicating that you want to run as an administrator. +> In Windows Vista, User Account Control (UAC) determines the privileges of a user. If you are a member of the Built-in Administrators group, you are assigned two runtime access tokens: a standard user access token and an administrator access token. By default, you are in the standard user role. To execute the code that requires you to be an administrator, you must first elevate your privileges from standard user to administrator. You can do this when you start an application by right-clicking the application icon and indicating that you want to run as an administrator. [!code-csharp[Classic PrincipalPermission Example#1](../../../samples/snippets/csharp/VS_Snippets_CLR_Classic/classic PrincipalPermission Example/CS/source.cs#1)] [!code-vb[Classic PrincipalPermission Example#1](../../../samples/snippets/visualbasic/VS_Snippets_CLR_Classic/classic PrincipalPermission Example/VB/source.vb#1)] diff --git a/docs/standard/serialization/binaryformatter-migration-guide/winforms-applications.md b/docs/standard/serialization/binaryformatter-migration-guide/winforms-applications.md index bb984836b7621..b48e5dc888880 100644 --- a/docs/standard/serialization/binaryformatter-migration-guide/winforms-applications.md +++ b/docs/standard/serialization/binaryformatter-migration-guide/winforms-applications.md @@ -76,7 +76,7 @@ Types that had been previously serialized into resource files via [BinaryFormatt ##### Generating resource files via MSBuild -When you generate resource files via MSBuild, you might encounter an `MSB3825` error. This error specifies that your binary-formatted resources might be deserialized using [BinaryFormatter] during run time. The warning is being removed from builds targeting .NET 9 and later, however the removal is not yet complete in all releases of .NET 9. The warning should be only of concern when targeting .NET 8 and lower. As stated earlier, these resources will not deserialize using [BinaryFormatter] during run time in .NET 9 and later versions. You can turn the warning off by setting the property `GenerateResourceWarnOnBinaryFormatterUse` to `false`. In rare cases that deserialization cannot occur without [BinaryFormatter], it can be added back with an unsupported compatibility package. For more information, see [BinaryFormatter migration guide: Compatibility package](compatibility-package.md). Note that an additional step of setting the `System.Resources.Extensions.UseBinaryFormatter` app context switch to `true` is required to use [BinaryFormatter] for resources. +When you generate resource files via MSBuild, you might encounter an `MSB3825` error. This error specifies that your binary-formatted resources might be deserialized using [BinaryFormatter] during runtime. The warning is being removed from builds targeting .NET 9 and later, however the removal is not yet complete in all releases of .NET 9. The warning should be only of concern when targeting .NET 8 and lower. As stated earlier, these resources will not deserialize using [BinaryFormatter] during runtime in .NET 9 and later versions. You can turn the warning off by setting the property `GenerateResourceWarnOnBinaryFormatterUse` to `false`. In rare cases that deserialization cannot occur without [BinaryFormatter], it can be added back with an unsupported compatibility package. For more information, see [BinaryFormatter migration guide: Compatibility package](compatibility-package.md). Note that an additional step of setting the `System.Resources.Extensions.UseBinaryFormatter` app context switch to `true` is required to use [BinaryFormatter] for resources. ## Migrate away from BinaryFormatter diff --git a/docs/standard/serialization/controlling-xml-serialization-using-attributes.md b/docs/standard/serialization/controlling-xml-serialization-using-attributes.md index ccbb877b0a6d6..9bd0f321ebeb3 100644 --- a/docs/standard/serialization/controlling-xml-serialization-using-attributes.md +++ b/docs/standard/serialization/controlling-xml-serialization-using-attributes.md @@ -3,10 +3,10 @@ title: "Controlling XML Serialization Using Attributes" description: Attributes can be used to control the XML serialization of an object or to create an alternate XML stream from the same set of classes. ms.date: "08/05/2022" ms.custom: devdivchpfy22 -dev_langs: +dev_langs: - "csharp" - "vb" -helpviewer_keywords: +helpviewer_keywords: - "classes, serializing" - "XML serialization, examples" - "derived classes, serializing" @@ -159,7 +159,7 @@ The resulting XML might resemble the following code: ## Serializing Derived Classes -Another use of the is to allow the serialization of derived classes. For example, another class named `Manager` that derives from `Employee` can be added to the previous example. If you don't apply the , the code will fail at run time because the derived class type won't be recognized. To remedy this outcome, apply the attribute twice, each time setting the property for each acceptable type (base and derived). +Another use of the is to allow the serialization of derived classes. For example, another class named `Manager` that derives from `Employee` can be added to the previous example. If you don't apply the , the code will fail at runtime because the derived class type won't be recognized. To remedy this outcome, apply the attribute twice, each time setting the property for each acceptable type (base and derived). ```vb Public Class Group diff --git a/docs/standard/serialization/system-text-json/converters-how-to.md b/docs/standard/serialization/system-text-json/converters-how-to.md index bc246901b9903..be4207133a567 100644 --- a/docs/standard/serialization/system-text-json/converters-how-to.md +++ b/docs/standard/serialization/system-text-json/converters-how-to.md @@ -47,7 +47,7 @@ Some examples of types that can be handled by the basic pattern include: * * -The basic pattern creates a class that can handle one type. The factory pattern creates a class that determines, at run time, which specific type is required and dynamically creates the appropriate converter. +The basic pattern creates a class that can handle one type. The factory pattern creates a class that determines, at runtime, which specific type is required and dynamically creates the appropriate converter. ## Sample basic converter @@ -57,7 +57,7 @@ The following sample is a converter that overrides default serialization for an ## Sample factory pattern converter -The following code shows a custom converter that works with `Dictionary`. The code follows the factory pattern because the first generic type parameter is `Enum` and the second is open. The `CanConvert` method returns `true` only for a `Dictionary` with two generic parameters, the first of which is an `Enum` type. The inner converter gets an existing converter to handle whichever type is provided at run time for `TValue`. +The following code shows a custom converter that works with `Dictionary`. The code follows the factory pattern because the first generic type parameter is `Enum` and the second is open. The `CanConvert` method returns `true` only for a `Dictionary` with two generic parameters, the first of which is an `Enum` type. The inner converter gets an existing converter to handle whichever type is provided at runtime for `TValue`. :::code language="csharp" source="snippets/how-to/csharp/DictionaryTKeyEnumTValueConverter.cs"::: @@ -78,7 +78,7 @@ The following steps explain how to create a converter by following the factory p * Create a class that derives from . * Override the `CanConvert` method to return `true` when the type to convert is one that the converter can handle. For example, if the converter is for `List`, it might only handle `List`, `List`, and `List`. -* Override the `CreateConverter` method to return an instance of a converter class that will handle the type-to-convert that is provided at run time. +* Override the `CreateConverter` method to return an instance of a converter class that will handle the type-to-convert that is provided at runtime. * Create the converter class that the `CreateConverter` method instantiates. The factory pattern is required for open generics because the code to convert an object to and from a string isn't the same for all types. A converter for an open generic type (`List`, for example) has to create a converter for a closed generic type (`List`, for example) behind the scenes. Code must be written to handle each closed-generic type that the converter can handle. @@ -226,7 +226,7 @@ For scenarios that require type inference, the following code shows a custom con :::code language="csharp" source="snippets/how-to-contd/csharp/CustomConverterInferredTypesToObject.cs"::: -The example shows the converter code and a `WeatherForecast` class with `object` properties. The `Main` method deserializes a JSON string into a `WeatherForecast` instance, first without using the converter, and then using the converter. The console output shows that without the converter, the run-time type for the `Date` property is `JsonElement`; with the converter, the run-time type is `DateTime`. +The example shows the converter code and a `WeatherForecast` class with `object` properties. The `Main` method deserializes a JSON string into a `WeatherForecast` instance, first without using the converter, and then using the converter. The console output shows that without the converter, the runtime type for the `Date` property is `JsonElement`; with the converter, the runtime type is `DateTime`. The [unit tests folder](https://github.com/dotnet/runtime/tree/main/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests) in the `System.Text.Json.Serialization` namespace has more examples of custom converters that handle deserialization to `object` properties. @@ -234,7 +234,7 @@ The [unit tests folder](https://github.com/dotnet/runtime/tree/main/src/librarie .NET 7 provides support for both [polymorphic serialization and deserialization](polymorphism.md). However, in previous .NET versions, there was limited polymorphic serialization support and no support for deserialization. If you're using .NET 6 or an earlier version, deserialization requires a custom converter. -Suppose, for example, you have a `Person` abstract base class, with `Employee` and `Customer` derived classes. Polymorphic deserialization means that at design time you can specify `Person` as the deserialization target, and `Customer` and `Employee` objects in the JSON are correctly deserialized at run time. During deserialization, you have to find clues that identify the required type in the JSON. The kinds of clues available vary with each scenario. For example, a discriminator property might be available or you might have to rely on the presence or absence of a particular property. The current release of `System.Text.Json` doesn't provide attributes to specify how to handle polymorphic deserialization scenarios, so custom converters are required. +Suppose, for example, you have a `Person` abstract base class, with `Employee` and `Customer` derived classes. Polymorphic deserialization means that at design time you can specify `Person` as the deserialization target, and `Customer` and `Employee` objects in the JSON are correctly deserialized at runtime. During deserialization, you have to find clues that identify the required type in the JSON. The kinds of clues available vary with each scenario. For example, a discriminator property might be available or you might have to rely on the presence or absence of a particular property. The current release of `System.Text.Json` doesn't provide attributes to specify how to handle polymorphic deserialization scenarios, so custom converters are required. The following code shows a base class, two derived classes, and a custom converter for them. The converter uses a discriminator property to do polymorphic deserialization. The type discriminator isn't in the class definitions but is created during serialization and is read during deserialization. diff --git a/docs/standard/serialization/system-text-json/custom-contracts.md b/docs/standard/serialization/system-text-json/custom-contracts.md index 764c2d6da2042..8c2bec09ac923 100644 --- a/docs/standard/serialization/system-text-json/custom-contracts.md +++ b/docs/standard/serialization/system-text-json/custom-contracts.md @@ -5,7 +5,7 @@ ms.date: 06/15/2023 --- # Customize a JSON contract -The library constructs a JSON *contract* for each .NET type, which defines how the type should be serialized and deserialized. The contract is derived from the type's shape, which includes characteristics such as its properties and fields and whether it implements the or interface. Types are mapped to contracts either at run time using reflection or at compile time using the source generator. +The library constructs a JSON *contract* for each .NET type, which defines how the type should be serialized and deserialized. The contract is derived from the type's shape, which includes characteristics such as its properties and fields and whether it implements the or interface. Types are mapped to contracts either at runtime using reflection or at compile time using the source generator. Starting in .NET 7, you can customize these JSON contracts to provide more control over how types are converted into JSON and vice versa. The following list shows just some examples of the types of customizations you can make to serialization and deserialization: diff --git a/docs/standard/serialization/system-text-json/migrate-from-newtonsoft.md b/docs/standard/serialization/system-text-json/migrate-from-newtonsoft.md index 88cfbfa949b82..0d818359eb9e1 100644 --- a/docs/standard/serialization/system-text-json/migrate-from-newtonsoft.md +++ b/docs/standard/serialization/system-text-json/migrate-from-newtonsoft.md @@ -130,7 +130,7 @@ The registration precedence for * collection * Attribute on type -The difference here is that a custom converter in the `Converters` collection overrides an attribute at the type level. The intention behind this order of precedence is to make run-time changes override design-time choices. There's no way to change the precedence. +The difference here is that a custom converter in the `Converters` collection overrides an attribute at the type level. The intention behind this order of precedence is to make runtime changes override design-time choices. There's no way to change the precedence. For more information about custom converter registration, see [Register a custom converter](converters-how-to.md#register-a-custom-converter). diff --git a/docs/standard/serialization/system-text-json/nullable-annotations.md b/docs/standard/serialization/system-text-json/nullable-annotations.md index 06193824a24c8..0183f53c5f483 100644 --- a/docs/standard/serialization/system-text-json/nullable-annotations.md +++ b/docs/standard/serialization/system-text-json/nullable-annotations.md @@ -28,7 +28,7 @@ Similarly, ` and `List` types are indistinguishable. diff --git a/docs/standard/serialization/system-text-json/overview.md b/docs/standard/serialization/system-text-json/overview.md index d722e860e415d..f43130ffa1e74 100644 --- a/docs/standard/serialization/system-text-json/overview.md +++ b/docs/standard/serialization/system-text-json/overview.md @@ -48,7 +48,7 @@ For framework versions earlier than .NET Core 3.0, install the [System.Text.Json ## Reflection vs. source generation -By default, `System.Text.Json` gathers the metadata it needs to access properties of objects for serialization and deserialization *at run time* using [reflection](../../../csharp/advanced-topics/reflection-and-attributes/index.md). As an alternative, `System.Text.Json` can use the C# [source generation](../../../csharp/roslyn-sdk/index.md#source-generators) feature to improve performance, reduce private memory usage, and facilitate [assembly trimming](../../../core/deploying/trimming/trim-self-contained.md), which reduces app size. +By default, `System.Text.Json` gathers the metadata it needs to access properties of objects for serialization and deserialization *at runtime* using [reflection](../../../csharp/advanced-topics/reflection-and-attributes/index.md). As an alternative, `System.Text.Json` can use the C# [source generation](../../../csharp/roslyn-sdk/index.md#source-generators) feature to improve performance, reduce private memory usage, and facilitate [assembly trimming](../../../core/deploying/trimming/trim-self-contained.md), which reduces app size. For more information, see [Reflection versus source generation](reflection-vs-source-generation.md). diff --git a/docs/standard/serialization/system-text-json/polymorphism.md b/docs/standard/serialization/system-text-json/polymorphism.md index a0b2cf0b257b7..bbec94bd7bb44 100644 --- a/docs/standard/serialization/system-text-json/polymorphism.md +++ b/docs/standard/serialization/system-text-json/polymorphism.md @@ -51,7 +51,7 @@ In this scenario, the `City` property is serialized because the `weatherForecast } ``` -While round-tripping of the payload as `WeatherForecastBase` is supported, it won't materialize as a run-time type of `WeatherForecastWithCity`. Instead, it will materialize as a run-time type of `WeatherForecastBase`: +While round-tripping of the payload as `WeatherForecastBase` is supported, it won't materialize as a runtime type of `WeatherForecastWithCity`. Instead, it will materialize as a runtime type of `WeatherForecastBase`: ```csharp WeatherForecastBase value = JsonSerializer.Deserialize(""" @@ -416,7 +416,7 @@ Public NotInheritable Class FourDimensionalPoint End Class ``` -Since the configuration does not explicitly opt-in support for `FourDimensionalPoint`, attempting to serialize instances of `FourDimensionalPoint` as `BasePoint` will result in a run-time exception: +Since the configuration does not explicitly opt-in support for `FourDimensionalPoint`, attempting to serialize instances of `FourDimensionalPoint` as `BasePoint` will result in a runtime exception: ```csharp JsonSerializer.Serialize(new FourDimensionalPoint()); // throws NotSupportedException @@ -623,7 +623,7 @@ End Class ### Additional polymorphic serialization details -* Polymorphic serialization supports derived types that have been explicitly opted in via the . Undeclared types will result in a run-time exception. The behavior can be changed by configuring the property. +* Polymorphic serialization supports derived types that have been explicitly opted in via the . Undeclared types will result in a runtime exception. The behavior can be changed by configuring the property. * Polymorphic configuration specified in derived types is not inherited by polymorphic configuration in base types. The base type must be configured independently. * Polymorphic hierarchies are supported for both `interface` and `class` types. * Polymorphism using type discriminators is only supported for type hierarchies that use the default converters for objects, collections, and dictionary types. diff --git a/docs/standard/serialization/system-text-json/populate-properties.md b/docs/standard/serialization/system-text-json/populate-properties.md index 6944378dbf2ed..9d182a59852d2 100644 --- a/docs/standard/serialization/system-text-json/populate-properties.md +++ b/docs/standard/serialization/system-text-json/populate-properties.md @@ -40,7 +40,7 @@ Starting in .NET 8, you can change the deserialization behavior to modify (*popu - For a property that's an object with properties, its mutable properties are updated to the JSON values but the object reference itself doesn't change. - For a struct type property, the effective behavior is that for its mutable properties, any existing values are kept and new values from the JSON are added. However, unlike a reference property, the object itself isn't reused since it's a value type. Instead, a copy of the struct is modified and then reassigned to the property. For an example, see [Struct property example](#struct-property-example). - A struct property must have a setter; otherwise, an is thrown at run time. + A struct property must have a setter; otherwise, an is thrown at runtime. > [!NOTE] > The populate behavior currently doesn't work for types that have a parameterized constructor. For more information, see [dotnet/runtime issue 92877](https://github.com/dotnet/runtime/issues/92877). diff --git a/docs/standard/serialization/system-text-json/reflection-vs-source-generation.md b/docs/standard/serialization/system-text-json/reflection-vs-source-generation.md index a2906811adcac..db4212f2d0b1e 100644 --- a/docs/standard/serialization/system-text-json/reflection-vs-source-generation.md +++ b/docs/standard/serialization/system-text-json/reflection-vs-source-generation.md @@ -16,13 +16,13 @@ To serialize or deserialize a type, needs * How to access property getters and fields for serialization. * How to access a constructor, property setters, and fields for deserialization. * Information about which attributes have been used to customize serialization or deserialization. -* Run-time configuration from . +* Runtime configuration from . This information is referred to as *metadata*. ## Reflection -By default, collects metadata at run time by using [reflection](../../../csharp/advanced-topics/reflection-and-attributes/index.md). Whenever `JsonSerializer` has to serialize or deserialize a type for the first time, it collects and caches this metadata. The metadata collection process takes time and uses memory. +By default, collects metadata at runtime by using [reflection](../../../csharp/advanced-topics/reflection-and-attributes/index.md). Whenever `JsonSerializer` has to serialize or deserialize a type for the first time, it collects and caches this metadata. The metadata collection process takes time and uses memory. ## Source generation @@ -54,7 +54,7 @@ Choose reflection or source-generation modes based on the following benefits tha | Supports all available serialization customizations. | ✔️ | ❌ | ❌ | | Reduces start-up time. | ❌ | ✔️ | ✔️ | | Reduces private memory usage. | ❌ | ✔️ | ✔️ | -| Eliminates run-time reflection. | ❌ | ✔️ | ✔️ | +| Eliminates runtime reflection. | ❌ | ✔️ | ✔️ | | Facilitates trim-safe app size reduction. | ❌ | ✔️ | ✔️ | | Increases serialization throughput. | ❌ | ❌ | ✔️ | diff --git a/docs/standard/serialization/system-text-json/source-generation-modes.md b/docs/standard/serialization/system-text-json/source-generation-modes.md index 913b3780389a6..13e4fb5cc4c86 100644 --- a/docs/standard/serialization/system-text-json/source-generation-modes.md +++ b/docs/standard/serialization/system-text-json/source-generation-modes.md @@ -18,13 +18,13 @@ For information about how to use source generation modes, see [How to use source ## Metadata-based mode -You can use source generation to move the metadata collection process from run time to compile time. During compilation, the metadata is collected and source code files are generated. The generated source code files are automatically compiled as an integral part of the application. This technique eliminates run-time metadata collection, which improves performance of both serialization and deserialization. +You can use source generation to move the metadata collection process from runtime to compile time. During compilation, the metadata is collected and source code files are generated. The generated source code files are automatically compiled as an integral part of the application. This technique eliminates runtime metadata collection, which improves performance of both serialization and deserialization. The performance improvements provided by source generation can be substantial. For example, [test results](https://devblogs.microsoft.com/dotnet/try-the-new-system-text-json-source-generator/#how-source-generation-provides-benefits) have shown up to 40% or more startup time reduction, private memory reduction, throughput speed increase (in serialization optimization mode), and app size reduction. ### Known issues -Only `public` properties and fields are supported by default in either serialization mode (reflection or source-generation). However, reflection mode supports the use of `private` members, while source-generation mode doesn't. For example, if you apply the [JsonInclude attribute](xref:System.Text.Json.Serialization.JsonIncludeAttribute) to a `private` property or a property that has a `private` setter or getter, it will be serialized in reflection mode. Source-generation mode supports only `public` or `internal` members and `public` or `internal` accessors of `public` properties. If you set `[JsonInclude]` on `private` members or accessors and choose source-generation mode, a `NotSupportedException` will be thrown at run time. +Only `public` properties and fields are supported by default in either serialization mode (reflection or source-generation). However, reflection mode supports the use of `private` members, while source-generation mode doesn't. For example, if you apply the [JsonInclude attribute](xref:System.Text.Json.Serialization.JsonIncludeAttribute) to a `private` property or a property that has a `private` setter or getter, it will be serialized in reflection mode. Source-generation mode supports only `public` or `internal` members and `public` or `internal` accessors of `public` properties. If you set `[JsonInclude]` on `private` members or accessors and choose source-generation mode, a `NotSupportedException` will be thrown at runtime. For information about other known issues with source generation, see the [GitHub issues that are labeled "source-generator"](https://github.com/dotnet/runtime/issues?q=is%3Aopen+is%3Aissue+label%3Aarea-System.Text.Json+label%3Asource-generator) in the *dotnet/runtime* repository. diff --git a/docs/standard/serialization/system-text-json/source-generation.md b/docs/standard/serialization/system-text-json/source-generation.md index dc16d62c62dad..5110451dcffd7 100644 --- a/docs/standard/serialization/system-text-json/source-generation.md +++ b/docs/standard/serialization/system-text-json/source-generation.md @@ -45,7 +45,7 @@ The types of `WeatherForecast` members don't need to be explicitly specified wit :::code language="csharp" source="snippets/source-generation/csharp/ObjectProperties.cs" id="WF"::: -And you know that at run time it might have `boolean` and `int` objects: +And you know that at runtime it might have `boolean` and `int` objects: :::code language="csharp" source="snippets/source-generation/csharp/ObjectProperties.cs" id="WFInit"::: @@ -165,7 +165,7 @@ services.AddControllers().AddJsonOptions( ## Disable reflection defaults -Because System.Text.Json uses reflection by default, calling a basic serialization method can break Native AOT apps, which doesn't support all required reflection APIs. These breaks can be challenging to diagnose since they can be unpredictable, and apps are often debugged using the CoreCLR runtime, where reflection works. Instead, if you explicitly disable reflection-based serialization, breaks are easier to diagnose. Code that uses reflection-based serialization will cause an with a descriptive message to be thrown at run time. +Because System.Text.Json uses reflection by default, calling a basic serialization method can break Native AOT apps, which doesn't support all required reflection APIs. These breaks can be challenging to diagnose since they can be unpredictable, and apps are often debugged using the CoreCLR runtime, where reflection works. Instead, if you explicitly disable reflection-based serialization, breaks are easier to diagnose. Code that uses reflection-based serialization will cause an with a descriptive message to be thrown at runtime. To disable default reflection in your app, set the `JsonSerializerIsReflectionEnabledByDefault` MSBuild property to `false` in your project file: diff --git a/docs/standard/threading/managed-threading-best-practices.md b/docs/standard/threading/managed-threading-best-practices.md index 605e8f9927cbd..2484d2158f6b6 100644 --- a/docs/standard/threading/managed-threading-best-practices.md +++ b/docs/standard/threading/managed-threading-best-practices.md @@ -2,10 +2,10 @@ title: "Managed Threading Best Practices" description: Learn managed threading best practices in .NET. Work with difficult situations such as coordinating many threads or handling blocking threads. ms.date: "10/15/2018" -dev_langs: +dev_langs: - "csharp" - "vb" -helpviewer_keywords: +helpviewer_keywords: - "threading [.NET], design guidelines" - "threading [.NET], best practices" - "managed threading" @@ -13,166 +13,166 @@ ms.assetid: e51988e7-7f4b-4646-a06d-1416cee8d557 --- # Managed threading best practices -Multithreading requires careful programming. For most tasks, you can reduce complexity by queuing requests for execution by thread pool threads. This topic addresses more difficult situations, such as coordinating the work of multiple threads, or handling threads that block. - +Multithreading requires careful programming. For most tasks, you can reduce complexity by queuing requests for execution by thread pool threads. This topic addresses more difficult situations, such as coordinating the work of multiple threads, or handling threads that block. + > [!NOTE] -> Starting with .NET Framework 4, the Task Parallel Library and PLINQ provide APIs that reduce some of the complexity and risks of multi-threaded programming. For more information, see [Parallel Programming in .NET](../parallel-programming/index.md). - -## Deadlocks and race conditions - - Multithreading solves problems with throughput and responsiveness, but in doing so it introduces new problems: deadlocks and race conditions. - -### Deadlocks - - A deadlock occurs when each of two threads tries to lock a resource the other has already locked. Neither thread can make any further progress. - - Many methods of the managed threading classes provide time-outs to help you detect deadlocks. For example, the following code attempts to acquire a lock on an object named `lockObject`. If the lock is not obtained in 300 milliseconds, returns `false`. - -```vb -If Monitor.TryEnter(lockObject, 300) Then - Try - ' Place code protected by the Monitor here. - Finally - Monitor.Exit(lockObject) - End Try -Else - ' Code to execute if the attempt times out. -End If -``` - -```csharp -if (Monitor.TryEnter(lockObject, 300)) { - try { - // Place code protected by the Monitor here. - } - finally { - Monitor.Exit(lockObject); - } -} -else { - // Code to execute if the attempt times out. -} -``` - -### Race conditions - - A race condition is a bug that occurs when the outcome of a program depends on which of two or more threads reaches a particular block of code first. Running the program many times produces different results, and the result of any given run cannot be predicted. - - A simple example of a race condition is incrementing a field. Suppose a class has a private **static** field (**Shared** in Visual Basic) that is incremented every time an instance of the class is created, using code such as `objCt++;` (C#) or `objCt += 1` (Visual Basic). This operation requires loading the value from `objCt` into a register, incrementing the value, and storing it in `objCt`. - - In a multithreaded application, a thread that has loaded and incremented the value might be preempted by another thread which performs all three steps; when the first thread resumes execution and stores its value, it overwrites `objCt` without taking into account the fact that the value has changed in the interim. - - This particular race condition is easily avoided by using methods of the class, such as . To read about other techniques for synchronizing data among multiple threads, see [Synchronizing Data for Multithreading](synchronizing-data-for-multithreading.md). - - Race conditions can also occur when you synchronize the activities of multiple threads. Whenever you write a line of code, you must consider what might happen if a thread were preempted before executing the line (or before any of the individual machine instructions that make up the line), and another thread overtook it. - -## Static members and static constructors - - A class is not initialized until its class constructor (`static` constructor in C#, `Shared Sub New` in Visual Basic) has finished running. To prevent the execution of code on a type that is not initialized, the common language runtime blocks all calls from other threads to `static` members of the class (`Shared` members in Visual Basic) until the class constructor has finished running. - - For example, if a class constructor starts a new thread, and the thread procedure calls a `static` member of the class, the new thread blocks until the class constructor completes. - - This applies to any type that can have a `static` constructor. +> Starting with .NET Framework 4, the Task Parallel Library and PLINQ provide APIs that reduce some of the complexity and risks of multi-threaded programming. For more information, see [Parallel Programming in .NET](../parallel-programming/index.md). + +## Deadlocks and race conditions + + Multithreading solves problems with throughput and responsiveness, but in doing so it introduces new problems: deadlocks and race conditions. + +### Deadlocks + + A deadlock occurs when each of two threads tries to lock a resource the other has already locked. Neither thread can make any further progress. + + Many methods of the managed threading classes provide time-outs to help you detect deadlocks. For example, the following code attempts to acquire a lock on an object named `lockObject`. If the lock is not obtained in 300 milliseconds, returns `false`. + +```vb +If Monitor.TryEnter(lockObject, 300) Then + Try + ' Place code protected by the Monitor here. + Finally + Monitor.Exit(lockObject) + End Try +Else + ' Code to execute if the attempt times out. +End If +``` + +```csharp +if (Monitor.TryEnter(lockObject, 300)) { + try { + // Place code protected by the Monitor here. + } + finally { + Monitor.Exit(lockObject); + } +} +else { + // Code to execute if the attempt times out. +} +``` + +### Race conditions + + A race condition is a bug that occurs when the outcome of a program depends on which of two or more threads reaches a particular block of code first. Running the program many times produces different results, and the result of any given run cannot be predicted. + + A simple example of a race condition is incrementing a field. Suppose a class has a private **static** field (**Shared** in Visual Basic) that is incremented every time an instance of the class is created, using code such as `objCt++;` (C#) or `objCt += 1` (Visual Basic). This operation requires loading the value from `objCt` into a register, incrementing the value, and storing it in `objCt`. + + In a multithreaded application, a thread that has loaded and incremented the value might be preempted by another thread which performs all three steps; when the first thread resumes execution and stores its value, it overwrites `objCt` without taking into account the fact that the value has changed in the interim. + + This particular race condition is easily avoided by using methods of the class, such as . To read about other techniques for synchronizing data among multiple threads, see [Synchronizing Data for Multithreading](synchronizing-data-for-multithreading.md). + + Race conditions can also occur when you synchronize the activities of multiple threads. Whenever you write a line of code, you must consider what might happen if a thread were preempted before executing the line (or before any of the individual machine instructions that make up the line), and another thread overtook it. + +## Static members and static constructors + + A class is not initialized until its class constructor (`static` constructor in C#, `Shared Sub New` in Visual Basic) has finished running. To prevent the execution of code on a type that is not initialized, the common language runtime blocks all calls from other threads to `static` members of the class (`Shared` members in Visual Basic) until the class constructor has finished running. + + For example, if a class constructor starts a new thread, and the thread procedure calls a `static` member of the class, the new thread blocks until the class constructor completes. + + This applies to any type that can have a `static` constructor. ## Number of processors Whether there are multiple processors or only one processor available on a system can influence multithreaded architecture. For more information, see [Number of Processors](/previous-versions/dotnet/netframework-1.1/1c9txz50(v=vs.71)#number-of-processors). -Use the property to determine the number of processors available at run time. - -## General recommendations - -Consider the following guidelines when using multiple threads: - -- Don't use to terminate other threads. Calling `Abort` on another thread is akin to throwing an exception on that thread, without knowing what point that thread has reached in its processing. - -- Don't use and to synchronize the activities of multiple threads. Do use , , , and . - -- Don't control the execution of worker threads from your main program (using events, for example). Instead, design your program so that worker threads are responsible for waiting until work is available, executing it, and notifying other parts of your program when finished. If your worker threads do not block, consider using thread pool threads. is useful in situations where worker threads block. - -- Don't use types as lock objects. That is, avoid code such as `lock(typeof(X))` in C# or `SyncLock(GetType(X))` in Visual Basic, or the use of with objects. For a given type, there is only one instance of per application domain. If the type you take a lock on is public, code other than your own can take locks on it, leading to deadlocks. For additional issues, see [Reliability Best Practices](../../framework/performance/reliability-best-practices.md). - -- Use caution when locking on instances, for example `lock(this)` in C# or `SyncLock(Me)` in Visual Basic. If other code in your application, external to the type, takes a lock on the object, deadlocks could occur. - -- Do ensure that a thread that has entered a monitor always leaves that monitor, even if an exception occurs while the thread is in the monitor. The C# [lock](../../csharp/language-reference/statements/lock.md) statement and the Visual Basic [SyncLock](../../visual-basic/language-reference/statements/synclock-statement.md) statement provide this behavior automatically, employing a **finally** block to ensure that is called. If you cannot ensure that **Exit** will be called, consider changing your design to use **Mutex**. A mutex is automatically released when the thread that currently owns it terminates. - -- Do use multiple threads for tasks that require different resources, and avoid assigning multiple threads to a single resource. For example, any task involving I/O benefits from having its own thread, because that thread will block during I/O operations and thus allow other threads to execute. User input is another resource that benefits from a dedicated thread. On a single-processor computer, a task that involves intensive computation coexists with user input and with tasks that involve I/O, but multiple computation-intensive tasks contend with each other. - -- Consider using methods of the class for simple state changes, instead of using the `lock` statement (`SyncLock` in Visual Basic). The `lock` statement is a good general-purpose tool, but the class provides better performance for updates that must be atomic. Internally, it executes a single lock prefix if there is no contention. In code reviews, watch for code like that shown in the following examples. In the first example, a state variable is incremented: - - ```vb - SyncLock lockObject - myField += 1 - End SyncLock - ``` - - ```csharp +Use the property to determine the number of processors available at runtime. + +## General recommendations + +Consider the following guidelines when using multiple threads: + +- Don't use to terminate other threads. Calling `Abort` on another thread is akin to throwing an exception on that thread, without knowing what point that thread has reached in its processing. + +- Don't use and to synchronize the activities of multiple threads. Do use , , , and . + +- Don't control the execution of worker threads from your main program (using events, for example). Instead, design your program so that worker threads are responsible for waiting until work is available, executing it, and notifying other parts of your program when finished. If your worker threads do not block, consider using thread pool threads. is useful in situations where worker threads block. + +- Don't use types as lock objects. That is, avoid code such as `lock(typeof(X))` in C# or `SyncLock(GetType(X))` in Visual Basic, or the use of with objects. For a given type, there is only one instance of per application domain. If the type you take a lock on is public, code other than your own can take locks on it, leading to deadlocks. For additional issues, see [Reliability Best Practices](../../framework/performance/reliability-best-practices.md). + +- Use caution when locking on instances, for example `lock(this)` in C# or `SyncLock(Me)` in Visual Basic. If other code in your application, external to the type, takes a lock on the object, deadlocks could occur. + +- Do ensure that a thread that has entered a monitor always leaves that monitor, even if an exception occurs while the thread is in the monitor. The C# [lock](../../csharp/language-reference/statements/lock.md) statement and the Visual Basic [SyncLock](../../visual-basic/language-reference/statements/synclock-statement.md) statement provide this behavior automatically, employing a **finally** block to ensure that is called. If you cannot ensure that **Exit** will be called, consider changing your design to use **Mutex**. A mutex is automatically released when the thread that currently owns it terminates. + +- Do use multiple threads for tasks that require different resources, and avoid assigning multiple threads to a single resource. For example, any task involving I/O benefits from having its own thread, because that thread will block during I/O operations and thus allow other threads to execute. User input is another resource that benefits from a dedicated thread. On a single-processor computer, a task that involves intensive computation coexists with user input and with tasks that involve I/O, but multiple computation-intensive tasks contend with each other. + +- Consider using methods of the class for simple state changes, instead of using the `lock` statement (`SyncLock` in Visual Basic). The `lock` statement is a good general-purpose tool, but the class provides better performance for updates that must be atomic. Internally, it executes a single lock prefix if there is no contention. In code reviews, watch for code like that shown in the following examples. In the first example, a state variable is incremented: + + ```vb + SyncLock lockObject + myField += 1 + End SyncLock + ``` + + ```csharp lock(lockObject) - { - myField++; - } - ``` - - You can improve performance by using the method instead of the `lock` statement, as follows: - - ```vb - System.Threading.Interlocked.Increment(myField) - ``` - - ```csharp - System.Threading.Interlocked.Increment(myField); - ``` - + { + myField++; + } + ``` + + You can improve performance by using the method instead of the `lock` statement, as follows: + + ```vb + System.Threading.Interlocked.Increment(myField) + ``` + + ```csharp + System.Threading.Interlocked.Increment(myField); + ``` + > [!NOTE] - > Use the method for atomic increments larger than 1. - - In the second example, a reference type variable is updated only if it is a null reference (`Nothing` in Visual Basic). - - ```vb - If x Is Nothing Then - SyncLock lockObject - If x Is Nothing Then - x = y - End If - End SyncLock - End If - ``` - - ```csharp - if (x == null) - { - lock (lockObject) - { + > Use the method for atomic increments larger than 1. + + In the second example, a reference type variable is updated only if it is a null reference (`Nothing` in Visual Basic). + + ```vb + If x Is Nothing Then + SyncLock lockObject + If x Is Nothing Then + x = y + End If + End SyncLock + End If + ``` + + ```csharp + if (x == null) + { + lock (lockObject) + { x ??= y; - } - } - ``` - - Performance can be improved by using the method instead, as follows: - - ```vb - System.Threading.Interlocked.CompareExchange(x, y, Nothing) - ``` - - ```csharp - System.Threading.Interlocked.CompareExchange(ref x, y, null); - ``` - + } + } + ``` + + Performance can be improved by using the method instead, as follows: + + ```vb + System.Threading.Interlocked.CompareExchange(x, y, Nothing) + ``` + + ```csharp + System.Threading.Interlocked.CompareExchange(ref x, y, null); + ``` + > [!NOTE] > The method overload provides a type-safe alternative for reference types. - -## Recommendations for class libraries - -Consider the following guidelines when designing class libraries for multithreading: - -- Avoid the need for synchronization, if possible. This is especially true for heavily used code. For example, an algorithm might be adjusted to tolerate a race condition rather than eliminate it. Unnecessary synchronization decreases performance and creates the possibility of deadlocks and race conditions. - -- Make static data (`Shared` in Visual Basic) thread safe by default. - -- Do not make instance data thread safe by default. Adding locks to create thread-safe code decreases performance, increases lock contention, and creates the possibility for deadlocks to occur. In common application models, only one thread at a time executes user code, which minimizes the need for thread safety. For this reason, the .NET class libraries are not thread safe by default. - -- Avoid providing static methods that alter static state. In common server scenarios, static state is shared across requests, which means multiple threads can execute that code at the same time. This opens up the possibility of threading bugs. Consider using a design pattern that encapsulates data into instances that are not shared across requests. Furthermore, if static data are synchronized, calls between static methods that alter state can result in deadlocks or redundant synchronization, adversely affecting performance. - + +## Recommendations for class libraries + +Consider the following guidelines when designing class libraries for multithreading: + +- Avoid the need for synchronization, if possible. This is especially true for heavily used code. For example, an algorithm might be adjusted to tolerate a race condition rather than eliminate it. Unnecessary synchronization decreases performance and creates the possibility of deadlocks and race conditions. + +- Make static data (`Shared` in Visual Basic) thread safe by default. + +- Do not make instance data thread safe by default. Adding locks to create thread-safe code decreases performance, increases lock contention, and creates the possibility for deadlocks to occur. In common application models, only one thread at a time executes user code, which minimizes the need for thread safety. For this reason, the .NET class libraries are not thread safe by default. + +- Avoid providing static methods that alter static state. In common server scenarios, static state is shared across requests, which means multiple threads can execute that code at the same time. This opens up the possibility of threading bugs. Consider using a design pattern that encapsulates data into instances that are not shared across requests. Furthermore, if static data are synchronized, calls between static methods that alter state can result in deadlocks or redundant synchronization, adversely affecting performance. + ## See also - [Threading](managed-threading-basics.md) diff --git a/docs/standard/threading/thread-local-storage-thread-relative-static-fields-and-data-slots.md b/docs/standard/threading/thread-local-storage-thread-relative-static-fields-and-data-slots.md index 93a6859a30a47..a15307000f636 100644 --- a/docs/standard/threading/thread-local-storage-thread-relative-static-fields-and-data-slots.md +++ b/docs/standard/threading/thread-local-storage-thread-relative-static-fields-and-data-slots.md @@ -2,7 +2,7 @@ description: "Learn more about: Thread Local Storage: Thread-Relative Static Fields and Data Slots" title: "Thread Local Storage: Thread-Relative Static Fields and Data Slots" ms.date: "03/30/2017" -helpviewer_keywords: +helpviewer_keywords: - "threading [.NET], local storage" - "threading [.NET], thread-relative static fields" - "local thread storage" @@ -11,48 +11,48 @@ ms.assetid: c633a4dc-a790-4ed1-96b5-f72bd968b284 --- # Thread Local Storage: Thread-Relative Static Fields and Data Slots -You can use managed thread local storage (TLS) to store data that's unique to a thread and application domain. .NET provides two ways to use managed TLS: thread-relative static fields and data slots. - -- Use thread-relative static fields (thread-relative `Shared` fields in Visual Basic) if you can anticipate your exact needs at compile time. Thread-relative static fields provide the best performance. They also give you the benefits of compile-time type checking. - -- Use data slots when your actual requirements might be discovered only at run time. Data slots are slower and more awkward to use than thread-relative static fields, and data is stored as type , so you must cast it to the correct type before you use it. - - In unmanaged C++, you use `TlsAlloc` to allocate slots dynamically and `__declspec(thread)` to declare that a variable should be allocated in thread-relative storage. Thread-relative static fields and data slots provide the managed version of this behavior. - -You can use the class to create thread-local objects that are initialized lazily when the object is first consumed. For more information, see [Lazy Initialization](../../framework/performance/lazy-initialization.md). - -## Uniqueness of Data in Managed TLS - - Whether you use thread-relative static fields or data slots, data in managed TLS is unique to the combination of thread and application domain. - -- Within an application domain, one thread cannot modify data from another thread, even when both threads use the same field or slot. - -- When a thread accesses the same field or slot from multiple application domains, a separate value is maintained in each application domain. - - For example, if a thread sets the value of a thread-relative static field, enters another application domain, and then retrieves the value of the field, the value retrieved in the second application domain differs from the value in the first application domain. Setting a new value for the field in the second application domain does not affect the field's value in the first application domain. - - Similarly, when a thread gets the same named data slot in two different application domains, the data in the first application domain remains independent of the data in the second application domain. - -## Thread-Relative Static Fields - - If you know that a piece of data is always unique to a thread and application-domain combination, apply the attribute to the static field. Use the field as you would use any other static field. The data in the field is unique to each thread that uses it. - - Thread-relative static fields provide better performance than data slots and have the benefit of compile-time type checking. - - Be aware that any class constructor code will run on the first thread in the first context that accesses the field. In all other threads or contexts in the same application domain, the fields will be initialized to `null` (`Nothing` in Visual Basic) if they are reference types, or to their default values if they are value types. Therefore, you should not rely on class constructors to initialize thread-relative static fields. Instead, avoid initializing thread-relative static fields and assume that they are initialized to `null` (`Nothing`) or to their default values. - -## Data Slots - -.NET provides dynamic data slots that are unique to a combination of thread and application domain. There are two types of data slots: named slots and unnamed slots. Both are implemented by using the structure. - -- To create a named data slot, use the or method. To get a reference to an existing named slot, pass its name to the method. - -- To create an unnamed data slot, use the method. - - For both named and unnamed slots, use the and methods to set and retrieve the information in the slot. These are static methods that always act on the data for the thread that is currently executing them. - - Named slots can be convenient, because you can retrieve the slot when you need it by passing its name to the method, instead of maintaining a reference to an unnamed slot. However, if another component uses the same name for its thread-relative storage and a thread executes code from both your component and the other component, the two components might corrupt each other's data. (This scenario assumes that both components are running in the same application domain, and that they are not designed to share the same data.) - +You can use managed thread local storage (TLS) to store data that's unique to a thread and application domain. .NET provides two ways to use managed TLS: thread-relative static fields and data slots. + +- Use thread-relative static fields (thread-relative `Shared` fields in Visual Basic) if you can anticipate your exact needs at compile time. Thread-relative static fields provide the best performance. They also give you the benefits of compile-time type checking. + +- Use data slots when your actual requirements might be discovered only at runtime. Data slots are slower and more awkward to use than thread-relative static fields, and data is stored as type , so you must cast it to the correct type before you use it. + + In unmanaged C++, you use `TlsAlloc` to allocate slots dynamically and `__declspec(thread)` to declare that a variable should be allocated in thread-relative storage. Thread-relative static fields and data slots provide the managed version of this behavior. + +You can use the class to create thread-local objects that are initialized lazily when the object is first consumed. For more information, see [Lazy Initialization](../../framework/performance/lazy-initialization.md). + +## Uniqueness of Data in Managed TLS + + Whether you use thread-relative static fields or data slots, data in managed TLS is unique to the combination of thread and application domain. + +- Within an application domain, one thread cannot modify data from another thread, even when both threads use the same field or slot. + +- When a thread accesses the same field or slot from multiple application domains, a separate value is maintained in each application domain. + + For example, if a thread sets the value of a thread-relative static field, enters another application domain, and then retrieves the value of the field, the value retrieved in the second application domain differs from the value in the first application domain. Setting a new value for the field in the second application domain does not affect the field's value in the first application domain. + + Similarly, when a thread gets the same named data slot in two different application domains, the data in the first application domain remains independent of the data in the second application domain. + +## Thread-Relative Static Fields + + If you know that a piece of data is always unique to a thread and application-domain combination, apply the attribute to the static field. Use the field as you would use any other static field. The data in the field is unique to each thread that uses it. + + Thread-relative static fields provide better performance than data slots and have the benefit of compile-time type checking. + + Be aware that any class constructor code will run on the first thread in the first context that accesses the field. In all other threads or contexts in the same application domain, the fields will be initialized to `null` (`Nothing` in Visual Basic) if they are reference types, or to their default values if they are value types. Therefore, you should not rely on class constructors to initialize thread-relative static fields. Instead, avoid initializing thread-relative static fields and assume that they are initialized to `null` (`Nothing`) or to their default values. + +## Data Slots + +.NET provides dynamic data slots that are unique to a combination of thread and application domain. There are two types of data slots: named slots and unnamed slots. Both are implemented by using the structure. + +- To create a named data slot, use the or method. To get a reference to an existing named slot, pass its name to the method. + +- To create an unnamed data slot, use the method. + + For both named and unnamed slots, use the and methods to set and retrieve the information in the slot. These are static methods that always act on the data for the thread that is currently executing them. + + Named slots can be convenient, because you can retrieve the slot when you need it by passing its name to the method, instead of maintaining a reference to an unnamed slot. However, if another component uses the same name for its thread-relative storage and a thread executes code from both your component and the other component, the two components might corrupt each other's data. (This scenario assumes that both components are running in the same application domain, and that they are not designed to share the same data.) + ## See also -