diff --git a/docs/standard/attributes/retrieving-information-stored-in-attributes.md b/docs/standard/attributes/retrieving-information-stored-in-attributes.md index 8b2704dafe2ff..48c8942845941 100644 --- a/docs/standard/attributes/retrieving-information-stored-in-attributes.md +++ b/docs/standard/attributes/retrieving-information-stored-in-attributes.md @@ -1,7 +1,8 @@ --- title: "Retrieving Information Stored in Attributes" description: Learn to retrieve information stored in attributes, such as for an attribute instance, many instances for the same scope, & many instances for different scopes. -ms.date: "03/30/2017" +ms.date: "08/05/2022" +ms.custom: devdivchpfy22 dev_langs: - "csharp" - "vb" @@ -14,10 +15,10 @@ ms.topic: how-to --- # Retrieving Information Stored in Attributes -Retrieving a custom attribute is a simple process. First, declare an instance of the attribute you want to retrieve. Then, use the method to initialize the new attribute to the value of the attribute you want to retrieve. Once the new attribute is initialized, you simply use its properties to get the values. +Retrieving a custom attribute is a simple process. First, declare an instance of the attribute you want to retrieve. Then, use the method to initialize the new attribute to the value of the attribute you want to retrieve. Once the new attribute is initialized, you can use its properties to get the values. > [!IMPORTANT] -> This topic describes how to retrieve attributes for code loaded into the execution context. To retrieve attributes for code loaded into the reflection-only context, you must use the class, as shown in [How to: Load Assemblies into the Reflection-Only Context](../../framework/reflection-and-codedom/how-to-load-assemblies-into-the-reflection-only-context.md). +> This article describes how to retrieve attributes for code loaded into the execution context. To retrieve attributes for code loaded into the reflection-only context, you must use the class, as shown in [How to: Load Assemblies into the Reflection-Only Context](../../framework/reflection-and-codedom/how-to-load-assemblies-into-the-reflection-only-context.md). This section describes the following ways to retrieve attributes: @@ -31,13 +32,13 @@ Retrieving a custom attribute is a simple process. First, declare an instance of ## Retrieving a Single Instance of an Attribute - In the following example, the `DeveloperAttribute` (described in the previous section) is applied to the `MainApp` class on the class level. The `GetAttribute` method uses **GetCustomAttribute** to retrieve the values stored in `DeveloperAttribute` on the class level before displaying them to the console. + In the following example, the `DeveloperAttribute` (described in the previous section) is applied to the `MainApp` class on the class level. The `GetAttribute` method uses `GetCustomAttribute` to retrieve the values stored in `DeveloperAttribute` on the class level before displaying them to the console. [!code-cpp[Conceptual.Attributes.Usage#18](../../../samples/snippets/cpp/VS_Snippets_CLR/conceptual.attributes.usage/cpp/source3.cpp#18)] [!code-csharp[Conceptual.Attributes.Usage#18](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.attributes.usage/cs/source3.cs#18)] [!code-vb[Conceptual.Attributes.Usage#18](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.attributes.usage/vb/source3.vb#18)] - This program displays the following text when executed. + The execution of the preceding program displays the following text: ```console The Name Attribute is: Joan Smith. @@ -45,21 +46,21 @@ The Level Attribute is: 42. The Reviewed Attribute is: True. ``` - If the attribute is not found, the **GetCustomAttribute** method initializes `MyAttribute` to a null value. This example checks `MyAttribute` for such an instance and notifies the user if no attribute is found. If the `DeveloperAttribute` is not found in the class scope, the following message displays to the console. + If the attribute isn't found, the `GetCustomAttribute` method initializes `MyAttribute` to a null value. This example checks `MyAttribute` for such an instance and notifies the user if the attribute isn't found. If `DeveloperAttribute` isn't found in the class scope, the console displays the following message: ```console The attribute was not found. ``` - This example assumes that the attribute definition is in the current namespace. Remember to import the namespace in which the attribute definition resides if it is not in the current namespace. + The preceding example assumes that the attribute definition is in the current namespace. Remember to import the namespace in which the attribute definition resides if it isn't in the current namespace. ## Retrieving Multiple Instances of an Attribute Applied to the Same Scope - In the previous example, the class to inspect and the specific attribute to find are passed to . That code works well if only one instance of an attribute is applied on the class level. However, if multiple instances of an attribute are applied on the same class level, the **GetCustomAttribute** method does not retrieve all the information. In cases where multiple instances of the same attribute are applied to the same scope, you can use to place all instances of an attribute into an array. For example, if two instances of `DeveloperAttribute` are applied on the class level of the same class, the `GetAttribute` method can be modified to display the information found in both attributes. Remember, to apply multiple attributes on the same level, the attribute must be defined with the **AllowMultiple** property set to **true** in the . + In the preceding example, the class to inspect and the specific attribute to find are passed to the method. That code works well if only one instance of an attribute is applied on the class level. However, if multiple instances of an attribute are applied on the same class level, the `GetCustomAttribute` method doesn't retrieve all the information. In cases where multiple instances of the same attribute are applied to the same scope, you can use method to place all instances of an attribute into an array. For example, if two instances of `DeveloperAttribute` are applied on the class level of the same class, the `GetAttribute` method can be modified to display the information found in both attributes. Remember, to apply multiple attributes on the same level. The attribute must be defined with the `AllowMultiple` property set to `true` in the class. - The following code example shows how to use the **GetCustomAttributes** method to create an array that references all instances of `DeveloperAttribute` in any given class. The values of all attributes are then displayed to the console. + The following code example shows how to use the `GetCustomAttributes` method to create an array that references all instances of `DeveloperAttribute` in any given class. The code then outputs the values of all the attributes to the console. [!code-cpp[Conceptual.Attributes.Usage#19](../../../samples/snippets/cpp/VS_Snippets_CLR/conceptual.attributes.usage/cpp/source3.cpp#19)] [!code-csharp[Conceptual.Attributes.Usage#19](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.attributes.usage/cs/source3.cs#19)] @@ -71,17 +72,17 @@ The attribute was not found. ## Retrieving Multiple Instances of an Attribute Applied to Different Scopes - The and methods do not search an entire class and return all instances of an attribute in that class. Rather, they search only one specified method or member at a time. If you have a class with the same attribute applied to every member and you want to retrieve the values in all the attributes applied to those members, you must supply every method or member individually to **GetCustomAttributes** and **GetCustomAttribute**. + The and methods don't search an entire class and return all instances of an attribute in that class. Rather, they search only one specified method or member at a time. If you have a class with the same attribute applied to every member and you want to retrieve the values in all the attributes applied to those members, you must supply every method or member individually to `GetCustomAttributes` and `GetCustomAttribute`. - The following code example takes a class as a parameter and searches for the `DeveloperAttribute` (defined previously) on the class level and on every individual method of that class. + The following code example takes a class as a parameter and searches for the `DeveloperAttribute` (defined previously) on the class level and on every individual method of that class: [!code-cpp[Conceptual.Attributes.Usage#20](../../../samples/snippets/cpp/VS_Snippets_CLR/conceptual.attributes.usage/cpp/source3.cpp#20)] [!code-csharp[Conceptual.Attributes.Usage#20](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.attributes.usage/cs/source3.cs#20)] [!code-vb[Conceptual.Attributes.Usage#20](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.attributes.usage/vb/source3.vb#20)] - If no instances of the `DeveloperAttribute` are found on the method level or class level, the `GetAttribute` method notifies the user that no attributes were found and displays the name of the method or class that does not contain the attribute. If an attribute is found, the `Name`, `Level`, and `Reviewed` fields are displayed to the console. + If no instances of the `DeveloperAttribute` are found on the method level or class level, the `GetAttribute` method notifies the user that no attributes were found and displays the name of the method or class that doesn't contain the attribute. If an attribute is found, the console displays the `Name`, `Level`, and `Reviewed` fields. - You can use the members of the class to get the individual methods and members in the passed class. This example first queries the **Type** object to get attribute information for the class level. Next, it uses to place instances of all methods into an array of objects to retrieve attribute information for the method level. You can also use the method to check for attributes on the property level or to check for attributes on the constructor level. + You can use the members of the class to get the individual methods and members in the passed class. This example first queries the `Type` object to get attribute information for the class level. Next, it uses to place instances of all methods into an array of objects to retrieve attribute information for the method level. You can also use the method to check for attributes on the property level or to check for attributes on the constructor level. ## See also diff --git a/docs/standard/attributes/writing-custom-attributes.md b/docs/standard/attributes/writing-custom-attributes.md index 16fa08499a909..20e89a6c34e99 100644 --- a/docs/standard/attributes/writing-custom-attributes.md +++ b/docs/standard/attributes/writing-custom-attributes.md @@ -1,7 +1,8 @@ --- title: "Writing Custom Attributes" description: Design your own custom attributes in .NET. Custom attributes are essentially classes derived directly or indirectly from System.Attribute. -ms.date: "07/17/2018" +ms.date: "08/05/2022" +ms.custom: devdivchpfy22 dev_langs: - "csharp" - "vb" @@ -17,9 +18,9 @@ helpviewer_keywords: - "attribute classes, declaring" ms.assetid: 97216f69-bde8-49fd-ac40-f18c500ef5dc --- -# Writing Custom Attributes +# Write custom attributes -To design your own custom attributes, you do not need to learn many new concepts. If you are familiar with object-oriented programming and know how to design classes, you already have most of the knowledge needed. Custom attributes are essentially traditional classes that derive directly or indirectly from . Just like traditional classes, custom attributes contain methods that store and retrieve data. +To design custom attributes, you don't need to learn many new concepts. If you're familiar with object-oriented programming and know how to design classes, you already have most of the knowledge needed. Custom attributes are traditional classes that derive directly or indirectly from the class. Just like traditional classes, custom attributes contain methods that store and retrieve data. The primary steps to properly design custom attribute classes are as follows: @@ -35,7 +36,7 @@ To design your own custom attributes, you do not need to learn many new concepts ## Applying the AttributeUsageAttribute - A custom attribute declaration begins with the , which defines some of the key characteristics of your attribute class. For example, you can specify whether your attribute can be inherited by other classes or specify which elements the attribute can be applied to. The following code fragment demonstrates how to use the . + A custom attribute declaration begins with the attribute, which defines some of the key characteristics of your attribute class. For example, you can specify whether your attribute can be inherited by other classes or which elements the attribute can be applied to. The following code fragment demonstrates how to use the : [!code-cpp[Conceptual.Attributes.Usage#5](../../../samples/snippets/cpp/VS_Snippets_CLR/conceptual.attributes.usage/cpp/source2.cpp#5)] [!code-csharp[Conceptual.Attributes.Usage#5](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.attributes.usage/cs/source2.cs#5)] @@ -45,9 +46,9 @@ To design your own custom attributes, you do not need to learn many new concepts ### AttributeTargets Member - In the previous example, is specified, indicating that this attribute can be applied to all program elements. Alternatively, you can specify , indicating that your attribute can be applied only to a class, or , indicating that your attribute can be applied only to a method. All program elements can be marked for description by a custom attribute in this manner. + In the preceding example, is specified, indicating that this attribute can be applied to all program elements. Alternatively, you can specify , indicating that your attribute can be applied only to a class, or , indicating that your attribute can be applied only to a method. All program elements can be marked for description by a custom attribute in this manner. - You can also pass multiple values. The following code fragment specifies that a custom attribute can be applied to any class or method. + You can also pass multiple values. The following code fragment specifies that a custom attribute can be applied to any class or method: [!code-cpp[Conceptual.Attributes.Usage#6](../../../samples/snippets/cpp/VS_Snippets_CLR/conceptual.attributes.usage/cpp/source2.cpp#6)] [!code-csharp[Conceptual.Attributes.Usage#6](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.attributes.usage/cs/source2.cs#6)] @@ -55,19 +56,19 @@ To design your own custom attributes, you do not need to learn many new concepts ### Inherited Property - The property indicates whether your attribute can be inherited by classes that are derived from the classes to which your attribute is applied. This property takes either a `true` (the default) or `false` flag. In the following example, `MyAttribute` has a default value of `true`, while `YourAttribute` has an value of `false`. + The property indicates whether your attribute can be inherited by classes that are derived from the classes to which your attribute is applied. This property takes either a `true` (the default) or `false` flag. In the following example, `MyAttribute` has a default value of `true`, while `YourAttribute` has an value of `false`: [!code-cpp[Conceptual.Attributes.Usage#7](../../../samples/snippets/cpp/VS_Snippets_CLR/conceptual.attributes.usage/cpp/source2.cpp#7)] [!code-csharp[Conceptual.Attributes.Usage#7](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.attributes.usage/cs/source2.cs#7)] [!code-vb[Conceptual.Attributes.Usage#7](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.attributes.usage/vb/source2.vb#7)] - The two attributes are then applied to a method in the base class `MyClass`. + The two attributes are then applied to a method in the base class `MyClass`: [!code-cpp[Conceptual.Attributes.Usage#9](../../../samples/snippets/cpp/VS_Snippets_CLR/conceptual.attributes.usage/cpp/source2.cpp#9)] [!code-csharp[Conceptual.Attributes.Usage#9](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.attributes.usage/cs/source2.cs#9)] [!code-vb[Conceptual.Attributes.Usage#9](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.attributes.usage/vb/source2.vb#9)] - Finally, the class `YourClass` is inherited from the base class `MyClass`. The method `MyMethod` shows `MyAttribute`, but not `YourAttribute`. + Finally, the class `YourClass` is inherited from the base class `MyClass`. The method `MyMethod` shows `MyAttribute` but not `YourAttribute`: [!code-cpp[Conceptual.Attributes.Usage#10](../../../samples/snippets/cpp/VS_Snippets_CLR/conceptual.attributes.usage/cpp/source2.cpp#10)] [!code-csharp[Conceptual.Attributes.Usage#10](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.attributes.usage/cs/source2.cs#10)] @@ -75,25 +76,25 @@ To design your own custom attributes, you do not need to learn many new concepts ### AllowMultiple Property - The property indicates whether multiple instances of your attribute can exist on an element. If set to `true`, multiple instances are allowed; if set to `false` (the default), only one instance is allowed. + The property indicates whether multiple instances of your attribute can exist on an element. If set to `true`, multiple instances are allowed. If set to `false` (the default), only one instance is allowed. - In the following example, `MyAttribute` has a default value of `false`, while `YourAttribute` has a value of `true`. + In the following example, `MyAttribute` has a default value of `false`, while `YourAttribute` has a value of `true`: [!code-cpp[Conceptual.Attributes.Usage#11](../../../samples/snippets/cpp/VS_Snippets_CLR/conceptual.attributes.usage/cpp/source2.cpp#11)] [!code-csharp[Conceptual.Attributes.Usage#11](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.attributes.usage/cs/source2.cs#11)] [!code-vb[Conceptual.Attributes.Usage#11](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.attributes.usage/vb/source2.vb#11)] - When multiple instances of these attributes are applied, `MyAttribute` produces a compiler error. The following code example shows the valid use of `YourAttribute` and the invalid use of `MyAttribute`. + When multiple instances of these attributes are applied, `MyAttribute` produces a compiler error. The following code example shows the valid use of `YourAttribute` and the invalid use of `MyAttribute`: [!code-cpp[Conceptual.Attributes.Usage#13](../../../samples/snippets/cpp/VS_Snippets_CLR/conceptual.attributes.usage/cpp/source2.cpp#13)] [!code-csharp[Conceptual.Attributes.Usage#13](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.attributes.usage/cs/source2.cs#13)] [!code-vb[Conceptual.Attributes.Usage#13](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.attributes.usage/vb/source2.vb#13)] - If both the property and the property are set to `true`, a class that is inherited from another class can inherit an attribute and have another instance of the same attribute applied in the same child class. If is set to `false`, the values of any attributes in the parent class will be overwritten by new instances of the same attribute in the child class. + If both the property and the property are set to `true`, a class that's inherited from another class can inherit an attribute and have another instance of the same attribute applied in the same child class. If is set to `false`, the values of any attributes in the parent class will be overwritten by new instances of the same attribute in the child class. ## Declaring the Attribute Class - After you apply the , you can begin to define the specifics of your attribute. The declaration of an attribute class looks similar to the declaration of a traditional class, as demonstrated by the following code. + After you apply the , start defining the specifics of your attribute. The declaration of an attribute class looks similar to the declaration of a traditional class, as demonstrated by the following code: [!code-cpp[Conceptual.Attributes.Usage#14](../../../samples/snippets/cpp/VS_Snippets_CLR/conceptual.attributes.usage/cpp/source2.cpp#14)] [!code-csharp[Conceptual.Attributes.Usage#14](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.attributes.usage/cs/source2.cs#14)] @@ -105,19 +106,22 @@ To design your own custom attributes, you do not need to learn many new concepts - By convention, the name of the attribute class ends with the word **Attribute**. While not required, this convention is recommended for readability. When the attribute is applied, the inclusion of the word Attribute is optional. -- All attribute classes must inherit directly or indirectly from . +- All attribute classes must inherit directly or indirectly from the class. - In Microsoft Visual Basic, all custom attribute classes must have the attribute. ## Declaring Constructors - Attributes are initialized with constructors in the same way as traditional classes. The following code fragment illustrates a typical attribute constructor. This public constructor takes a parameter and sets a member variable equal to its value. + Just like traditional classes, attributes are initialized with constructors. The following code fragment illustrates a typical attribute constructor. This public constructor takes a parameter and sets a member variable equal to its value. [!code-cpp[Conceptual.Attributes.Usage#15](../../../samples/snippets/cpp/VS_Snippets_CLR/conceptual.attributes.usage/cpp/source2.cpp#15)] [!code-csharp[Conceptual.Attributes.Usage#15](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.attributes.usage/cs/source2.cs#15)] [!code-vb[Conceptual.Attributes.Usage#15](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.attributes.usage/vb/source2.vb#15)] - You can overload the constructor to accommodate different combinations of values. If you also define a [property](/previous-versions/visualstudio/visual-studio-2013/65zdfbdt(v=vs.120)) for your custom attribute class, you can use a combination of named and positional parameters when initializing the attribute. Typically, you define all required parameters as positional and all optional parameters as named. In this case, the attribute cannot be initialized without the required parameter. All other parameters are optional. Note that in Visual Basic, constructors for an attribute class should not use a ParamArray argument. + You can overload the constructor to accommodate different combinations of values. If you also define a [property](/previous-versions/visualstudio/visual-studio-2013/65zdfbdt(v=vs.120)) for your custom attribute class, you can use a combination of named and positional parameters when initializing the attribute. Typically, you define all required parameters as positional and all optional parameters as named. In this case, the attribute can't be initialized without the required parameter. All other parameters are optional. + +> [!NOTE] +> In Visual Basic, constructors for an attribute class shouldn't use a `ParamArray` argument. The following code example shows how an attribute that uses the previous constructor can be applied using optional and required parameters. It assumes that the attribute has one required Boolean value and one optional string property. @@ -127,7 +131,7 @@ To design your own custom attributes, you do not need to learn many new concepts ## Declaring Properties - If you want to define a named parameter or provide an easy way to return the values stored by your attribute, declare a [property](/previous-versions/visualstudio/visual-studio-2013/65zdfbdt(v=vs.120)). Attribute properties should be declared as public entities with a description of the data type that will be returned. Define the variable that will hold the value of your property and associate it with the **get** and **set** methods. The following code example demonstrates how to implement a simple property in your attribute. + If you want to define a named parameter or provide an easy way to return the values stored by your attribute, declare a [property](/previous-versions/visualstudio/visual-studio-2013/65zdfbdt(v=vs.120)). Attribute properties should be declared as public entities with a description of the data type that will be returned. Define the variable that will hold the value of your property and associate it with the `get` and `set` methods. The following code example demonstrates how to implement a property in your attribute: [!code-cpp[Conceptual.Attributes.Usage#16](../../../samples/snippets/cpp/VS_Snippets_CLR/conceptual.attributes.usage/cpp/source2.cpp#16)] [!code-csharp[Conceptual.Attributes.Usage#16](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.attributes.usage/cs/source2.cs#16)] @@ -135,19 +139,19 @@ To design your own custom attributes, you do not need to learn many new concepts ## Custom Attribute Example - This section incorporates the previous information and shows how to design a simple attribute that documents information about the author of a section of code. The attribute in this example stores the name and level of the programmer, and whether the code has been reviewed. It uses three private variables to store the actual values to save. Each variable is represented by a public property that gets and sets the values. Finally, the constructor is defined with two required parameters. + This section incorporates the previous information and shows how to design an attribute that documents information about the author of a section of code. The attribute in this example stores the name and level of the programmer, and whether the code has been reviewed. It uses three private variables to store the actual values to save. Each variable is represented by a public property that gets and sets the values. Finally, the constructor is defined with two required parameters: [!code-cpp[Conceptual.Attributes.Usage#4](../../../samples/snippets/cpp/VS_Snippets_CLR/conceptual.attributes.usage/cpp/source2.cpp#4)] [!code-csharp[Conceptual.Attributes.Usage#4](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.attributes.usage/cs/source2.cs#4)] [!code-vb[Conceptual.Attributes.Usage#4](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.attributes.usage/vb/source2.vb#4)] - You can apply this attribute using the full name, `DeveloperAttribute`, or using the abbreviated name, `Developer`, in one of the following ways. + You can apply this attribute using the full name, `DeveloperAttribute`, or using the abbreviated name, `Developer`, in one of the following ways: [!code-cpp[Conceptual.Attributes.Usage#12](../../../samples/snippets/cpp/VS_Snippets_CLR/conceptual.attributes.usage/cpp/source2.cpp#12)] [!code-csharp[Conceptual.Attributes.Usage#12](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.attributes.usage/cs/source2.cs#12)] [!code-vb[Conceptual.Attributes.Usage#12](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.attributes.usage/vb/source2.vb#12)] - The first example shows the attribute applied with only the required named parameters, while the second example shows the attribute applied with both the required and optional parameters. + The first example shows the attribute applied with only the required named parameters. The second example shows the attribute applied with both the required and optional parameters. ## See also diff --git a/docs/standard/base-types/best-practices.md b/docs/standard/base-types/best-practices.md index 8e429e6ffeeb1..94bdd450edf27 100644 --- a/docs/standard/base-types/best-practices.md +++ b/docs/standard/base-types/best-practices.md @@ -1,7 +1,8 @@ --- title: Best Practices for Regular Expressions in .NET description: Learn how to create efficient, effective regular expressions in .NET. -ms.date: "06/30/2020" +ms.date: "08/05/2022" +ms.custom: devdivchpfy22 ms.topic: conceptual dev_langs: - "csharp" @@ -13,64 +14,64 @@ ms.assetid: 618e5afb-3a97-440d-831a-70e4c526a51c --- # Best practices for regular expressions in .NET -The regular expression engine in .NET is a powerful, full-featured tool that processes text based on pattern matches rather than on comparing and matching literal text. In most cases, it performs pattern matching rapidly and efficiently. However, in some cases, the regular expression engine can appear to be very slow. In extreme cases, it can even appear to stop responding as it processes a relatively small input over the course of hours or even days. +The regular expression engine in .NET is a powerful, full-featured tool that processes text based on pattern matches rather than on comparing and matching literal text. In most cases, it performs pattern matching rapidly and efficiently. However, in some cases, the regular expression engine can appear to be slow. In extreme cases, it can even appear to stop responding as it processes a relatively small input over the course of hours or even days. -This topic outlines some of the best practices that developers can adopt to ensure that their regular expressions achieve optimal performance. +This article outlines some of the best practices that developers can adopt to ensure that their regular expressions achieve optimal performance. [!INCLUDE [regex](../../../includes/regex.md)] ## Consider the input source -In general, regular expressions can accept two types of input: constrained or unconstrained. Constrained input is text that originates from a known or reliable source and follows a predefined format. Unconstrained input is text that originates from an unreliable source, such as a web user, and may not follow a predefined or expected format. +In general, regular expressions can accept two types of input: constrained or unconstrained. Constrained input is a text that originates from a known or reliable source and follows a predefined format. Unconstrained input is a text that originates from an unreliable source, such as a web user, and might not follow a predefined or expected format. -Regular expression patterns are typically written to match valid input. That is, developers examine the text that they want to match and then write a regular expression pattern that matches it. Developers then determine whether this pattern requires correction or further elaboration by testing it with multiple valid input items. When the pattern matches all presumed valid inputs, it is declared to be production-ready and can be included in a released application. This makes a regular expression pattern suitable for matching constrained input. However, it does not make it suitable for matching unconstrained input. +Regular expression patterns are often written to match valid input. That is, developers examine the text that they want to match and then write a regular expression pattern that matches it. Developers then determine whether this pattern requires correction or further elaboration by testing it with multiple valid input items. When the pattern matches all presumed valid inputs, it's declared to be production-ready, and can be included in a released application. This approach makes a regular expression pattern suitable for matching constrained input. However, it doesn't make it suitable for matching unconstrained input. -To match unconstrained input, a regular expression must be able to efficiently handle three kinds of text: +To match unconstrained input, a regular expression must handle three kinds of text efficiently: - Text that matches the regular expression pattern. -- Text that does not match the regular expression pattern. +- Text that doesn't match the regular expression pattern. - Text that nearly matches the regular expression pattern. The last text type is especially problematic for a regular expression that has been written to handle constrained input. If that regular expression also relies on extensive [backtracking](backtracking-in-regular-expressions.md), the regular expression engine can spend an inordinate amount of time (in some cases, many hours or days) processing seemingly innocuous text. > [!WARNING] -> The following example uses a regular expression that is prone to excessive backtracking and that is likely to reject valid email addresses. You should not use it in an email validation routine. If you would like a regular expression that validates email addresses, see [How to: Verify that Strings Are in Valid Email Format](how-to-verify-that-strings-are-in-valid-email-format.md). +> The following example uses a regular expression that's prone to excessive backtracking and that's likely to reject valid email addresses. You shouldn't use it in an email validation routine. If you would like a regular expression that validates email addresses, see [How to: Verify that Strings Are in Valid Email Format](how-to-verify-that-strings-are-in-valid-email-format.md). -For example, consider a very commonly used but extremely problematic regular expression for validating the alias of an email address. The regular expression `^[0-9A-Z]([-.\w]*[0-9A-Z])*$` is written to process what is considered to be a valid email address, which consists of an alphanumeric character, followed by zero or more characters that can be alphanumeric, periods, or hyphens. The regular expression must end with an alphanumeric character. However, as the following example shows, although this regular expression handles valid input easily, its performance is very inefficient when it is processing nearly valid input. +For example, consider a commonly used but problematic regular expression for validating the alias of an email address. The regular expression `^[0-9A-Z]([-.\w]*[0-9A-Z])*$` is written to process what is considered to be a valid email address. A valid email address consists of an alphanumeric character, followed by zero or more characters that can be alphanumeric, periods, or hyphens. The regular expression must end with an alphanumeric character. However, as the following example shows, although this regular expression handles valid input easily, its performance is inefficient when it's processing nearly valid input: [!code-csharp[Conceptual.RegularExpressions.BestPractices#1](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.regularexpressions.bestpractices/cs/design2.cs#1)] [!code-vb[Conceptual.RegularExpressions.BestPractices#1](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.regularexpressions.bestpractices/vb/design2.vb#1)] -As the output from the example shows, the regular expression engine processes the valid email alias in about the same time interval regardless of its length. On the other hand, when the nearly valid email address has more than five characters, processing time approximately doubles for each additional character in the string. This means that a nearly valid 28-character string would take over an hour to process, and a nearly valid 33-character string would take nearly a day to process. +As the output from the preceding example shows, the regular expression engine processes the valid email alias in about the same time interval regardless of its length. On the other hand, when the nearly valid email address has more than five characters, processing time approximately doubles for each extra character in the string. Therefore, a nearly valid 28-character string would take over an hour to process, and a nearly valid 33-character string would take nearly a day to process. -Because this regular expression was developed solely by considering the format of input to be matched, it fails to take account of input that does not match the pattern. This, in turn, can allow unconstrained input that nearly matches the regular expression pattern to significantly degrade performance. +Because this regular expression was developed solely by considering the format of input to be matched, it fails to take account of input that doesn't match the pattern. This oversight, in turn, can allow unconstrained input that nearly matches the regular expression pattern to significantly degrade performance. To solve this problem, you can do the following: - When developing a pattern, you should consider how backtracking might affect the performance of the regular expression engine, particularly if your regular expression is designed to process unconstrained input. For more information, see the [Take Charge of Backtracking](#take-charge-of-backtracking) section. -- Thoroughly test your regular expression using invalid and near-valid input as well as valid input. To generate input for a particular regular expression randomly, you can use [Rex](https://www.microsoft.com/research/project/rex-regular-expression-exploration/), which is a regular expression exploration tool from Microsoft Research. +- Thoroughly test your regular expression using invalid, near-valid, and valid input. You can use [Rex](https://www.microsoft.com/research/project/rex-regular-expression-exploration/) to randomly generate input for a particular regular expression. [Rex](https://www.microsoft.com/research/project/rex-regular-expression-exploration/) is a regular expression exploration tool from Microsoft Research. ## Handle object instantiation appropriately -At the heart of .NET's regular expression object model is the class, which represents the regular expression engine. Often, the single greatest factor that affects regular expression performance is the way in which the engine is used. Defining a regular expression involves tightly coupling the regular expression engine with a regular expression pattern. That coupling process, whether it involves instantiating a object by passing its constructor a regular expression pattern or calling a static method by passing it the regular expression pattern along with the string to be analyzed, is by necessity an expensive one. +At the heart of .NET's regular expression object model, is the class, which represents the regular expression engine. Often, the single greatest factor that affects regular expression performance is the way in which the engine is used. Defining a regular expression involves tightly coupling the regular expression engine with a regular expression pattern. That coupling process, whether it involves instantiating a object by passing its constructor a regular expression pattern or calling a static method by passing it the regular expression pattern and the string to be analyzed, is by necessity an expensive one. > [!NOTE] -> For a more detailed discussion of the performance implications of using interpreted and compiled regular expressions, see [Optimizing Regular Expression Performance, Part II: Taking Charge of Backtracking](/archive/blogs/bclteam/optimizing-regular-expression-performance-part-ii-taking-charge-of-backtracking-ron-petrusha) in the BCL Team blog. +> For a detailed discussion of the performance implications of using interpreted and compiled regular expressions, see [Optimizing Regular Expression Performance, Part II: Taking Charge of Backtracking](/archive/blogs/bclteam/optimizing-regular-expression-performance-part-ii-taking-charge-of-backtracking-ron-petrusha) in the BCL Team blog. -You can couple the regular expression engine with a particular regular expression pattern and then use the engine to match text in several ways: +You can couple the regular expression engine with a particular regular expression pattern and then use the engine to match the text in several ways: -- You can call a static pattern-matching method, such as . This does not require instantiation of a regular expression object. +- You can call a static pattern-matching method, such as . This method doesn't require instantiation of a regular expression object. -- You can instantiate a object and call an instance pattern-matching method of an interpreted regular expression. This is the default method for binding the regular expression engine to a regular expression pattern. It results when a object is instantiated without an `options` argument that includes the flag. +- You can instantiate a object and call an instance pattern-matching method of an interpreted regular expression, which is the default method for binding the regular expression engine to a regular expression pattern. It results when a object is instantiated without an `options` argument that includes the flag. - You can instantiate a object and call an instance pattern-matching method of a compiled regular expression. Regular expression objects represent compiled patterns when a object is instantiated with an `options` argument that includes the flag. -- You can create a special-purpose object that is tightly coupled with a particular regular expression pattern, compile it, and save it to a standalone assembly. You do this by calling the method. +- You can create a special-purpose object that's tightly coupled with a particular regular expression pattern, compile it, and save it to a standalone assembly. You can call the method to compile and save it. -The particular way in which you call regular expression matching methods can have a significant impact on your application. The following sections discuss when to use static method calls, interpreted regular expressions, and compiled regular expressions to improve your application's performance. +The particular way in which you call regular expression matching methods can affect your application's performance. The following sections discuss when to use static method calls, interpreted regular expressions, and compiled regular expressions to improve your application's performance. > [!IMPORTANT] > The form of the method call (static, interpreted, compiled) affects performance if the same regular expression is used repeatedly in method calls, or if an application makes extensive use of regular expression objects. @@ -79,123 +80,126 @@ The particular way in which you call regular expression matching methods can hav Static regular expression methods are recommended as an alternative to repeatedly instantiating a regular expression object with the same regular expression. Unlike regular expression patterns used by regular expression objects, either the operation codes or the compiled Microsoft intermediate language (MSIL) from patterns used in static method calls is cached internally by the regular expression engine. -For example, an event handler frequently calls another method to validate user input. This is reflected in the following code, in which a control's event is used to call a method named `IsValidCurrency`, which checks whether the user has entered a currency symbol followed by at least one decimal digit. +For example, an event handler frequently calls another method to validate user input. This example is reflected in the following code, in which a control's event is used to call a method named `IsValidCurrency`, which checks whether the user has entered a currency symbol followed by at least one decimal digit. [!code-csharp[Conceptual.RegularExpressions.BestPractices#2](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.regularexpressions.bestpractices/cs/static1.cs#2)] [!code-vb[Conceptual.RegularExpressions.BestPractices#2](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.regularexpressions.bestpractices/vb/static1.vb#2)] -A very inefficient implementation of the `IsValidCurrency` method is shown in the following example. Note that each method call reinstantiates a object with the same pattern. This, in turn, means that the regular expression pattern must be recompiled each time the method is called. +An inefficient implementation of the `IsValidCurrency` method is shown in the following example: + +> [!NOTE] +> Each method call reinstantiates a object with the same pattern. This, in turn, means that the regular expression pattern must be recompiled each time the method is called. [!code-csharp[Conceptual.RegularExpressions.BestPractices#3](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.regularexpressions.bestpractices/cs/static1.cs#3)] [!code-vb[Conceptual.RegularExpressions.BestPractices#3](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.regularexpressions.bestpractices/vb/static1.vb#3)] -You should replace this inefficient code with a call to the static method. This eliminates the need to instantiate a object each time you want to call a pattern-matching method, and enables the regular expression engine to retrieve a compiled version of the regular expression from its cache. +You should replace the preceding inefficient code with a call to the static method. This approach eliminates the need to instantiate a object each time you want to call a pattern-matching method, and enables the regular expression engine to retrieve a compiled version of the regular expression from its cache. [!code-csharp[Conceptual.RegularExpressions.BestPractices#4](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.regularexpressions.bestpractices/cs/static2.cs#4)] [!code-vb[Conceptual.RegularExpressions.BestPractices#4](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.regularexpressions.bestpractices/vb/static2.vb#4)] By default, the last 15 most recently used static regular expression patterns are cached. For applications that require a larger number of cached static regular expressions, the size of the cache can be adjusted by setting the property. -The regular expression `\p{Sc}+\s*\d+` that is used in this example verifies that the input string consists of a currency symbol and at least one decimal digit. The pattern is defined as shown in the following table. +The regular expression `\p{Sc}+\s*\d+` that's used in this example verifies that the input string has a currency symbol and at least one decimal digit. The pattern is defined as shown in the following table: |Pattern|Description| |-------------|-----------------| -|`\p{Sc}+`|Match one or more characters in the Unicode Symbol, Currency category.| -|`\s*`|Match zero or more white-space characters.| -|`\d+`|Match one or more decimal digits.| +|`\p{Sc}+`|Matches one or more characters in the Unicode Symbol, Currency category.| +|`\s*`|Matches zero or more white-space characters.| +|`\d+`|Matches one or more decimal digits.| ### Interpreted vs. compiled regular expressions -Regular expression patterns that are not bound to the regular expression engine through the specification of the option are interpreted. When a regular expression object is instantiated, the regular expression engine converts the regular expression to a set of operation codes. When an instance method is called, the operation codes are converted to MSIL and executed by the JIT compiler. Similarly, when a static regular expression method is called and the regular expression cannot be found in the cache, the regular expression engine converts the regular expression to a set of operation codes and stores them in the cache. It then converts these operation codes to MSIL so that the JIT compiler can execute them. Interpreted regular expressions reduce startup time at the cost of slower execution time. Because of this, they are best used when the regular expression is used in a small number of method calls, or if the exact number of calls to regular expression methods is unknown but is expected to be small. As the number of method calls increases, the performance gain from reduced startup time is outstripped by the slower execution speed. +Regular expression patterns that aren't bound to the regular expression engine through the specification of the option are interpreted. When a regular expression object is instantiated, the regular expression engine converts the regular expression to a set of operation codes. When an instance method is called, the operation codes are converted to MSIL and executed by the JIT compiler. Similarly, when a static regular expression method is called and the regular expression can't be found in the cache, the regular expression engine converts the regular expression to a set of operation codes and stores them in the cache. It then converts these operation codes to MSIL so that the JIT compiler can execute them. Interpreted regular expressions reduce startup time at the cost of slower execution time. Because of this process, they're best used when the regular expression is used in a small number of method calls, or if the exact number of calls to regular expression methods is unknown but is expected to be small. As the number of method calls increases, the performance gain from reduced startup time is outstripped by the slower execution speed. -Regular expression patterns that are bound to the regular expression engine through the specification of the option are compiled. This means that, when a regular expression object is instantiated, or when a static regular expression method is called and the regular expression cannot be found in the cache, the regular expression engine converts the regular expression to an intermediary set of operation codes, which it then converts to MSIL. When a method is called, the JIT compiler executes the MSIL. In contrast to interpreted regular expressions, compiled regular expressions increase startup time but execute individual pattern-matching methods faster. As a result, the performance benefit that results from compiling the regular expression increases in proportion to the number of regular expression methods called. +Regular expression patterns that are bound to the regular expression engine through the specification of the option are compiled. Therefore, when a regular expression object is instantiated, or when a static regular expression method is called and the regular expression can't be found in the cache, the regular expression engine converts the regular expression to an intermediary set of operation codes. These codes are then converted to MSIL. When a method is called, the JIT compiler executes the MSIL. In contrast to interpreted regular expressions, compiled regular expressions increase startup time but execute individual pattern-matching methods faster. As a result, the performance benefit that results from compiling the regular expression increases in proportion to the number of regular expression methods called. -To summarize, we recommend that you use interpreted regular expressions when you call regular expression methods with a specific regular expression relatively infrequently. You should use compiled regular expressions when you call regular expression methods with a specific regular expression relatively frequently. The exact threshold at which the slower execution speeds of interpreted regular expressions outweigh gains from their reduced startup time, or the threshold at which the slower startup times of compiled regular expressions outweigh gains from their faster execution speeds, is difficult to determine. It depends on a variety of factors, including the complexity of the regular expression and the specific data that it processes. To determine whether interpreted or compiled regular expressions offer the best performance for your particular application scenario, you can use the class to compare their execution times. +To summarize, we recommend that you use interpreted regular expressions when you call regular expression methods with a specific regular expression relatively infrequently. You should use compiled regular expressions when you call regular expression methods with a specific regular expression relatively frequently. It's difficult to determine the exact threshold at which the slower execution speeds of interpreted regular expressions outweigh gains from their reduced startup time, or the threshold at which the slower startup times of compiled regular expressions outweigh gains from their faster execution speeds. It depends on various factors, including the complexity of the regular expression and the specific data that it processes. To determine whether interpreted or compiled regular expressions offer the best performance for your particular application scenario, you can use the class to compare their execution times. -The following example compares the performance of compiled and interpreted regular expressions when reading the first ten sentences and when reading all the sentences in the text of Theodore Dreiser's *The Financier*. As the output from the example shows, when only ten calls are made to regular expression matching methods, an interpreted regular expression offers better performance than a compiled regular expression. However, a compiled regular expression offers better performance when a large number of calls (in this case, over 13,000) are made. +The following example compares the performance of compiled and interpreted regular expressions when reading the first 10 sentences and when reading all the sentences in the text of Theodore Dreiser's *The Financier*. As the output from the example shows, when only 10 calls are made to regular expression matching methods, an interpreted regular expression offers better performance than a compiled regular expression. However, a compiled regular expression offers better performance when a large number of calls (in this case, over 13,000) are made. [!code-csharp[Conceptual.RegularExpressions.BestPractices#5](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.regularexpressions.bestpractices/cs/compare1.cs#5)] [!code-vb[Conceptual.RegularExpressions.BestPractices#5](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.regularexpressions.bestpractices/vb/compare1.vb#5)] -The regular expression pattern used in the example, `\b(\w+((\r?\n)|,?\s))*\w+[.?:;!]`, is defined as shown in the following table. +The regular expression pattern used in the example, `\b(\w+((\r?\n)|,?\s))*\w+[.?:;!]`, is defined as shown in the following table: |Pattern|Description| |-------------|-----------------| |`\b`|Begin the match at a word boundary.| -|`\w+`|Match one or more word characters.| -|(\r?\n)|,?\s)|Match either zero or one carriage return followed by a newline character, or zero or one comma followed by a white-space character.| -|(\w+((\r?\n)|,?\s))*|Match zero or more occurrences of one or more word characters that are followed either by zero or one carriage return and a newline character, or by zero or one comma followed by a white-space character.| -|`\w+`|Match one or more word characters.| -|`[.?:;!]`|Match a period, question mark, colon, semicolon, or exclamation point.| +|`\w+`|Matches one or more word characters.| +|(\r?\n)|,?\s)|Matches either zero or one carriage return followed by a newline character, or zero or one comma followed by a white-space character.| +|(\w+((\r?\n)|,?\s))*|Matches zero or more occurrences of one or more word characters that are followed either by zero or one carriage return and a newline character, or by zero or one comma followed by a white-space character.| +|`\w+`|Matches one or more word characters.| +|`[.?:;!]`|Matches a period, question mark, colon, semicolon, or exclamation point.| ### Regular expressions: Compiled to an assembly -.NET also enables you to create an assembly that contains compiled regular expressions. This moves the performance hit of regular expression compilation from run time to design time. However, it also involves some additional work: You must define the regular expressions in advance and compile them to an assembly. The compiler can then reference this assembly when compiling source code that uses the assembly's regular expressions. Each compiled regular expression in the assembly is represented by a class that derives from . +.NET also enables you to create an assembly that contains compiled regular expressions. This capability moves the performance hit of regular expression compilation from run time to design time. However, it also involves some additional work. You must define the regular expressions in advance and compile them to an assembly. The compiler can then reference this assembly when compiling source code that uses the assembly's regular expressions. Each compiled regular expression in the assembly is represented by a class that derives from . -To compile regular expressions to an assembly, you call the method and pass it an array of objects that represent the regular expressions to be compiled, and an object that contains information about the assembly to be created. +To compile regular expressions to an assembly, you call the method and pass it an array of objects and an object. The objects represent the regular expressions to be compiled, and the object that contains information about the assembly to be created. We recommend that you compile regular expressions to an assembly in the following situations: -- If you are a component developer who wants to create a library of reusable regular expressions. +- If you're a component developer who wants to create a library of reusable regular expressions. -- If you expect your regular expression's pattern-matching methods to be called an indeterminate number of times -- anywhere from once or twice to thousands or tens of thousands of times. Unlike compiled or interpreted regular expressions, regular expressions that are compiled to separate assemblies offer performance that is consistent regardless of the number of method calls. +- If you expect your regular expression's pattern-matching methods to be called an indeterminate number of times—anywhere from once or twice to thousands or tens of thousands of times. Unlike compiled or interpreted regular expressions, regular expressions that are compiled to separate assemblies offer performance that's consistent regardless of the number of method calls. -If you are using compiled regular expressions to optimize performance, you should not use reflection to create the assembly, load the regular expression engine, and execute its pattern-matching methods. This requires that you avoid building regular expression patterns dynamically, and that you specify any pattern-matching options (such as case-insensitive pattern matching) at the time the assembly is created. It also requires that you separate the code that creates the assembly from the code that uses the regular expression. +If you're using compiled regular expressions to optimize performance, you shouldn't use reflection to create the assembly, load the regular expression engine, and execute its pattern-matching methods. Avoiding reflection requires that you don't build regular expression patterns dynamically, and that you specify any pattern-matching options, such as case-insensitive pattern matching, at the time the assembly is created. It also requires that you separate the code that creates the assembly from the code that uses the regular expression. -The following example shows how to create an assembly that contains a compiled regular expression. It creates an assembly named `RegexLib.dll` with a single regular expression class, `SentencePattern`, that contains the sentence-matching regular expression pattern used in the [Interpreted vs. Compiled Regular Expressions](#interpreted-vs-compiled-regular-expressions) section. +The following example shows how to create an assembly that contains a compiled regular expression. It creates an assembly named `RegexLib.dll` with a single regular expression class, `SentencePattern`. This class contains the sentence-matching regular expression pattern used in the [Interpreted vs. Compiled Regular Expressions](#interpreted-vs-compiled-regular-expressions) section. [!code-csharp[Conceptual.RegularExpressions.BestPractices#6](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.regularexpressions.bestpractices/cs/compile1.cs#6)] [!code-vb[Conceptual.RegularExpressions.BestPractices#6](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.regularexpressions.bestpractices/vb/compile1.vb#6)] -When the example is compiled to an executable and run, it creates an assembly named `RegexLib.dll`. The regular expression is represented by a class named `Utilities.RegularExpressions.SentencePattern` that is derived from . The following example then uses the compiled regular expression to extract the sentences from the text of Theodore Dreiser's *The Financier*. +When the example is compiled to an executable and run, it creates an assembly named `RegexLib.dll`. A `Utilities.RegularExpressions.SentencePattern` class derived from represents the regular expression. The following example then uses the compiled regular expression to extract the sentences from the text of Theodore Dreiser's *The Financier*: [!code-csharp[Conceptual.RegularExpressions.BestPractices#7](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.regularexpressions.bestpractices/cs/compile2.cs#7)] [!code-vb[Conceptual.RegularExpressions.BestPractices#7](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.regularexpressions.bestpractices/vb/compile2.vb#7)] ## Take charge of backtracking -Ordinarily, the regular expression engine uses linear progression to move through an input string and compare it to a regular expression pattern. However, when indeterminate quantifiers such as `*`, `+`, and `?` are used in a regular expression pattern, the regular expression engine may give up a portion of successful partial matches and return to a previously saved state in order to search for a successful match for the entire pattern. This process is known as backtracking. +Ordinarily, the regular expression engine uses linear progression to move through an input string and compare it to a regular expression pattern. However, when indeterminate quantifiers such as `*`, `+`, and `?` are used in a regular expression pattern, the regular expression engine might give up a portion of successful partial matches and return to a previously saved state in order to search for a successful match for the entire pattern. This process is known as backtracking. > [!NOTE] > For more information on backtracking, see [Details of Regular Expression Behavior](details-of-regular-expression-behavior.md) and [Backtracking](backtracking-in-regular-expressions.md). For a detailed discussion of backtracking, see [Optimizing Regular Expression Performance, Part II: Taking Charge of Backtracking](/archive/blogs/bclteam/optimizing-regular-expression-performance-part-ii-taking-charge-of-backtracking-ron-petrusha) in the BCL Team blog. -Support for backtracking gives regular expressions power and flexibility. It also places the responsibility for controlling the operation of the regular expression engine in the hands of regular expression developers. Because developers are often not aware of this responsibility, their misuse of backtracking or reliance on excessive backtracking often plays the most significant role in degrading regular expression performance. In a worst-case scenario, execution time can double for each additional character in the input string. In fact, by using backtracking excessively, it is easy to create the programmatic equivalent of an endless loop if input nearly matches the regular expression pattern; the regular expression engine may take hours or even days to process a relatively short input string. +Support for backtracking gives regular expressions power and flexibility. It also places the responsibility for controlling the operation of the regular expression engine in the hands of regular expression developers. Because developers are often not aware of this responsibility, their misuse of backtracking or reliance on excessive backtracking often plays the most significant role in degrading regular expression performance. In a worst-case scenario, execution time can double for each additional character in the input string. In fact, by using backtracking excessively, it's easy to create the programmatic equivalent of an endless loop if input nearly matches the regular expression pattern. The regular expression engine might take hours or even days to process a relatively short input string. -Often, applications pay a performance penalty for using backtracking despite the fact that backtracking is not essential for a match. For example, the regular expression `\b\p{Lu}\w*\b` matches all words that begin with an uppercase character, as the following table shows. +Often, applications pay a performance penalty for using backtracking even though backtracking isn't essential for a match. For example, the regular expression `\b\p{Lu}\w*\b` matches all words that begin with an uppercase character, as the following table shows: |Pattern|Description| |-|-| |`\b`|Begin the match at a word boundary.| -|`\p{Lu}`|Match an uppercase character.| -|`\w*`|Match zero or more word characters.| +|`\p{Lu}`|Matches an uppercase character.| +|`\w*`|Matches zero or more word characters.| |`\b`|End the match at a word boundary.| -Because a word boundary is not the same as, or a subset of, a word character, there is no possibility that the regular expression engine will cross a word boundary when matching word characters. This means that for this regular expression, backtracking can never contribute to the overall success of any match -- it can only degrade performance, because the regular expression engine is forced to save its state for each successful preliminary match of a word character. +Because a word boundary isn't the same as, or a subset of, a word character, there's no possibility that the regular expression engine will cross a word boundary when matching word characters. Therefore for this regular expression, backtracking can never contribute to the overall success of any match. It can only degrade performance because the regular expression engine is forced to save its state for each successful preliminary match of a word character. -If you determine that backtracking is not necessary, you can disable it by using the `(?>subexpression)` language element, known as an atomic group. The following example parses an input string by using two regular expressions. The first, `\b\p{Lu}\w*\b`, relies on backtracking. The second, `\b\p{Lu}(?>\w*)\b`, disables backtracking. As the output from the example shows, they both produce the same result. +If you determine that backtracking isn't necessary, you can disable it by using the `(?>subexpression)` language element, known as an atomic group. The following example parses an input string by using two regular expressions. The first, `\b\p{Lu}\w*\b`, relies on backtracking. The second, `\b\p{Lu}(?>\w*)\b`, disables backtracking. As the output from the example shows, they both produce the same result: [!code-csharp[Conceptual.RegularExpressions.BestPractices#10](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.regularexpressions.bestpractices/cs/backtrack2.cs#10)] [!code-vb[Conceptual.RegularExpressions.BestPractices#10](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.regularexpressions.bestpractices/vb/backtrack2.vb#10)] -In many cases, backtracking is essential for matching a regular expression pattern to input text. However, excessive backtracking can severely degrade performance and create the impression that an application has stopped responding. In particular, this happens when quantifiers are nested and the text that matches the outer subexpression is a subset of the text that matches the inner subexpression. +In many cases, backtracking is essential for matching a regular expression pattern to input text. However, excessive backtracking can severely degrade performance and create the impression that an application has stopped responding. In particular, this problem arises when quantifiers are nested and the text that matches the outer subexpression is a subset of the text that matches the inner subexpression. > [!WARNING] -> In addition to avoiding excessive backtracking, you should use the timeout feature to ensure that excessive backtracking does not severely degrade regular expression performance. For more information, see the [Use Time-out Values](#use-time-out-values) section. +> In addition to avoiding excessive backtracking, you should use the timeout feature to ensure that excessive backtracking doesn't severely degrade regular expression performance. For more information, see the [Use Time-out Values](#use-time-out-values) section. -For example, the regular expression pattern `^[0-9A-Z]([-.\w]*[0-9A-Z])*\$$` is intended to match a part number that consists of at least one alphanumeric character. Any additional characters can consist of an alphanumeric character, a hyphen, an underscore, or a period, though the last character must be alphanumeric. A dollar sign terminates the part number. In some cases, this regular expression pattern can exhibit extremely poor performance because quantifiers are nested, and because the subexpression `[0-9A-Z]` is a subset of the subexpression `[-.\w]*`. +For example, the regular expression pattern `^[0-9A-Z]([-.\w]*[0-9A-Z])*\$$` is intended to match a part number that consists of at least one alphanumeric character. Any additional characters can consist of an alphanumeric character, a hyphen, an underscore, or a period, though the last character must be alphanumeric. A dollar sign terminates the part number. In some cases, this regular expression pattern can exhibit poor performance because quantifiers are nested, and because the subexpression `[0-9A-Z]` is a subset of the subexpression `[-.\w]*`. -In these cases, you can optimize regular expression performance by removing the nested quantifiers and replacing the outer subexpression with a zero-width lookahead or lookbehind assertion. Lookahead and lookbehind assertions are anchors; they do not move the pointer in the input string, but instead look ahead or behind to check whether a specified condition is met. For example, the part number regular expression can be rewritten as `^[0-9A-Z][-.\w]*(?<=[0-9A-Z])\$$`. This regular expression pattern is defined as shown in the following table. +In these cases, you can optimize regular expression performance by removing the nested quantifiers and replacing the outer subexpression with a zero-width lookahead or lookbehind assertion. Lookahead and lookbehind assertions are anchors. They don't move the pointer in the input string but instead look ahead or behind to check whether a specified condition is met. For example, the part number regular expression can be rewritten as `^[0-9A-Z][-.\w]*(?<=[0-9A-Z])\$$`. This regular expression pattern is defined as shown in the following table: -|Pattern|Description| -|-------------|-----------------| -|`^`|Begin the match at the beginning of the input string.| -|`[0-9A-Z]`|Match an alphanumeric character. The part number must consist of at least this character.| -|`[-.\w]*`|Match zero or more occurrences of any word character, hyphen, or period.| -|`\$`|Match a dollar sign.| -|`(?<=[0-9A-Z])`|Look behind of the ending dollar sign to ensure that the previous character is alphanumeric.| -|`$`|End the match at the end of the input string.| +| Pattern | Description | +|-----------------|-------------------------------------------------------------------------------------------| +| `^` | Begin the match at the beginning of the input string. | +| `[0-9A-Z]` | Match an alphanumeric character. The part number must consist of at least this character. | +| `[-.\w]*` | Match zero or more occurrences of any word character, hyphen, or period. | +| `\$` | Match a dollar sign. | +| `(?<=[0-9A-Z])` | Look behind the ending dollar sign to ensure that the previous character is alphanumeric. | +| `$` | End the match at the end of the input string. | -The following example illustrates the use of this regular expression to match an array containing possible part numbers. +The following example illustrates the use of this regular expression to match an array containing possible part numbers: [!code-csharp[Conceptual.RegularExpressions.BestPractices#11](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.regularexpressions.bestpractices/cs/backtrack4.cs#11)] [!code-vb[Conceptual.RegularExpressions.BestPractices#11](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.regularexpressions.bestpractices/vb/backtrack4.vb#11)] @@ -204,62 +208,62 @@ The regular expression language in .NET includes the following language elements |Language element|Description| |----------------------|-----------------| -|`(?=` `subexpression` `)`|Zero-width positive lookahead. Look ahead of the current position to determine whether `subexpression` matches the input string.| -|`(?!` `subexpression` `)`|Zero-width negative lookahead. Look ahead of the current position to determine whether `subexpression` does not match the input string.| -|`(?<=` `subexpression` `)`|Zero-width positive lookbehind. Look behind the current position to determine whether `subexpression` matches the input string.| -|`(?, which means that the regular expression will not time out. You can override this value and define a time-out interval as follows: +The regular expression time-out interval defines the period of time that the regular expression engine will look for a single match before it times out. Depending on the regular expression pattern and the input text, the execution time might exceed the specified time-out interval, but it won't spend more time backtracking than the specified time-out interval. The default time-out interval is , which means that the regular expression won't time out. You can override this value and define a time-out interval as follows: -- By providing a time-out value when you instantiate a object by calling the constructor. +- Call the constructor to provide a time-out value when you instantiate a object. -- By calling a static pattern matching method, such as or , that includes a `matchTimeout` parameter. +- Call a static pattern matching method, such as or , that includes a `matchTimeout` parameter. -- For compiled regular expressions that are created by calling the method, by calling the constructor that has a parameter of type . +- Call the constructor that has a parameter of type for compiled regular expressions that are created by calling the method. -- By setting a process-wide or AppDomain-wide value with code such as `AppDomain.CurrentDomain.SetData("REGEX_DEFAULT_MATCH_TIMEOUT", TimeSpan.FromMilliseconds(100));`. +- Set a process-wide or AppDomain-wide value with code such as `AppDomain.CurrentDomain.SetData("REGEX_DEFAULT_MATCH_TIMEOUT", TimeSpan.FromMilliseconds(100));`. -If you have defined a time-out interval and a match is not found at the end of that interval, the regular expression method throws a exception. In your exception handler, you can choose to retry the match with a longer time-out interval, abandon the match attempt and assume that there is no match, or abandon the match attempt and log the exception information for future analysis. +If you've defined a time-out interval and a match isn't found at the end of that interval, the regular expression method throws a exception. In your exception handler, you can choose to retry the match with a longer time-out interval, abandon the match attempt and assume that there's no match, or abandon the match attempt and log the exception information for future analysis. -The following example defines a `GetWordData` method that instantiates a regular expression with a time-out interval of 350 milliseconds to calculate the number of words and average number of characters in a word in a text document. If the matching operation times out, the time-out interval is increased by 350 milliseconds and the object is re-instantiated. If the new time-out interval exceeds 1 second, the method re-throws the exception to the caller. +The following example defines a `GetWordData` method that instantiates a regular expression with a time-out interval of 350 milliseconds to calculate the number of words and average number of characters in a word in a text document. If the matching operation times out, the time-out interval is increased by 350 milliseconds and the object is reinstantiated. If the new time-out interval exceeds one second, the method rethrows the exception to the caller. [!code-csharp[Conceptual.RegularExpressions.BestPractices#12](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.regularexpressions.bestpractices/cs/timeout1.cs#12)] [!code-vb[Conceptual.RegularExpressions.BestPractices#12](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.regularexpressions.bestpractices/vb/timeout1.vb#12)] ## Capture only when necessary -Regular expressions in .NET support a number of grouping constructs, which let you group a regular expression pattern into one or more subexpressions. The most commonly used grouping constructs in .NET regular expression language are `(`*subexpression*`)`, which defines a numbered capturing group, and `(?<`*name*`>`*subexpression*`)`, which defines a named capturing group. Grouping constructs are essential for creating backreferences and for defining a subexpression to which a quantifier is applied. +Regular expressions in .NET support grouping constructs, which let you group a regular expression pattern into one or more subexpressions. The most commonly used grouping constructs in .NET regular expression language are `(`*subexpression*`)`, which defines a numbered capturing group, and `(?<`*name*`>`*subexpression*`)`, which defines a named capturing group. Grouping constructs are essential for creating backreferences and for defining a subexpression to which a quantifier is applied. -However, the use of these language elements has a cost. They cause the object returned by the property to be populated with the most recent unnamed or named captures, and if a single grouping construct has captured multiple substrings in the input string, they also populate the object returned by the property of a particular capturing group with multiple objects. +However, the use of these language elements has a cost. They cause the object returned by the property to be populated with the most recent unnamed or named captures. If a single grouping construct has captured multiple substrings in the input string, they also populate the object returned by the property of a particular capturing group with multiple objects. -Often, grouping constructs are used in a regular expression only so that quantifiers can be applied to them, and the groups captured by these subexpressions are not subsequently used. For example, the regular expression `\b(\w+[;,]?\s?)+[.?!]` is designed to capture an entire sentence. The following table describes the language elements in this regular expression pattern and their effect on the object's and collections. +Often, grouping constructs are used in a regular expression only so that quantifiers can be applied to them. The groups captured by these subexpressions aren't used later. For example, the regular expression `\b(\w+[;,]?\s?)+[.?!]` is designed to capture an entire sentence. The following table describes the language elements in this regular expression pattern and their effect on the object's and collections: |Pattern|Description| |-------------|-----------------| |`\b`|Begin the match at a word boundary.| -|`\w+`|Match one or more word characters.| -|`[;,]?`|Match zero or one comma or semicolon.| -|`\s?`|Match zero or one white-space character.| -|`(\w+[;,]?\s?)+`|Match one or more occurrences of one or more word characters followed by an optional comma or semicolon followed by an optional white-space character. This defines the first capturing group, which is necessary so that the combination of multiple word characters (that is, a word) followed by an optional punctuation symbol will be repeated until the regular expression engine reaches the end of a sentence.| -|`[.?!]`|Match a period, question mark, or exclamation point.| +|`\w+`|Matches one or more word characters.| +|`[;,]?`|Matches zero or one comma or semicolon.| +|`\s?`|Matches zero or one white-space character.| +|`(\w+[;,]?\s?)+`|Matches one or more occurrences of one or more word characters followed by an optional comma or semicolon followed by an optional white-space character. This pattern defines the first capturing group, which is necessary so that the combination of multiple word characters (that is, a word) followed by an optional punctuation symbol will be repeated until the regular expression engine reaches the end of a sentence.| +|`[.?!]`|Matches a period, question mark, or exclamation point.| As the following example shows, when a match is found, both the and objects are populated with captures from the match. In this case, the capturing group `(\w+[;,]?\s?)` exists so that the `+` quantifier can be applied to it, which enables the regular expression pattern to match each word in a sentence. Otherwise, it would match the last word in a sentence. [!code-csharp[Conceptual.RegularExpressions.BestPractices#8](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.regularexpressions.bestpractices/cs/group1.cs#8)] [!code-vb[Conceptual.RegularExpressions.BestPractices#8](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.regularexpressions.bestpractices/vb/group1.vb#8)] -When you use subexpressions only to apply quantifiers to them, and you are not interested in the captured text, you should disable group captures. For example, the `(?:subexpression)` language element prevents the group to which it applies from capturing matched substrings. In the following example, the regular expression pattern from the previous example is changed to `\b(?:\w+[;,]?\s?)+[.?!]`. As the output shows, it prevents the regular expression engine from populating the and collections. +When you use subexpressions only to apply quantifiers to them and you aren't interested in the captured text, you should disable group captures. For example, the `(?:subexpression)` language element prevents the group to which it applies from capturing matched substrings. In the following example, the regular expression pattern from the previous example is changed to `\b(?:\w+[;,]?\s?)+[.?!]`. As the output shows, it prevents the regular expression engine from populating the and collections: [!code-csharp[Conceptual.RegularExpressions.BestPractices#9](../../../samples/snippets/csharp/VS_Snippets_CLR/conceptual.regularexpressions.bestpractices/cs/group2.cs#9)] [!code-vb[Conceptual.RegularExpressions.BestPractices#9](../../../samples/snippets/visualbasic/VS_Snippets_CLR/conceptual.regularexpressions.bestpractices/vb/group2.vb#9)] You can disable captures in one of the following ways: -- Use the `(?:subexpression)` language element. This element prevents the capture of matched substrings in the group to which it applies. It does not disable substring captures in any nested groups. +- Use the `(?:subexpression)` language element. This element prevents the capture of matched substrings in the group to which it applies. It doesn't disable substring captures in any nested groups. - Use the option. It disables all unnamed or implicit captures in the regular expression pattern. When you use this option, only substrings that match named groups defined with the `(?subexpression)` language element can be captured. The flag can be passed to the `options` parameter of a class constructor or to the `options` parameter of a static matching method. @@ -267,10 +271,10 @@ You can disable captures in one of the following ways: - Use the `n` option in the `(?imnsx:subexpression)` language element. This option disables all unnamed or implicit captures in `subexpression`. Captures by any unnamed or implicit nested capturing groups are disabled as well. -## Related topics +## Related articles |Title|Description| |-----------|-----------------| -|[Details of Regular Expression Behavior](details-of-regular-expression-behavior.md)|Examines the implementation of the regular expression engine in .NET. The topic focuses on the flexibility of regular expressions and explains the developer's responsibility for ensuring the efficient and robust operation of the regular expression engine.| +|[Details of Regular Expression Behavior](details-of-regular-expression-behavior.md)|Examines the implementation of the regular expression engine in .NET. The article focuses on the flexibility of regular expressions and explains the developer's responsibility for ensuring the efficient and robust operation of the regular expression engine.| |[Backtracking](backtracking-in-regular-expressions.md)|Explains what backtracking is and how it affects regular expression performance, and examines language elements that provide alternatives to backtracking.| |[Regular Expression Language - Quick Reference](regular-expression-language-quick-reference.md)|Describes the elements of the regular expression language in .NET and provides links to detailed documentation for each language element.| diff --git a/docs/standard/base-types/how-to-extract-the-day-of-the-week-from-a-specific-date.md b/docs/standard/base-types/how-to-extract-the-day-of-the-week-from-a-specific-date.md index f3524f33553ee..813ebb04cba74 100644 --- a/docs/standard/base-types/how-to-extract-the-day-of-the-week-from-a-specific-date.md +++ b/docs/standard/base-types/how-to-extract-the-day-of-the-week-from-a-specific-date.md @@ -1,7 +1,8 @@ --- title: "How to: Extract the Day of the Week from a Specific Date" description: Learn how to determine the ordinal day of the week for a particular date in .NET. Learn how to display the localized weekday name for a particular date. -ms.date: "03/30/2017" +ms.date: "08/09/2022" +ms.custom: devdivchpfy22 dev_langs: - "csharp" - "vb" @@ -25,71 +26,71 @@ ms.assetid: 1c9bef76-5634-46cf-b91c-9b9eb72091d7 --- # How to: Extract the Day of the Week from a Specific Date -.NET makes it easy to determine the ordinal day of the week for a particular date, and to display the localized weekday name for a particular date. An enumerated value that indicates the day of the week corresponding to a particular date is available from the or property. In contrast, retrieving the weekday name is a formatting operation that can be performed by calling a formatting method, such as a date and time value's `ToString` method or the method. This topic shows how to perform these formatting operations. +.NET makes it easy to determine the ordinal day of the week for a particular date, and to display the localized weekday name for a particular date. An enumerated value that indicates the day of the week corresponding to a particular date is available from the or property. In contrast, retrieving the weekday name is a formatting operation that can be performed by calling a formatting method, such as a date and time value's `ToString` method or the method. This article shows how to perform these formatting operations. ## Extract a number indicating the day of the week -1. If you are working with the string representation of a date, convert it to a or a value by using the static or method. +1. Use the static or method to convert the string representation of a date to a or a value. -2. Use the or property to retrieve a value that indicates the day of the week. +1. Use the or property to retrieve a value that indicates the day of the week. -3. If necessary, cast (in C#) or convert (in Visual Basic) the value to an integer. +1. If necessary, cast (in C#) or convert (in Visual Basic) the value to an integer. - The following example displays an integer that represents the day of the week of a specific date. + The following example displays an integer that represents the day of the week of a specific date: [!code-csharp[Formatting.Howto.WeekdayName#7](../../../samples/snippets/csharp/VS_Snippets_CLR/Formatting.HowTo.WeekdayName/cs/weekdaynumber7.cs#7)] [!code-vb[Formatting.Howto.WeekdayName#7](../../../samples/snippets/visualbasic/VS_Snippets_CLR/Formatting.HowTo.WeekdayName/vb/weekdaynumber7.vb#7)] ## Extract the abbreviated weekday name -1. If you are working with the string representation of a date, convert it to a or a value by using the static or method. +1. Use the static or method to convert the string representation of a date to a or a value. -2. You can extract the abbreviated weekday name of the current culture or of a specific culture: +1. You can extract the abbreviated weekday name of the current culture or of a specific culture: - 1. To extract the abbreviated weekday name for the current culture, call the date and time value's or instance method, and pass the string "ddd" as the `format` parameter. The following example illustrates the call to the method. + 1. To extract the abbreviated weekday name for the current culture, call the date and time value's or instance method, and pass the string `ddd` as the `format` parameter. The following example illustrates the call to the method: [!code-csharp[Formatting.Howto.WeekdayName#1](../../../samples/snippets/csharp/VS_Snippets_CLR/Formatting.HowTo.WeekdayName/cs/abbrname1.cs#1)] [!code-vb[Formatting.Howto.WeekdayName#1](../../../samples/snippets/visualbasic/VS_Snippets_CLR/Formatting.HowTo.WeekdayName/vb/abbrname1.vb#1)] - 2. To extract the abbreviated weekday name for a specific culture, call the date and time value's or instance method. Pass the string "ddd" as the `format` parameter. Pass either a or a object that represents the culture whose weekday name you want to retrieve as the `provider` parameter. The following code illustrates a call to the method using a object that represents the fr-FR culture. + 1. To extract the abbreviated weekday name for a specific culture, call the date and time value's or instance method. Pass the string `ddd` as the `format` parameter. Pass either a or a object that represents the culture whose weekday name you want to retrieve as the `provider` parameter. The following code illustrates a call to the method using a object that represents the fr-FR culture: [!code-csharp[Formatting.Howto.WeekdayName#2](../../../samples/snippets/csharp/VS_Snippets_CLR/Formatting.HowTo.WeekdayName/cs/abbrname2.cs#2)] [!code-vb[Formatting.Howto.WeekdayName#2](../../../samples/snippets/visualbasic/VS_Snippets_CLR/Formatting.HowTo.WeekdayName/vb/abbrname2.vb#2)] ## Extract the full weekday name -1. If you are working with the string representation of a date, convert it to a or a value by using the static or method. +1. Use the static or method to convert the string representation of a date to a or a value. -2. You can extract the full weekday name of the current culture or of a specific culture: +1. You can extract the full weekday name of the current culture or of a specific culture: - 1. To extract the weekday name for the current culture, call the date and time value's or instance method, and pass the string "dddd" as the `format` parameter. The following example illustrates the call to the method. + 1. To extract the weekday name for the current culture, call the date and time value's or instance method, and pass the string `dddd` as the `format` parameter. The following example illustrates the call to the method: [!code-csharp[Formatting.Howto.WeekdayName#4](../../../samples/snippets/csharp/VS_Snippets_CLR/Formatting.HowTo.WeekdayName/cs/fullname4.cs#4)] [!code-vb[Formatting.Howto.WeekdayName#4](../../../samples/snippets/visualbasic/VS_Snippets_CLR/Formatting.HowTo.WeekdayName/vb/fullname4.vb#4)] - 2. To extract the weekday name for a specific culture, call the date and time value's or instance method. Pass the string "dddd" as the `format` parameter. Pass either a or a object that represents the culture whose weekday name you want to retrieve as the `provider` parameter. The following code illustrates a call to the method using a object that represents the es-ES culture. + 1. To extract the weekday name for a specific culture, call the date and time value's or instance method. Pass the string `dddd` as the `format` parameter. Pass either a or a object that represents the culture whose weekday name you want to retrieve as the `provider` parameter. The following code illustrates a call to the method using a object that represents the es-ES culture: [!code-csharp[Formatting.Howto.WeekdayName#5](../../../samples/snippets/csharp/VS_Snippets_CLR/Formatting.HowTo.WeekdayName/cs/fullname5.cs#5)] [!code-vb[Formatting.Howto.WeekdayName#5](../../../samples/snippets/visualbasic/VS_Snippets_CLR/Formatting.HowTo.WeekdayName/vb/fullname5.vb#5)] ## Example - The example illustrates calls to the and properties and the and methods to retrieve the number that represents the day of the week, the abbreviated weekday name, and the full weekday name for a particular date. + The following example illustrates calls to the and properties to retrieve the number that represents the day of the week for a particular date. It also includes calls to the and methods to extract the abbreviated weekday name and the full weekday name. [!code-csharp[Formatting.Howto.WeekdayName#6](../../../samples/snippets/csharp/VS_Snippets_CLR/Formatting.HowTo.WeekdayName/cs/example6.cs#6)] [!code-vb[Formatting.Howto.WeekdayName#6](../../../samples/snippets/visualbasic/VS_Snippets_CLR/Formatting.HowTo.WeekdayName/vb/example6.vb#6)] - Individual languages may provide functionality that duplicates or supplements the functionality provided by .NET. For example, Visual Basic includes two such functions: + Individual languages might provide functionality that duplicates or supplements the functionality provided by .NET. For example, Visual Basic includes two such functions: - `Weekday`, which returns a number that indicates the day of the week of a particular date. It considers the ordinal value of the first day of the week to be one, whereas the property considers it to be zero. - `WeekdayName`, which returns the name of the week in the current culture that corresponds to a particular weekday number. - The following example illustrates the use of the Visual Basic `Weekday` and `WeekdayName` functions. + The following example illustrates the use of the Visual Basic `Weekday` and `WeekdayName` functions: [!code-vb[Formatting.HowTo.WeekdayName#9](../../../samples/snippets/visualbasic/VS_Snippets_CLR/Formatting.HowTo.WeekdayName/vb/example9.vb#9)] - You can also use the value returned by the property to retrieve the weekday name of a particular date. This requires only a call to the method on the value returned by the property. However, this technique does not produce a localized weekday name for the current culture, as the following example illustrates. + You can also use the value returned by the property to retrieve the weekday name of a particular date. This process requires only a call to the method on the value returned by the property. However, this technique doesn't produce a localized weekday name for the current culture, as the following example illustrates: [!code-csharp[Formatting.HowTo.WeekdayName#8](../../../samples/snippets/csharp/VS_Snippets_CLR/Formatting.HowTo.WeekdayName/cs/Howto1.cs#8)] [!code-vb[Formatting.HowTo.WeekdayName#8](../../../samples/snippets/visualbasic/VS_Snippets_CLR/Formatting.HowTo.WeekdayName/vb/Howto1.vb#8)] diff --git a/docs/standard/datetime/system-text-json-support.md b/docs/standard/datetime/system-text-json-support.md index 3222e17992fa1..e97265844d5d4 100644 --- a/docs/standard/datetime/system-text-json-support.md +++ b/docs/standard/datetime/system-text-json-support.md @@ -3,7 +3,8 @@ title: DateTime and DateTimeOffset support in System.Text.Json description: An overview of how DateTime and DateTimeOffset types are supported in the System.Text.Json library. author: layomia ms.author: laakinri -ms.date: 07/22/2019 +ms.date: 08/09/2022 +ms.custom: devdivchpfy22 helpviewer_keywords: - "JSON, Serializer, Utf8" - "JSON DateTime, JSON DateTimeOffset" @@ -15,21 +16,20 @@ helpviewer_keywords: --- # DateTime and DateTimeOffset support in System.Text.Json -The System.Text.Json library parses and writes and values according to the ISO 8601-1:2019 extended profile. -[Converters](xref:System.Text.Json.Serialization.JsonConverter%601) provide custom support for serializing and deserializing with . -Custom support can also be implemented when using and . +The `System.Text.Json` library parses and writes and values according to the ISO 8601-1:2019 extended profile. +[Converters](xref:System.Text.Json.Serialization.JsonConverter%601) provide custom support for serializing and deserializing with . You can also use and to implement custom support. ## Support for the ISO 8601-1:2019 format The , , , and types parse and write and -text representations according to the extended profile of the ISO 8601-1:2019 format; for example, 2019-07-26T16:59:57-05:00. +text representations according to the extended profile of the ISO 8601-1:2019 format. For example, `2019-07-26T16:59:57-05:00`. and data can be serialized with : :::code language="csharp" source="snippets/system-text-json-support/csharp/serializing-with-jsonserializer/Program.cs"::: -They can also be deserialized with : + and can also be deserialized with : :::code language="csharp" source="snippets/system-text-json-support/csharp/deserializing-with-jsonserializer-valid/Program.cs"::: @@ -39,13 +39,12 @@ Attempting to deserialize representations that don't conform to the profile will :::code language="csharp" source="snippets/system-text-json-support/csharp/deserializing-with-jsonserializer-error/Program.cs"::: The provides structured access to the contents of a JSON payload, including -and representations. The example below shows how, when given a collection of temperatures, the average -temperature on Mondays can be calculated: +and representations. The following example shows how to calculate the average +temperature on Mondays from a collection of temperatures: :::code language="csharp" source="snippets/system-text-json-support/csharp/computing-with-jsondocument-valid/Program.cs"::: -Attempting to compute the average temperature given a payload with non-compliant representations will cause -to throw a : +Attempting to compute the average temperature given a payload with non-compliant representations will cause to throw a : :::code language="csharp" source="snippets/system-text-json-support/csharp/computing-with-jsondocument-error/Program.cs"::: @@ -65,22 +64,18 @@ Attempting to read non-compliant formats with -If you want the serializer to perform custom parsing or formatting, you can implement -[custom converters](xref:System.Text.Json.Serialization.JsonConverter%601). +If you want the serializer to perform custom parsing or formatting, you can implement [custom converters](xref:System.Text.Json.Serialization.JsonConverter%601). Here are a few examples: -#### Using `DateTime(Offset).Parse` and `DateTime(Offset).ToString` +#### Using DateTime(Offset).Parse and DateTime(Offset).ToString -If you can't determine the formats of your input or text representations, you can use the -`DateTime(Offset).Parse` method in your converter read logic. This allows you to use .NET's extensive support for parsing various - and text formats, including non-ISO 8601 strings and ISO 8601 formats that don't conform to -the extended ISO 8601-1:2019 profile. This approach is significantly less performant than using the serializer's native implementation. +If you can't determine the formats of your input or text representations, you can use the `DateTime(Offset).Parse` method in your converter read logic. +This method allows you to use .NET's extensive support for parsing various and text formats, including non-ISO 8601 strings and ISO 8601 formats that don't conform to the extended ISO 8601-1:2019 profile. +This approach is less performant than using the serializer's native implementation. -For serializing, you can use the `DateTime(Offset).ToString` method in your converter write logic. This allows you to write -and values using any of the -[standard date and time formats](../base-types/standard-date-and-time-format-strings.md), and the -[custom date and time formats](../base-types/custom-date-and-time-format-strings.md). -This is also significantly less performant than using the serializer's native implementation. +For serializing, you can use the `DateTime(Offset).ToString` method in your converter write logic. +This method allows you to write and values using any of the [standard date and time formats](../base-types/standard-date-and-time-format-strings.md), and the [custom date and time formats](../base-types/custom-date-and-time-format-strings.md). +This approach is also less performant than using the serializer's native implementation. :::code language="csharp" source="snippets/system-text-json-support/csharp/datetime-converter-examples/example1/Program.cs"::: @@ -92,25 +87,25 @@ The parameter is useful for handling polymorphic cases and when using generics t You can use fast UTF-8-based parsing and formatting methods in your converter logic if your input or text representations are compliant with one of the "R", "l", "O", or "G" -[standard date and time format strings](../base-types/standard-date-and-time-format-strings.md), -or you want to write according to one of these formats. This is much faster than using `DateTime(Offset).Parse` and `DateTime(Offset).ToString`. + [standard date and time format strings](../base-types/standard-date-and-time-format-strings.md), +or you want to write according to one of these formats. This approach is much faster than using s`DateTime(Offset).Parse` and `DateTime(Offset).ToString`. -This example shows a custom converter that serializes and deserializes values according to -[the "R" standard format](../base-types/standard-date-and-time-format-strings.md#the-rfc1123-r-r-format-specifier): +The following example shows a custom converter that serializes and deserializes values according to + [the "R" standard format](../base-types/standard-date-and-time-format-strings.md#the-rfc1123-r-r-format-specifier): :::code language="csharp" source="snippets/system-text-json-support/csharp/datetime-converter-examples/example2/Program.cs"::: > [!NOTE] > The "R" standard format will always be 29 characters long. > -> The "l" (lowercase "L") format is not documented with the other [standard date and time format strings](../base-types/standard-date-and-time-format-strings.md) because it is supported only by the `Utf8Parser` and `Utf8Formatter` types. The format is lowercase RFC 1123 (a lowercase version of the "R" format), for example: "thu, 25 jul 2019 06:36:07 gmt". +> The "l" (lowercase "L") format isn't documented with the other [standard date and time format strings](../base-types/standard-date-and-time-format-strings.md) because it's supported only by the `Utf8Parser` and `Utf8Formatter` types. The format is lowercase RFC 1123 (a lowercase version of the "R" format). For example, "thu, 25 jul 2019 06:36:07 gmt". -#### Using `DateTime(Offset).Parse` as a fallback to the serializer's native parsing +#### Using DateTime(Offset).Parse as a fallback to the serializer's native parsing If you generally expect your input or data to conform to the extended ISO 8601-1:2019 profile, -you can use the serializer's native parsing logic. You can also implement a fallback mechanism just in case. -This example shows that, after failing to parse a text representation using , -the converter successfully parses the data using . +you can use the serializer's native parsing logic. You can also implement a fallback mechanism. +The following example shows that, after failing to parse a text representation using , +the converter successfully parses the data using : :::code language="csharp" source="snippets/system-text-json-support/csharp/datetime-converter-examples/example3/Program.cs"::: @@ -129,18 +124,17 @@ you can format your custom representation to a , `ReadOnlySp then pass it to the corresponding or method. -The following example shows how a custom format can be created with , -then written with the method: +The following example shows how a custom format can be created with +and then written with the method: :::code language="csharp" source="snippets/system-text-json-support/csharp/custom-writing-with-utf8jsonwriter/Program.cs"::: ### When reading with If you want to read a custom or text representation with , -you can get the value of the current JSON token as a using , then parse the value -using custom logic. +you can get the value of the current JSON token as a using method, then parse the value using custom logic. -The following example shows how a custom text representation can be retrieved using , +The following example shows how a custom text representation can be retrieved using the method, then parsed using : :::code language="csharp" source="snippets/system-text-json-support/csharp/custom-reading-with-utf8jsonreader/Program.cs"::: @@ -150,23 +144,23 @@ then parsed using defines the following components for -date and time representations. These components are used to define various levels of granularity -supported when parsing and formatting and representations. +date and time representations. These components are used to define various supported levels of granularity +when parsing and formatting and representations. | Component | Format | Description | |-----------------|-----------------------------|---------------------------------------------------------------------------------| | Year | "yyyy" | 0001-9999 | | Month | "MM" | 01-12 | -| Day | "dd" | 01-28, 01-29, 01-30, 01-31 based on month/year | +| Day | "dd" | 01-28, 01-29, 01-30, 01-31 based on month/year. | | Hour | "HH" | 00-23 | | Minute | "mm" | 00-59 | | Second | "ss" | 00-59 | -| Second fraction | "FFFFFFF" | Minimum of one digit, maximum of 16 digits | -| Time offset | "K" | Either "Z" or "('+'/'-')HH':'mm" | -| Partial time | "HH':'mm':'ss[FFFFFFF]" | Time without UTC offset information | -| Full date | "yyyy'-'MM'-'dd" | Calendar date | -| Full time | "'Partial time'K" | UTC of day or Local time of day with the time offset between local time and UTC | -| Date time | "'Full date''T''Full time'" | Calendar date and time of day, e.g. 2019-07-26T16:59:57-05:00 | +| Second fraction | "FFFFFFF" | Minimum of one digit, maximum of 16 digits. | +| Time offset | "K" | Either "Z" or "('+'/'-')HH':'mm". | +| Partial time | "HH':'mm':'ss[FFFFFFF]" | Time without UTC offset information. | +| Full date | "yyyy'-'MM'-'dd" | Calendar date. | +| Full time | "'Partial time'K" | UTC of day or Local time of day with the time offset between local time and UTC.| +| Date time | "'Full date''T''Full time'" | Calendar date and time of day, for example, 2019-07-26T16:59:57-05:00. | ### Support for parsing @@ -175,36 +169,36 @@ The following levels of granularity are defined for parsing: 1. 'Full date' 1. "yyyy'-'MM'-'dd" -2. "'Full date''T''Hour'':''Minute'" +1. "'Full date''T''Hour'':''Minute'" 1. "yyyy'-'MM'-'dd'T'HH':'mm" -3. "'Full date''T''Partial time'" +1. "'Full date''T''Partial time'" 1. "yyyy'-'MM'-'dd'T'HH':'mm':'ss" ([The Sortable ("s") Format Specifier](../base-types/standard-date-and-time-format-strings.md#the-sortable-s-format-specifier)) - 2. "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFF" + 1. "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFF" -4. "'Full date''T''Time hour'':''Minute''Time offset'" +1. "'Full date''T''Time hour'':''Minute''Time offset'" 1. "yyyy'-'MM'-'dd'T'HH':'mmZ" - 2. "yyyy'-'MM'-'dd'T'HH':'mm('+'/'-')HH':'mm" + 1. "yyyy'-'MM'-'dd'T'HH':'mm('+'/'-')HH':'mm" -5. 'Date time' +1. 'Date time' 1. "yyyy'-'MM'-'dd'T'HH':'mm':'ssZ" - 2. "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFFZ" - 3. "yyyy'-'MM'-'dd'T'HH':'mm':'ss('+'/'-')HH':'mm" - 4. "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFF('+'/'-')HH':'mm" + 1. "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFFZ" + 1. "yyyy'-'MM'-'dd'T'HH':'mm':'ss('+'/'-')HH':'mm" + 1. "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFF('+'/'-')HH':'mm" - This level of granularity is compliant with [RFC 3339](https://tools.ietf.org/html/rfc3339#section-5.6), a widely adopted profile of ISO 8601 used for interchanging date and time information. However, there are a few restrictions in the System.Text.Json implementation. + This level of granularity is compliant with [RFC 3339](https://tools.ietf.org/html/rfc3339#section-5.6), a widely adopted profile of ISO 8601 used for interchanging date and time information. However, there are a few restrictions in the `System.Text.Json` implementation. - - RFC 3339 does not specify a maximum number of fractional-second digits, but specifies that at least one digit must follow the period, if a fractional-second section is present. The implementation in System.Text.Json allows up to 16 digits (to support interop with other programming languages and frameworks), but parses only the first seven. A will be thrown if there are more than 16 fractional second digits when reading `DateTime` and `DateTimeOffset` instances. - - RFC 3339 allows the "T" and "Z" characters to be "t" or "z" respectively, but allows applications to limit support to just the upper-case variants. The implementation in System.Text.Json requires them to be "T" and "Z". A will be thrown if input payloads contain "t" or "z" when reading `DateTime` and `DateTimeOffset` instances. - - RFC 3339 specifies that the date and time sections are separated by "T", but allows applications to separate them by a space (" ") instead. System.Text.Json requires date and time sections to be separated with "T". A will be thrown if input payloads contain a space (" ") when reading `DateTime` and `DateTimeOffset` instances. + - RFC 3339 doesn't specify a maximum number of fractional-second digits, but specifies that at least one digit must follow the period, if a fractional-second section is present. The implementation in `System.Text.Json` allows up to 16 digits (to support interop with other programming languages and frameworks), but parses only the first seven. A will be thrown if there are more than 16 fractional second digits when reading `DateTime` and `DateTimeOffset` instances. + - RFC 3339 allows the "T" and "Z" characters to be "t" or "z" respectively, but allows applications to limit support to just the upper-case variants. The implementation in `System.Text.Json` requires them to be "T" and "Z". A will be thrown if input payloads contain "t" or "z" when reading `DateTime` and `DateTimeOffset` instances. + - RFC 3339 specifies that the date and time sections are separated by "T", but allows applications to separate them by a space (" ") instead. `System.Text.Json` requires date and time sections to be separated with "T". A will be thrown if input payloads contain a space (" ") when reading `DateTime` and `DateTimeOffset` instances. -If there are decimal fractions for seconds, there must be at least one digit; `2019-07-26T00:00:00.` is not allowed. +If there are decimal fractions for seconds, there must be at least one digit. `2019-07-26T00:00:00.` isn't allowed. While up to 16 fractional digits are allowed, only the first seven are parsed. Anything beyond that is considered a zero. -For example, `2019-07-26T00:00:00.1234567890` will be parsed as if it is `2019-07-26T00:00:00.1234567`. -This is to stay compatible with the implementation, which is limited to this resolution. +For example, `2019-07-26T00:00:00.1234567890` will be parsed as if it's `2019-07-26T00:00:00.1234567`. +This approach maintains compatibility with the implementation, which is limited to this resolution. -Leap seconds are not supported. +Leap seconds aren't supported. ### Support for formatting @@ -216,24 +210,24 @@ The following levels of granularity are defined for formatting: Used to format a without fractional seconds and without offset information. - 2. "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFF" + 1. "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFF" Used to format a with fractional seconds but without offset information. -2. 'Date time' +1. 'Date time' 1. "yyyy'-'MM'-'dd'T'HH':'mm':'ssZ" Used to format a without fractional seconds but with a UTC offset. - 2. "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFFZ" + 1. "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFFZ" Used to format a with fractional seconds and with a UTC offset. - 3. "yyyy'-'MM'-'dd'T'HH':'mm':'ss('+'/'-')HH':'mm" + 1. "yyyy'-'MM'-'dd'T'HH':'mm':'ss('+'/'-')HH':'mm" Used to format a or without fractional seconds but with a local offset. - 4. "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFF('+'/'-')HH':'mm" + 1. "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFF('+'/'-')HH':'mm" Used to format a or with fractional seconds and with a local offset. @@ -255,4 +249,4 @@ and . Truncating zeros in fractional-second digits allows the smallest output needed to preserve information on a round trip to be written. -A maximum of 7 fractional-second digits are written. This aligns with the implementation, which is limited to this resolution. +A maximum of seven fractional-second digits are written. This maximum aligns with the implementation, which is limited to this resolution. diff --git a/docs/standard/events/how-to-raise-and-consume-events.md b/docs/standard/events/how-to-raise-and-consume-events.md index c4c0a4109d3a6..b97451417efab 100644 --- a/docs/standard/events/how-to-raise-and-consume-events.md +++ b/docs/standard/events/how-to-raise-and-consume-events.md @@ -1,7 +1,8 @@ --- title: "How to: Raise and Consume Events" description: Raise & consume events in .NET. See examples that use the EventHandler delegate, the EventHandler delegate, & a custom delegate. -ms.date: "03/30/2017" +ms.date: "07/29/2022" +ms.custom: devdivchpfy22 dev_langs: - "csharp" - "vb" @@ -14,20 +15,20 @@ ms.assetid: 42afade7-3a02-4f2e-868b-95845f302f8f --- # How to: Raise and Consume Events -The examples in this topic show how to work with events. They include examples of the delegate, the delegate, and a custom delegate, to illustrate events with and without data. +The examples in this article show how to work with events. They include examples of the delegate, the delegate, and a custom delegate to illustrate events with and without data. - The examples use concepts described in the [Events](index.md) article. +The examples use concepts described in the [Events](index.md) article. ## Example 1 - The first example shows how to raise and consume an event that doesn't have data. It contains a class named `Counter` that has an event named `ThresholdReached`. This event is raised when a counter value equals or exceeds a threshold value. The delegate is associated with the event, because no event data is provided. + The first example shows how to raise and consume an event that doesn't have data. It contains a class named `Counter` that has an event called `ThresholdReached`. This event is raised when a counter value equals or exceeds a threshold value. The delegate is associated with the event because no event data is provided. [!code-csharp[EventsOverview#5](../../../samples/snippets/csharp/VS_Snippets_CLR/eventsoverview/cs/programnodata.cs#5)] [!code-vb[EventsOverview#5](../../../samples/snippets/visualbasic/VS_Snippets_CLR/eventsoverview/vb/module1nodata.vb#5)] ## Example 2 - The next example shows how to raise and consume an event that provides data. The delegate is associated with the event, and an instance of a custom event data object is provided. + The second example shows how to raise and consume an event that provides data. The delegate is associated with the event, and an instance of a custom event data object is provided. [!code-cpp[EventsOverview#6](../../../samples/snippets/cpp/VS_Snippets_CLR/eventsoverview/cpp/programwithdata.cpp#6)] [!code-csharp[EventsOverview#6](../../../samples/snippets/csharp/VS_Snippets_CLR/eventsoverview/cs/programwithdata.cs#6)] @@ -35,7 +36,7 @@ The examples in this topic show how to work with events. They include examples o ## Example 3 - The next example shows how to declare a delegate for an event. The delegate is named `ThresholdReachedEventHandler`. This is just an illustration. Typically, you do not have to declare a delegate for an event, because you can use either the or the delegate. You should declare a delegate only in rare scenarios, such as making your class available to legacy code that cannot use generics. + The third example shows how to declare a delegate for an event. The delegate is named `ThresholdReachedEventHandler`. This example is just an illustration. Typically, you don't have to declare a delegate for an event because you can use either the or the delegate. You should declare a delegate only in rare scenarios, such as making your class available to legacy code that can't use generics. [!code-csharp[EventsOverview#7](../../../samples/snippets/csharp/VS_Snippets_CLR/eventsoverview/cs/programwithdelegate.cs#7)] [!code-vb[EventsOverview#7](../../../samples/snippets/visualbasic/VS_Snippets_CLR/eventsoverview/vb/module1withdelegate.vb#7)] diff --git a/docs/standard/io/how-to-read-text-from-a-file.md b/docs/standard/io/how-to-read-text-from-a-file.md index 33a447cab7146..ab4ebb57cafaf 100644 --- a/docs/standard/io/how-to-read-text-from-a-file.md +++ b/docs/standard/io/how-to-read-text-from-a-file.md @@ -1,7 +1,8 @@ --- title: "How to: Read text from a file" description: In this article, see examples of how to read text synchronously or asynchronously from a text file, using the StreamReader class in .NET for desktop apps. -ms.date: "01/03/2019" +ms.date: "07/29/2022" +ms.custom: devdivchpfy22 dev_langs: - "csharp" - "vb" @@ -18,7 +19,7 @@ ms.assetid: ed180baa-dfc6-4c69-a725-46e87edafb27 The following examples show how to read text synchronously and asynchronously from a text file using .NET for desktop apps. In both examples, when you create the instance of the class, you provide the relative or absolute path to the file. > [!NOTE] -> These code examples do not apply to Universal Windows (UWP) apps, because the Windows Runtime provides different stream types for reading and writing to files. For an example that shows how to read text from a file in a UWP app, see [Quickstart: Reading and writing files](/previous-versions/windows/apps/hh758325(v=win.10)). For examples that show how to convert between .NET Framework streams and Windows Runtime streams, see [How to: Convert between .NET Framework streams and Windows Runtime streams](how-to-convert-between-dotnet-streams-and-winrt-streams.md). +> These code examples don't apply to Universal Windows (UWP) apps because the Windows runtime provides different stream types for reading and writing to files. For an example that shows how to read text from a file in a UWP app, see [Quickstart: Reading and writing files](/previous-versions/windows/apps/hh758325(v=win.10)). For examples that show how to convert between .NET Framework streams and Windows Runtime streams, see [How to: Convert between .NET Framework streams and Windows Runtime streams](how-to-convert-between-dotnet-streams-and-winrt-streams.md). ## Example: Synchronous read in a console app 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 d6fc81f5e422b..3aee21c67ae24 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 @@ -1,7 +1,8 @@ --- title: "Chaining tasks using continuation tasks" description: Learn to chain task by using continuation tasks in .NET. A continuation task is an asynchronous task that's invoked by another task. -ms.date: 01/06/2021 +ms.date: 08/05/2022 +ms.custom: devdivchpfy22 dev_langs: - "csharp" - "vb" @@ -12,13 +13,13 @@ ms.assetid: 0b45e9a2-de28-46ce-8212-1817280ed42d # Chaining tasks using continuation tasks -In asynchronous programming, it's common for one asynchronous operation, on completion, to invoke a second operation. Continuations allow descendant operations to consume the results of the first operation. Traditionally, continuations have been done by using callback methods. In the Task Parallel Library, the same functionality is provided by _continuation tasks_. A continuation task (also known just as a continuation) is an asynchronous task that's invoked by another task, known as the _antecedent_, when the antecedent finishes. +In asynchronous programming, it's common for one asynchronous operation to invoke a second operation on completion. Continuations allow descendant operations to consume the results of the first operation. Traditionally, continuations have been done by using callback methods. In the Task Parallel Library (TPL), the same functionality is provided by _continuation tasks_. A continuation task (also known just as a continuation) is an asynchronous task that's invoked by another task, known as the _antecedent_, when the antecedent finishes. -Continuations are relatively easy to use, but are nevertheless powerful and flexible. For example, you can: +Continuations are relatively easy to use but are nevertheless powerful and flexible. For example, you can: - Pass data from the antecedent to the continuation. - Specify the precise conditions under which the continuation will be invoked or not invoked. -- Cancel a continuation either before it starts or cooperatively as it is running. +- Cancel a continuation either before it starts or cooperatively as it's running. - Provide hints about how the continuation should be scheduled. - Invoke multiple continuations from the same antecedent. - Invoke one continuation when all or any one of multiple antecedents complete. @@ -27,13 +28,13 @@ Continuations are relatively easy to use, but are nevertheless powerful and flex ## About continuations -A continuation is a task that is created in the state. It is activated automatically when its antecedent task or tasks complete. Calling on a continuation in user code throws an exception. +A continuation is a task that's created in the state. It's activated automatically when its antecedent task or tasks complete. Calling on a continuation in user code throws an exception. -A continuation is itself a and does not block the thread on which it is started. Call the method to block until the continuation task finishes. +A continuation is itself a and doesn't block the thread on which it's started. Call the method to block until the continuation task finishes. ## Create a continuation for a single antecedent -You create a continuation that executes when its antecedent has completed by calling the method. The following example shows the basic pattern (for clarity, exception handling is omitted). It executes an antecedent task, `taskA`, that returns a object that indicates the name of the current day of the week. When the antecedent completes, the continuation task, `continuation`, is passed the antecedent and displays a string that includes its result. +You create a continuation that executes when its antecedent has completed by calling the method. The following example shows the basic pattern (for clarity, exception handling is omitted). It executes an antecedent task `taskA` that returns a object that indicates the name of the current day of the week. When the antecedent completes, the continuation task, `continuation`, is passed the antecedent and displays a string that includes its result. :::code language="csharp" source="snippets/cs/simple1.cs"::: @@ -41,11 +42,11 @@ You create a continuation that executes when its antecedent has completed by cal ## Create a continuation for multiple antecedents -You can also create a continuation that will run when any or all of a group of tasks has completed. To execute a continuation when all antecedent tasks have completed, you call the static (`Shared` in Visual Basic) method or the instance method. To execute a continuation when any of the antecedent tasks has completed, you call the static (`Shared` in Visual Basic) method or the instance method. +You can also create a continuation that will run when any or all of a group of tasks have completed. To execute a continuation when all antecedent tasks have completed, you can call the static (`Shared` in Visual Basic) method or the instance method. To execute a continuation when any of the antecedent tasks have completed, you can call the static (`Shared` in Visual Basic) method or the instance method. -Calls to the and overloads do not block the calling thread. However, you typically call all but the and methods to retrieve the returned property, which does block the calling thread. +Calls to the and overloads don't block the calling thread. However, you typically call all but the and methods to retrieve the returned property, which does block the calling thread. -The following example calls the method to create a continuation task that reflects the results of its 10 antecedent tasks. Each antecedent task squares an index value that ranges from one to 10. If the antecedents complete successfully (their property is ), the property of the continuation is an array of the values returned by each antecedent. The example adds them to compute the sum of squares for all numbers between one and 10. +The following example calls the method to create a continuation task that reflects the results of its 10 antecedent tasks. Each antecedent task squares an index value that ranges from one to 10. If the antecedents complete successfully (their property is ), the property of the continuation is an array of the values returned by each antecedent. The example adds them to compute the sum of squares for all numbers between one and 10: :::code language="csharp" source="snippets/cs/whenall1.cs"::: @@ -53,23 +54,23 @@ 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 is not true when the antecedent is ready to invoke the continuation, the continuation transitions directly to the state and subsequently cannot be started. +When you create a single-task continuation, you can use a 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. -A number of multi-task continuation methods, such as overloads of the method, also include a parameter. Only a subset of all enumeration members are valid, however. 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 run time. -For more information on task continuation options, see the topic. +For more information on task continuation options, see the article. ## Pass data to a continuation -The method passes a reference to the antecedent to the user delegate of the continuation as an argument. If the antecedent is a object, and the task ran until it was completed, then the continuation can access the property of the task. +The method passes a reference to the antecedent as an argument to the user delegate of the continuation. If the antecedent is a object, and the task ran until it was completed, then the continuation can access the property of the task. -The property blocks until the task has completed. However, if the task was canceled or faulted, attempting to access the property throws an exception. You can avoid this problem by using the option, as shown in the following example. +The property blocks until the task has completed. However, if the task was canceled or faulted, attempting to access the property throws an exception. You can avoid this problem by using the option, as shown in the following example: :::code language="csharp" source="snippets/cs/result1.cs"::: [!code-vb[TPL_Continuations#2](../../../samples/snippets/visualbasic/VS_Snippets_Misc/tpl_continuations/vb/result1.vb#2)] -If you want the continuation to run even if the antecedent did not run to successful completion, you must guard against the exception. One approach is to test the property of the antecedent, and only attempt to access the property if the status is not or . You can also examine the property of the antecedent. For more information, see [Exception Handling](exception-handling-task-parallel-library.md). The following example modifies the previous example to access antecedent's property only if its status is . +If you want the continuation to run even if the antecedent didn't run to successful completion, you must guard against the exception. One approach is to test the property of the antecedent, and only attempt to access the property if the status isn't or . You can also examine the property of the antecedent. For more information, see [Exception Handling](exception-handling-task-parallel-library.md). The following example modifies the preceding example to access antecedent's property only if its status is : :::code language="csharp" source="snippets/cs/result2.cs"::: @@ -79,47 +80,49 @@ If you want the continuation to run even if the antecedent did not run to succes The property of a continuation is set to in the following situations: -- It throws an exception in response to a cancellation request. As with any task, if the exception contains the same token that was passed to the continuation, it is treated as an acknowledgment of cooperative cancellation. -- The continuation is passed a whose property is `true`. In this case, the continuation does not start, and it transitions to the state. -- The continuation never runs because the condition set by its argument was not met. For example, if an antecedent goes into a state, its continuation that was passed the option will not run but will transition to the state. +- It throws an exception in response to a cancellation request. As with any task, if the exception contains the same token that was passed to the continuation, it's treated as an acknowledgment of cooperative cancellation. -If a task and its continuation represent two parts of the same logical operation, you can pass the same cancellation token to both tasks, as shown in the following example. It consists of an antecedent that generates a list of integers that are divisible by 33, which it passes to the continuation. The continuation in turn displays the list. Both the antecedent and the continuation pause regularly for random intervals. In addition, a object is used to execute the `Elapsed` method after a five-second timeout interval. This example calls the method, which causes the currently executing task to call the method. Whether the method is called when the antecedent or its continuation is executing depends on the duration of the randomly generated pauses. If the antecedent is canceled, the continuation will not start. If the antecedent is not canceled, the token can still be used to cancel the continuation. +- The continuation is passed a whose property is `true`. In this case, the continuation doesn't start, and it transitions to the state. + +- The continuation never runs because the condition set by its argument wasn't met. For example, if an antecedent goes into a state, its continuation that was passed the option won't run but will transition to the state. + +If a task and its continuation represent two parts of the same logical operation, you can pass the same cancellation token to both tasks, as shown in the following example. It consists of an antecedent that generates a list of integers that are divisible by 33, which it passes to the continuation. The continuation in turn displays the list. Both the antecedent and the continuation pause regularly for random intervals. In addition, a object is used to execute the `Elapsed` method after a five-second timeout interval. This example calls the method, which causes the currently executing task to call the method. Whether the method is called when the antecedent or its continuation is executing depends on the duration of the randomly generated pauses. If the antecedent is canceled, the continuation won't start. If the antecedent isn't canceled, the token can still be used to cancel the continuation. :::code language="csharp" source="snippets/cs/cancellation1.cs"::: [!code-vb[TPL_Continuations#3](../../../samples/snippets/visualbasic/VS_Snippets_Misc/tpl_continuations/vb/cancellation1.vb#3)] -You can also prevent a continuation from executing if its antecedent is canceled without supplying the continuation a cancellation token by specifying the option when you create the continuation. The following is a simple example. +You can also prevent a continuation from executing if its antecedent is canceled without providing the continuation a cancellation token. Provide the token by specifying the option when you create the continuation, as shown in the following example: :::code language="csharp" source="snippets/cs/cancellation2.cs"::: [!code-vb[TPL_Continuations#8](../../../samples/snippets/visualbasic/VS_Snippets_Misc/tpl_continuations/vb/cancellation2.vb#8)] -After a continuation goes into the state, it may affect continuations that follow, depending on the that were specified for those continuations. +After a continuation goes into the state, it might affect continuations that follow, depending on the that were specified for those continuations. -Continuations that are disposed will not start. +Continuations that are disposed won't start. ## Continuations and child tasks -A continuation does not run until the antecedent and all of its attached child tasks have completed. The continuation does not wait for detached child tasks to finish. The following two examples illustrate child tasks that are attached to and detached from an antecedent that creates a continuation. In the following example, the continuation runs only after all child tasks have completed, and running the example multiple times produces identical output each time. The example launches the antecedent by calling the method, since by default the method creates a parent task whose default task creation option is . +A continuation doesn't run until the antecedent and all of its attached child tasks have completed. A continuation doesn't wait for detached child tasks to finish. The following two examples illustrate child tasks that are attached to and detached from an antecedent that creates a continuation. In the following example, the continuation runs only after all child tasks have completed, and multiple runs of the example produces identical output each time. The example launches the antecedent by calling the method because by default the method creates a parent task whose default task creation option is . :::code language="csharp" source="snippets/cs/attached1.cs"::: [!code-vb[TPL_Continuations#9](../../../samples/snippets/visualbasic/VS_Snippets_Misc/tpl_continuations/vb/attached1.vb#9)] -If child tasks are detached from the antecedent, however, the continuation runs as soon as the antecedent has terminated, regardless of the state of the child tasks. As a result, multiple runs of the following example can produce variable output that depends on how the task scheduler handled each child task. +If child tasks are detached from the antecedent, however, the continuation runs as soon as the antecedent has terminated, regardless of the state of the child tasks. As a result, multiple runs of the following example can produce variable output that depends on how the task scheduler handled each child task: :::code language="csharp" source="snippets/cs/detached1.cs"::: [!code-vb[TPL_Continuations#10](../../../samples/snippets/visualbasic/VS_Snippets_Misc/tpl_continuations/vb/detached1.vb#10)] -The final status of the antecedent task depends on the final status of any attached child tasks. The status of detached child tasks does not affect the parent. For more information, see [Attached and Detached Child Tasks](attached-and-detached-child-tasks.md). +The final status of the antecedent task depends on the final status of any attached child tasks. The status of detached child tasks doesn't affect the parent. For more information, see [Attached and Detached Child Tasks](attached-and-detached-child-tasks.md). ## Associate state with continuations -You can associate arbitrary state with a task continuation. The method provides overloaded versions that each take an value that represents the state of the continuation. You can later access this state object by using the property. This state object is `null` if you do not provide a value. +You can associate arbitrary state with a task continuation. The method provides overloaded versions that each take an value that represents the state of the continuation. You can later access this state object by using the property. This state object is `null` if you don't provide a value. -Continuation state is useful when you convert existing code that uses the [Asynchronous Programming Model (APM)](../asynchronous-programming-patterns/asynchronous-programming-model-apm.md) to use the TPL. In the APM, you typically provide object state in the **Begin**_Method_ method and later access that state by using the property. By using the method, you can preserve this state when you convert code that uses the APM to use the TPL. +Continuation state is useful when you convert existing code that uses the [Asynchronous Programming Model (APM)](../asynchronous-programming-patterns/asynchronous-programming-model-apm.md) to use the TPL. In the APM, you can provide object state in the **Begin**_Method_ method and later you can use the property to access that state. To preserve this state when you convert a code that uses the APM to use the TPL, you use the method. Continuation state can also be useful when you work with objects in the Visual Studio debugger. For example, in the **Parallel Tasks** window, the **Task** column displays the string representation of the state object for each task. For more information about the **Parallel Tasks** window, see [Using the Tasks Window](/visualstudio/debugger/using-the-tasks-window). @@ -131,7 +134,7 @@ The following example shows how to use continuation state. It creates a chain of ## Continuations that return Task types -Sometimes you may need to chain a continuation that returns a type. These are referred to as nested tasks, and they are common. When a parent task calls , and provides a `continuationFunction` that is task returning you call to create a proxy task that represents the asynchronous operation of the `>>` or `Task(Of Task(Of T))` (Visual Basic). +Sometimes you might need to chain a continuation that returns a type. These tasks are referred as nested tasks. When a parent task calls and provides a `continuationFunction` that's task-returning, you can call to create a proxy task that represents the asynchronous operation of the `>>` or `Task(Of Task(Of T))` (Visual Basic). The following example shows how to use continuations that wrap additional task returning functions. Each continuation can be unwrapped, exposing the inner task that was wrapped. @@ -142,9 +145,9 @@ For more information on using , , or method, or its generic counterpart, to wait on the continuation. You can wait for an antecedent and its continuations in the same `try` statement, as shown in the following example. +- You can use the , , or method, or its generic counterpart, to wait on the continuation. You can wait for an antecedent and its continuations in the same `try` statement, as shown in the following example: :::code language="csharp" source="snippets/cs/exception1.cs"::: @@ -156,7 +159,7 @@ An antecedent-continuation relationship is not a parent-child relationship. Exce [!code-vb[TPL_Continuations#4](../../../samples/snippets/visualbasic/VS_Snippets_Misc/tpl_continuations/vb/exception2.vb#4)] -Because it was run with the option, the continuation executes only if an exception occurs in the antecedent, and therefore it can assume that the antecedent's property is not `null`. If the continuation executes whether or not an exception is thrown in the antecedent, it would have to check whether the antecedent's property is not `null` before attempting to handle the exception, as the following code fragment shows. +Because it was run with the option, the continuation executes only if an exception occurs in the antecedent. Therefore it can assume that the antecedent's property isn't `null`. If the continuation executes whether or not an exception is thrown in the antecedent, it must check whether the antecedent's property isn't `null` before attempting to handle the exception, as the following code fragment shows: :::code language="csharp" source="snippets/cs/exception2.cs" id="exception"::: diff --git a/docs/standard/serialization/controlling-xml-serialization-using-attributes.md b/docs/standard/serialization/controlling-xml-serialization-using-attributes.md index d0119dae61cc6..ccbb877b0a6d6 100644 --- a/docs/standard/serialization/controlling-xml-serialization-using-attributes.md +++ b/docs/standard/serialization/controlling-xml-serialization-using-attributes.md @@ -1,7 +1,8 @@ --- 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: "03/30/2017" +ms.date: "08/05/2022" +ms.custom: devdivchpfy22 dev_langs: - "csharp" - "vb" @@ -19,12 +20,12 @@ ms.topic: how-to --- # Control XML serialization using attributes -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. For more details about creating an alternate XML stream, see [How to: Specify an Alternate Element Name for an XML Stream](how-to-specify-an-alternate-element-name-for-an-xml-stream.md). +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. For more information about creating an alternate XML stream, see [How to: Specify an Alternate Element Name for an XML Stream](how-to-specify-an-alternate-element-name-for-an-xml-stream.md). > [!NOTE] > If the XML generated must conform to section 5 of the World Wide Web Consortium (W3C) document titled [Simple Object Access Protocol (SOAP) 1.1](https://www.w3.org/TR/2000/NOTE-SOAP-20000508/), use the attributes listed in [Attributes That Control Encoded SOAP Serialization](attributes-that-control-encoded-soap-serialization.md). -By default, an XML element name is determined by the class or member name. In a simple class named `Book`, a field named `ISBN` will produce an XML element tag \, as shown in the following example. +By default, an XML element name is determined by the class or member name. In a class named `Book`, a field named **ISBN** will produce an XML element tag ``, as shown in the following example: ```vb Public Class Book @@ -45,7 +46,7 @@ public class Book // 1234567890. ``` -This default behavior can be changed if you want to give the element a new name. The following code shows how an attribute enables this by setting the property of a . +The default behavior can be changed if you want to give the element a new name. The following code shows how an attribute enables this functionality by setting the property of an : ```vb Public Class TaxRates @@ -65,7 +66,7 @@ For more information about attributes, see [Attributes](../attributes/index.md). ## Controlling Array Serialization -The and the attributes are designed to control the serialization of arrays. Using these attributes, you can control the element name, namespace, and XML Schema (XSD) data type (as defined in the World Wide Web Consortium [www.w3.org] document titled "XML Schema Part 2: Datatypes"). You can also specify the types that can be included in an array. +The and the attributes control the serialization of arrays. Using these attributes, you can control the element name, namespace, and XML Schema (XSD) data type as defined in the W3C document titled [XML Schema Part 2: Datatypes](https://www.w3.org/TR/xmlschema-2/). You can also specify the types that can be included in an array. The will determine the properties of the enclosing XML element that results when an array is serialized. For example, by default, serializing the array below will result in an XML element named `Employees`. The `Employees` element will contain a series of elements named after the array type `Employee`. @@ -87,7 +88,7 @@ public class Employee { } ``` -A serialized instance might resemble the following. +A serialized instance might resemble the following code: ```xml @@ -99,7 +100,7 @@ A serialized instance might resemble the following. ``` -By applying a , you can change the name of the XML element, as follows. +By applying a , you can change the name of the XML element, as follows: ```vb Public Class Group @@ -115,7 +116,7 @@ public class Group { } ``` -The resulting XML might resemble the following. +The resulting XML might resemble the following code: ```xml @@ -127,7 +128,10 @@ The resulting XML might resemble the following. ``` -The , on the other hand, controls how the items contained in the array are serialized. Note that the attribute is applied to the field returning the array. +The , on the other hand, controls how the items contained in the array are serialized. + +> [!NOTE] +> The attribute is applied to the field returning the array. ```vb Public Class Group @@ -143,7 +147,7 @@ public class Group { } ``` -The resulting XML might resemble the following. +The resulting XML might resemble the following code: ```xml @@ -155,7 +159,7 @@ The resulting XML might resemble the following. ## 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 do not apply the , the code will fail at run time because the derived class type will not be recognized. To remedy this, 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 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). ```vb Public Class Group @@ -186,7 +190,7 @@ public class Manager:Employee { } ``` -A serialized instance might resemble the following. +A serialized instance might resemble the following code: ```xml @@ -204,7 +208,7 @@ A serialized instance might resemble the following. ## Serializing an Array as a Sequence of Elements -You can also serialize an array as a flat sequence of XML elements by applying a to the field returning the array as follows. +You can also serialize an array as a flat sequence of XML elements by applying a to the field returning the array as follows: ```vb Public Class Group @@ -220,7 +224,7 @@ public class Group { } ``` -A serialized instance might resemble the following. +A serialized instance might resemble the following code: ```xml @@ -236,13 +240,13 @@ A serialized instance might resemble the following. ``` -Another way to differentiate the two XML streams is to use the XML Schema Definition tool to generate the XML Schema (XSD) document files from the compiled code. (For more details on using the tool, see [The XML Schema Definition Tool and XML Serialization](the-xml-schema-definition-tool-and-xml-serialization.md).) When no attribute is applied to the field, the schema describes the element in the following manner. +Another way to differentiate the two XML streams is to use the XML Schema Definition tool to generate the XML Schema (XSD) document files from the compiled code. For more information on using the tool, see [The XML Schema Definition Tool and XML Serialization](the-xml-schema-definition-tool-and-xml-serialization.md). When no attribute is applied to the field, the schema describes the element in the following manner: ```xml ``` -When the is applied to the field, the resulting schema describes the element as follows. +When the is applied to the field, the resulting schema describes the element as follows: ```xml @@ -270,11 +274,11 @@ public class Group { ## Controlling Serialization of Classes Using XmlRootAttribute and XmlTypeAttribute -There are two attributes that can be applied to a class (and only a class): and . These attributes are very similar. The can be applied to only one class: the class that, when serialized, represents the XML document's opening and closing element—in other words, the root element. The , on the other hand, can be applied to any class, including the root class. +You can apply two attributes to a class only: and . These attributes are similar. The can be applied to only one class: the class that, when serialized, represents the XML document's opening and closing element—in other words, the root element. The , on the other hand, can be applied to any class, including the root class. -For example, in the previous examples, the `Group` class is the root class, and all its public fields and properties become the XML elements found in the XML document. Therefore, there can be only one root class. By applying the , you can control the XML stream generated by the . For example, you can change the element name and namespace. +For example, in the previous examples, the `Group` class is the root class, and all its public fields and properties become the XML elements found in the XML document. Therefore, you can have only one root class. By applying the , you can control the XML stream generated by the . For example, you can change the element name and namespace. -The allows you to control the schema of the generated XML. This capability is useful when you need to publish the schema through an XML Web service. The following example applies both the and the to the same class. +The allows you to control the schema of the generated XML. This capability is useful when you need to publish the schema through an XML Web service. The following example applies both the and the to the same class: ```vb ``` -In contrast, if you were to serialize an instance of the class, only `NewGroupName` would be found in the XML document. +In contrast, if you were to serialize an instance of the class, only `NewGroupName` would be found in the XML document: ```xml @@ -308,7 +312,7 @@ In contrast, if you were to serialize an instance of the class, only `NewGroupNa ## Preventing Serialization with the XmlIgnoreAttribute -There might be situations when a public property or field does not need to be serialized. For example, a field or property could be used to contain metadata. In such cases, apply the to the field or property and the will skip over it. +You might come across a situation where a public property or field doesn't need to be serialized. For example, a field or property could be used to contain metadata. In such cases, apply the to the field or property and the will skip over it. ## See also diff --git a/docs/standard/threading/using-threads-and-threading.md b/docs/standard/threading/using-threads-and-threading.md index 5a59d8809c09a..20f7427ac3854 100644 --- a/docs/standard/threading/using-threads-and-threading.md +++ b/docs/standard/threading/using-threads-and-threading.md @@ -1,7 +1,8 @@ --- title: "Using threads and threading" description: Learn about using threads and threading in .NET, so you can write applications to perform many operations at the same time (multithreading). -ms.date: "08/08/2018" +ms.date: "08/05/2022" +ms.custom: devdivchpfy22 helpviewer_keywords: - "threading [.NET], about threading" - "managed threading" @@ -11,22 +12,22 @@ ms.assetid: 9b5ec2cd-121b-4d49-b075-222cf26f2344 With .NET, you can write applications that perform multiple operations at the same time. Operations with the potential of holding up other operations can execute on separate threads, a process known as *multithreading* or *free threading*. -Applications that use multithreading are more responsive to user input because the user interface stays active as processor-intensive tasks execute on separate threads. Multithreading is also useful when you create scalable applications, because you can add threads as the workload increases. +Applications that use multithreading are more responsive to user input because the user interface stays active as processor-intensive tasks execute on separate threads. Multithreading is also useful when you create scalable applications because you can add threads as the workload increases. > [!NOTE] -> If you need more control over the behavior of the application's threads, you can manage the threads yourself. However, multithreaded programming is greatly simplified with the and classes, [Parallel LINQ (PLINQ)](../parallel-programming/introduction-to-plinq.md), concurrent collection classes in the namespace, and a programming model that is based on the concept of tasks rather than threads. For more information, see [Parallel Programming](../parallel-programming/index.md) and [Task Parallel Library (TPL)](../parallel-programming/task-parallel-library-tpl.md). +> If you need more control over the behavior of the application's threads, you can manage the threads yourself. However, multithreaded programming is greatly simplified with the and classes, [Parallel LINQ (PLINQ)](../parallel-programming/introduction-to-plinq.md), concurrent collection classes in the namespace, and a programming model that's based on the concept of tasks rather than threads. For more information, see [Parallel Programming](../parallel-programming/index.md) and [Task Parallel Library (TPL)](../parallel-programming/task-parallel-library-tpl.md). ## How to: Create and start a new thread -You create a new thread by creating a new instance of the class and providing the name of the method that you want to execute on a new thread to the constructor. To start a created thread, call the method. For more information and examples, see the [Creating threads and passing data at start time](creating-threads-and-passing-data-at-start-time.md) article and the API reference. +You create a new thread by creating a new instance of the class. You provide the name of the method that you want to execute on the new thread to the constructor. To start a created thread, call the method. For more information and examples, see the [Creating threads and passing data at start time](creating-threads-and-passing-data-at-start-time.md) article and the API reference. ## How to: Stop a thread To terminate the execution of a thread, use the . It provides a unified way to stop threads cooperatively. For more information, see [Cancellation in managed threads](cancellation-in-managed-threads.md). -Sometimes it is not possible to stop a thread cooperatively, because it runs third-party code not designed for cooperative cancellation. In this case, you might want to terminate its execution forcibly. To terminate the execution of a thread forcibly, in .NET Framework you can use the method. That method raises a on the thread on which it's invoked. For more information, see [Destroying threads](destroying-threads.md). The method is not supported in .NET Core. If you need to terminate the execution of third-party code forcibly in .NET Core, run it in the separate process and use . +Sometimes it's not possible to stop a thread cooperatively because it runs third-party code not designed for cooperative cancellation. In this case, you might want to terminate its execution forcibly. To terminate the execution of a thread forcibly, in .NET Framework you can use the method. That method raises a on the thread on which it's invoked. For more information, see [Destroying threads](destroying-threads.md). The method isn't supported in .NET Core. If you need to terminate the execution of third-party code forcibly in .NET Core, run it in the separate process and use the method. -The is not available before .NET Framework 4. To stop a thread in older .NET Framework versions, implement the cooperative cancellation manually using the thread synchronization techniques. For example, you can create the volatile boolean field `shouldStop` and use it to request the code executed by the thread to stop. For more information, see [volatile](../../csharp/language-reference/keywords/volatile.md) in C# Reference and . +The isn't available before .NET Framework 4. To stop a thread in older .NET Framework versions, use the thread synchronization techniques to implement the cooperative cancellation manually. For example, you can create the volatile boolean field `shouldStop` and use it to request the code executed by the thread to stop. For more information, see [volatile](../../csharp/language-reference/keywords/volatile.md) in C# Reference and . Use the method to make the calling thread wait for the termination of the thread being stopped. @@ -40,10 +41,10 @@ The following table presents some of the properti |Property|Description| |--------------|-----------| -||Returns `true` if a thread has been started and has not yet terminated normally or aborted.| -||Gets or sets a Boolean that indicates if a thread is a background thread. Background threads are like foreground threads, but a background thread doesn't prevent a process from stopping. Once all foreground threads that belong to a process have stopped, the common language runtime ends the process by calling the method on background threads that are still alive. For more information, see [Foreground and Background Threads](foreground-and-background-threads.md).| +||Returns `true` if a thread has been started and hasn't yet terminated normally or aborted.| +||Gets or sets a Boolean that indicates if a thread is a background thread. Background threads are like foreground threads. However, a background thread doesn't prevent a process from stopping. Once all foreground threads that belong to a process have stopped, the common language runtime ends the process by calling the method on background threads that are still alive. For more information, see [Foreground and Background Threads](foreground-and-background-threads.md).| ||Gets or sets the name of a thread. Most frequently used to discover individual threads when you debug.| -||Gets or sets a value that is used by the operating system to prioritize thread scheduling. For more information, see [Scheduling threads](scheduling-threads.md) and the reference.| +||Gets or sets a value that's used by the operating system to prioritize thread scheduling. For more information, see [Scheduling threads](scheduling-threads.md) and the reference.| ||Gets a value containing the current states of a thread.| ## See also