diff --git a/docs/csharp/how-to/compare-strings.md b/docs/csharp/how-to/compare-strings.md index c86f6252600ab..b21db5922644a 100644 --- a/docs/csharp/how-to/compare-strings.md +++ b/docs/csharp/how-to/compare-strings.md @@ -38,7 +38,7 @@ By default, the most common operations: - - and , that is, [equality operators `==` and `!=`](../language-reference/operators/equality-operators.md#string-equality), respectively perform a case-sensitive, ordinal comparison. has an overload where a argument can be provided to alter its sorting rules. The following example demonstrates that: -:::code language="csharp" interactive="try-dotnet-method" source="../../../samples/snippets/csharp/how-to/strings/CompareStrings.cs" id="Snippet1"::: +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/strings/CompareStrings.cs" id="Snippet1"::: The default ordinal comparison doesn't take linguistic rules into account when comparing strings. It compares the binary value of each object in two strings. As a result, the default ordinal comparison is also case-sensitive. @@ -49,7 +49,7 @@ The test for equality with method enables you to specify a value of for a case-insensitive ordinal comparison. There's also a static method that performs a case-insensitive ordinal comparison if you specify a value of for the argument. These comparisons are shown in the following code: -:::code language="csharp" interactive="try-dotnet-method" source="../../../samples/snippets/csharp/how-to/strings/CompareStrings.cs" id="Snippet2"::: +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/strings/CompareStrings.cs" id="Snippet2"::: These methods use the casing conventions of the [invariant culture](xref:System.Globalization.CultureInfo.InvariantCulture) when performing a case-insensitive ordinal comparison. @@ -57,7 +57,7 @@ These methods use the casing conventions of the [invariant culture](xref:System. Many string comparison methods (such as ) use linguistic rules for the _current culture_ by default to order their inputs. This linguistic comparison is sometimes referred to as "word sort order." When you perform a linguistic comparison, some nonalphanumeric Unicode characters might have special weights assigned. For example, the hyphen "-" might have a small weight assigned to it so that "co-op" and "coop" appear next to each other in sort order. Some nonprinting control characters might be ignored. In addition, some Unicode characters might be equivalent to a sequence of instances. The following example uses the phrase "They dance in the street." in German with the "ss" (U+0073 U+0073) in one string and 'ß' (U+00DF) in another. Linguistically (in Windows), "ss" is equal to the German Esszet: 'ß' character in both the "en-US" and "de-DE" cultures. -:::code language="csharp" interactive="try-dotnet-method" source="../../../samples/snippets/csharp/how-to/strings/CompareStrings.cs" id="Snippet3"::: +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/strings/CompareStrings.cs" id="Snippet3"::: On Windows, prior to .NET 5, the sort order of "cop", "coop", and "co-op" changes when you change from a linguistic comparison to an ordinal comparison. The two German sentences also compare differently using the different comparison types. Prior to .NET 5, the .NET globalization APIs used [National Language Support (NLS)](/windows/win32/intl/national-language-support) libraries. In .NET 5 and later versions, the .NET globalization APIs use [International Components for Unicode (ICU)](https://icu.unicode.org/) libraries, which unifies .NET's globalization behavior across all supported operating systems. @@ -65,7 +65,7 @@ On Windows, prior to .NET 5, the sort order of "cop", "coop", and "co-op" change The following example stores objects for the en-US and de-DE cultures. The comparisons are performed using a object to ensure a culture-specific comparison. The culture used affects linguistic comparisons. The following example shows the results of comparing the two German sentences using the "en-US" culture and the "de-DE" culture: -:::code language="csharp" interactive="try-dotnet-method" source="../../../samples/snippets/csharp/how-to/strings/CompareStrings.cs" id="Snippet4"::: +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/strings/CompareStrings.cs" id="Snippet4"::: Culture-sensitive comparisons are typically used to compare and sort strings input by users with other strings input by users. The characters and sorting conventions of these strings might vary depending on the locale of the user's computer. Even strings that contain identical characters might sort differently depending on the culture of the current thread. @@ -75,21 +75,21 @@ The following examples show how to sort and search for strings in an array using The following example shows how to sort an array of strings using the current culture: -:::code language="csharp" interactive="try-dotnet-method" source="../../../samples/snippets/csharp/how-to/strings/CompareStrings.cs" id="Snippet5"::: +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/strings/CompareStrings.cs" id="Snippet5"::: Once the array is sorted, you can search for entries using a binary search. A binary search starts in the middle of the collection to determine which half of the collection would contain the sought string. Each subsequent comparison subdivides the remaining part of the collection in half. The array is sorted using the . The local function `ShowWhere` displays information about where the string was found. If the string wasn't found, the returned value indicates where it would be if it were found. -:::code language="csharp" interactive="try-dotnet-method" source="../../../samples/snippets/csharp/how-to/strings/CompareStrings.cs" id="Snippet6"::: +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/strings/CompareStrings.cs" id="Snippet6"::: ## Ordinal sorting and searching in collections The following code uses the collection class to store strings. The strings are sorted using the method. This method needs a delegate that compares and orders two strings. The method provides that comparison function. Run the sample and observe the order. This sort operation uses an ordinal case-sensitive sort. You would use the static methods to specify different comparison rules. -:::code language="csharp" interactive="try-dotnet-method" source="../../../samples/snippets/csharp/how-to/strings/CompareStrings.cs" id="Snippet7"::: +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/strings/CompareStrings.cs" id="Snippet7"::: Once sorted, the list of strings can be searched using a binary search. The following sample shows how to search the sorted list using the same comparison function. The local function `ShowWhere` shows where the sought text is or would be: -:::code language="csharp" interactive="try-dotnet-method" source="../../../samples/snippets/csharp/how-to/strings/CompareStrings.cs" id="Snippet8"::: +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/strings/CompareStrings.cs" id="Snippet8"::: Always make sure to use the same type of comparison for sorting and searching. Using different comparison types for sorting and searching produces unexpected results. diff --git a/docs/csharp/how-to/concatenate-multiple-strings.md b/docs/csharp/how-to/concatenate-multiple-strings.md index ba73d17d4c47d..87504e77369bf 100644 --- a/docs/csharp/how-to/concatenate-multiple-strings.md +++ b/docs/csharp/how-to/concatenate-multiple-strings.md @@ -22,19 +22,19 @@ ms.custom: copilot-scenario-highlight The following example splits a long string literal into smaller strings to improve readability in the source code. The code concatenates the smaller strings to create the long string literal. The parts are concatenated into a single string at compile time. There's no run-time performance cost regardless of the number of strings involved. -:::code language="csharp" interactive="try-dotnet-method" source="../../../samples/snippets/csharp/how-to/strings/Concatenate.cs" id="Snippet1"::: +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/strings/Concatenate.cs" id="Snippet1"::: ## `+` and `+=` operators To concatenate string variables, you can use the `+` or `+=` operators, [string interpolation](../language-reference/tokens/interpolated.md) or the , , or methods. The `+` operator is easy to use and makes for intuitive code. Even if you use several `+` operators in one statement, the string content is copied only once. The following code shows examples of using the `+` and `+=` operators to concatenate strings: -:::code language="csharp" interactive="try-dotnet-method" source="../../../samples/snippets/csharp/how-to/strings/Concatenate.cs" id="Snippet2"::: +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/strings/Concatenate.cs" id="Snippet2"::: ## String interpolation In some expressions, it's easier to concatenate strings using string interpolation, as the following code shows: -:::code language="csharp" interactive="try-dotnet-method" source="../../../samples/snippets/csharp/how-to/strings/Concatenate.cs" id="Snippet3"::: +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/strings/Concatenate.cs" id="Snippet3"::: > [!NOTE] > In string concatenation operations, the C# compiler treats a null string the same as an empty string. @@ -49,7 +49,7 @@ Another method to concatenate strings is class was designed for these scenarios. The following code uses the method of the class to concatenate strings. -:::code language="csharp" interactive="try-dotnet-method" source="../../../samples/snippets/csharp/how-to/strings/Concatenate.cs" id="Snippet4"::: +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/strings/Concatenate.cs" id="Snippet4"::: You can read more about the [reasons to choose string concatenation or the `StringBuilder` class](/dotnet/api/system.text.stringbuilder#the-string-and-stringbuilder-types). @@ -57,7 +57,7 @@ You can read more about the [reasons to choose string concatenation or the `Stri Another option to join strings from a collection is to use method. Use method if a delimiter should separate source strings. The following code combines an array of words using both methods: -:::code language="csharp" interactive="try-dotnet-method" source="../../../samples/snippets/csharp/how-to/strings/Concatenate.cs" id="Snippet5"::: +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/strings/Concatenate.cs" id="Snippet5"::: ## LINQ and `Enumerable.Aggregate` @@ -67,7 +67,7 @@ the source strings using a lambda expression. The lambda expression does the work to add each string to the existing accumulation. The following example combines an array of words, adding a space between each word in the array: -:::code language="csharp" interactive="try-dotnet-method" source="../../../samples/snippets/csharp/how-to/strings/Concatenate.cs" id="Snippet6"::: +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/strings/Concatenate.cs" id="Snippet6"::: This option can cause more allocations than other methods for concatenating collections, as it creates an intermediate string for each iteration. If optimizing performance is critical, consider the [`StringBuilder`](#stringbuilder) class or the [`String.Concat` or `String.Join`](#stringconcat-or-stringjoin) method to concatenate a collection, instead of `Enumerable.Aggregate`. diff --git a/docs/csharp/how-to/modify-string-contents.md b/docs/csharp/how-to/modify-string-contents.md index a0551a4bdc935..1425bf67af9f1 100644 --- a/docs/csharp/how-to/modify-string-contents.md +++ b/docs/csharp/how-to/modify-string-contents.md @@ -17,13 +17,13 @@ There are several techniques demonstrated in this article. You can replace exist The following code creates a new string by replacing existing text with a substitute. -:::code language="csharp" interactive="try-dotnet-method" source="../../../samples/snippets/csharp/how-to/strings/ModifyStrings.cs" id="Snippet1"::: +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/strings/ModifyStrings.cs" id="Snippet1"::: The preceding code demonstrates this *immutable* property of strings. You can see in the preceding example that the original string, `source`, is not modified. The method creates a new `string` containing the modifications. The method can replace either strings or single characters. In both cases, every occurrence of the sought text is replaced. The following example replaces all ' ' characters with '\_': -:::code language="csharp" interactive="try-dotnet-method" source="../../../samples/snippets/csharp/how-to/strings/ModifyStrings.cs" id="Snippet2"::: +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/strings/ModifyStrings.cs" id="Snippet2"::: The source string is unchanged, and a new string is returned with the replacement. @@ -31,13 +31,13 @@ The source string is unchanged, and a new string is returned with the replacemen You can use the , , and methods to remove any leading or trailing white space. The following code shows an example of each. The source string does not change; these methods return a new string with the modified contents. -:::code language="csharp" interactive="try-dotnet-method" source="../../../samples/snippets/csharp/how-to/strings/ModifyStrings.cs" id="Snippet3"::: +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/strings/ModifyStrings.cs" id="Snippet3"::: ## Remove text You can remove text from a string using the method. This method removes a number of characters starting at a specific index. The following example shows how to use followed by to remove text from a string: -:::code language="csharp" interactive="try-dotnet-method" source="../../../samples/snippets/csharp/how-to/strings/ModifyStrings.cs" id="Snippet4"::: +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/strings/ModifyStrings.cs" id="Snippet4"::: ## Replace matching patterns @@ -45,7 +45,7 @@ You can use [regular expressions](../../standard/base-types/regular-expressions. Regular expressions are most useful for searching and replacing text that follows a pattern, rather than known text. For more information, see [How to search strings](search-strings.md). The search pattern, "the\s" searches for the word "the" followed by a white-space character. That part of the pattern ensures that it doesn't match "there" in the source string. For more information on regular expression language elements, see [Regular Expression Language - Quick Reference](../../standard/base-types/regular-expression-language-quick-reference.md). -:::code language="csharp" interactive="try-dotnet-method" source="../../../samples/snippets/csharp/how-to/strings/ModifyStrings.cs" id="Snippet5"::: +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/strings/ModifyStrings.cs" id="Snippet5"::: The method returns an immutable string with the contents in the object. @@ -55,13 +55,13 @@ You can produce a character array from a string, modify the contents of the arra The following example shows how to replace a set of characters in a string. First, it uses the method to create an array of characters. It uses the method to find the starting index of the word "fox." The next three characters are replaced with a different word. Finally, a new string is constructed from the updated character array. -:::code language="csharp" interactive="try-dotnet-method" source="../../../samples/snippets/csharp/how-to/strings/ModifyStrings.cs" id="Snippet6"::: +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/strings/ModifyStrings.cs" id="Snippet6"::: ## Programmatically build up string content Since strings are immutable, the previous examples all create temporary strings or character arrays. In high-performance scenarios, it may be desirable to avoid these heap allocations. .NET Core provides a method that allows you to programmatically fill in the character content of a string via a callback while avoiding the intermediate temporary string allocations. -:::code language="csharp" source="../../../samples/snippets/csharp/how-to/strings/ModifyStrings.cs" id="Snippet7"::: +:::code language="csharp" source="./snippets/strings/ModifyStrings.cs" id="Snippet7"::: You could modify a string in a fixed block with unsafe code, but it is **strongly** discouraged to modify the string content after a string is created. Doing so will break things in unpredictable ways. For example, if someone interns a string that has the same content as yours, they'll get your copy and won't expect that you are modifying their string. diff --git a/docs/csharp/how-to/parse-strings-using-split.md b/docs/csharp/how-to/parse-strings-using-split.md index fcff09eb616ec..3a44fd32d2a48 100644 --- a/docs/csharp/how-to/parse-strings-using-split.md +++ b/docs/csharp/how-to/parse-strings-using-split.md @@ -1,7 +1,7 @@ --- title: "Divide strings using String.Split" description: The Split method returns an array of strings split from a set of delimiters. It's an easy way to extract substrings from a string. -ms.date: 10/31/2024 +ms.date: 02/10/2025 helpviewer_keywords: - "splitting strings [C#]" - "Split method [C#]" @@ -24,15 +24,15 @@ The method creates an The following code splits a common phrase into an array of strings for each word. -:::code language="csharp" interactive="try-dotnet-method" source="../../../samples/snippets/csharp/how-to/strings/ParseStringsUsingSplit.cs" id="Snippet1"::: +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/strings/ParseStringsUsingSplit.cs" id="Snippet1"::: Every instance of a separator character produces a value in the returned array. Since arrays in C# are zero-indexed, each string in the array is indexed from 0 to the value returned by the property minus 1: -:::code language="csharp" interactive="try-dotnet-method" source="../../../samples/snippets/csharp/how-to/strings/ParseStringsUsingSplit.cs" id="Snippet1.5"::: +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/strings/ParseStringsUsingSplit.cs" id="Snippet1.5"::: Consecutive separator characters produce the empty string as a value in the returned array. You can see how an empty string is created in the following example, which uses the space character as a separator. -:::code language="csharp" interactive="try-dotnet-method" source="../../../samples/snippets/csharp/how-to/strings/ParseStringsUsingSplit.cs" id="Snippet2"::: +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/strings/ParseStringsUsingSplit.cs" id="Snippet2"::: This behavior makes it easier for formats like comma-separated values (CSV) files representing tabular data. Consecutive commas represent a blank column. @@ -40,15 +40,15 @@ You can pass an optional can use multiple separator characters. The following example uses spaces, commas, periods, colons, and tabs as separating characters, which are passed to in an array. The loop at the bottom of the code displays each of the words in the returned array. -:::code language="csharp" interactive="try-dotnet-method" source="../../../samples/snippets/csharp/how-to/strings/ParseStringsUsingSplit.cs" id="Snippet3"::: +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/strings/ParseStringsUsingSplit.cs" id="Snippet3"::: Consecutive instances of any separator produce the empty string in the output array: -:::code language="csharp" interactive="try-dotnet-method" source="../../../samples/snippets/csharp/how-to/strings/ParseStringsUsingSplit.cs" id="Snippet4"::: +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/strings/ParseStringsUsingSplit.cs" id="Snippet4"::: can take an array of strings (character sequences that act as separators for parsing the target string, instead of single characters). -:::code language="csharp" interactive="try-dotnet-method" source="../../../samples/snippets/csharp/how-to/strings/ParseStringsUsingSplit.cs" id="Snippet5"::: +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/strings/ParseStringsUsingSplit.cs" id="Snippet5"::: ## Use GitHub Copilot to split a string diff --git a/docs/csharp/how-to/search-strings.md b/docs/csharp/how-to/search-strings.md index fe7cd0f298a9d..7d3733ce39d97 100644 --- a/docs/csharp/how-to/search-strings.md +++ b/docs/csharp/how-to/search-strings.md @@ -21,7 +21,7 @@ The [string](../language-reference/builtin-types/reference-types.md#the-string-t The , , and methods search a string for specific text. The following example shows each of these methods and a variation that uses a case-insensitive search: -:::code language="csharp" interactive="try-dotnet-method" source="../../../samples/snippets/csharp/how-to/strings/SearchStrings.cs" id="Snippet1"::: +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/strings/SearchStrings.cs" id="Snippet1"::: The preceding example demonstrates an important point for using these methods. Searches are **case-sensitive** by default. You use the enumeration value to specify a case-insensitive search. @@ -29,7 +29,7 @@ The preceding example demonstrates an important point for using these methods. S The and methods also search for text in strings. These methods return the location of the text being sought. If the text isn't found, they return `-1`. The following example shows a search for the first and last occurrence of the word "methods" and displays the text in between. -:::code language="csharp" interactive="try-dotnet-method" source="../../../samples/snippets/csharp/how-to/strings/SearchStrings.cs" id="Snippet2"::: +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/strings/SearchStrings.cs" id="Snippet2"::: ## Finding specific text using regular expressions @@ -45,7 +45,7 @@ The search pattern describes the text you search for. The following table descri | `(eir)?` | match 0 or 1 occurrence of "eir" | | `\s` | match a white-space character | -:::code language="csharp" interactive="try-dotnet-method" source="../../../samples/snippets/csharp/how-to/strings/SearchStrings.cs" id="Snippet3"::: +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/strings/SearchStrings.cs" id="Snippet3"::: > [!TIP] > The `string` methods are usually better choices when you are searching for an exact string. Regular expressions are better when you are searching for some pattern in a source string. @@ -62,7 +62,7 @@ The following code uses regular expressions to validate the format of each strin | `\d{4}` | matches exactly 4 digit characters | | `$` | matches the end of the string | -:::code language="csharp" interactive="try-dotnet-method" source="../../../samples/snippets/csharp/how-to/strings/SearchStrings.cs" id="Snippet4"::: +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/\strings/SearchStrings.cs" id="Snippet4"::: This single search pattern matches many valid strings. Regular expressions are better to search for or validate against a pattern, rather than a single text string. diff --git a/docs/csharp/how-to/snippets/strings/CompareStrings.cs b/docs/csharp/how-to/snippets/strings/CompareStrings.cs new file mode 100644 index 0000000000000..00838afd46729 --- /dev/null +++ b/docs/csharp/how-to/snippets/strings/CompareStrings.cs @@ -0,0 +1,338 @@ +namespace HowToStrings; + +public static class CompareStrings +{ + public static void Examples() + { + OrdinalDefaultComparisons(); + OrdinalIgnoreCaseComparisons(); + WordSortOrderInvariantCulture(); + LinguisticComparisons(); + + SortArrayOfStrings(); + SearchSortedArray(); + + SortListOfStrings(); + SearchSortedList(); + } + + private static void OrdinalDefaultComparisons() + { + // + string root = @"C:\users"; + string root2 = @"C:\Users"; + + bool result = root.Equals(root2); + Console.WriteLine($"Ordinal comparison: <{root}> and <{root2}> are {(result ? "equal." : "not equal.")}"); + + result = root.Equals(root2, StringComparison.Ordinal); + Console.WriteLine($"Ordinal comparison: <{root}> and <{root2}> are {(result ? "equal." : "not equal.")}"); + + Console.WriteLine($"Using == says that <{root}> and <{root2}> are {(root == root2 ? "equal" : "not equal")}"); + // + } + + private static void OrdinalIgnoreCaseComparisons() + { + // + string root = @"C:\users"; + string root2 = @"C:\Users"; + + bool result = root.Equals(root2, StringComparison.OrdinalIgnoreCase); + bool areEqual = String.Equals(root, root2, StringComparison.OrdinalIgnoreCase); + int comparison = String.Compare(root, root2, comparisonType: StringComparison.OrdinalIgnoreCase); + + Console.WriteLine($"Ordinal ignore case: <{root}> and <{root2}> are {(result ? "equal." : "not equal.")}"); + Console.WriteLine($"Ordinal static ignore case: <{root}> and <{root2}> are {(areEqual ? "equal." : "not equal.")}"); + if (comparison < 0) + { + Console.WriteLine($"<{root}> is less than <{root2}>"); + } + else if (comparison > 0) + { + Console.WriteLine($"<{root}> is greater than <{root2}>"); + } + else + { + Console.WriteLine($"<{root}> and <{root2}> are equivalent in order"); + } + // + } + + private static void WordSortOrderInvariantCulture() + { + // + string first = "Sie tanzen auf der Straße."; + string second = "Sie tanzen auf der Strasse."; + + Console.WriteLine($"First sentence is <{first}>"); + Console.WriteLine($"Second sentence is <{second}>"); + + bool equal = String.Equals(first, second, StringComparison.InvariantCulture); + Console.WriteLine($"The two strings {(equal == true ? "are" : "are not")} equal."); + showComparison(first, second); + + string word = "coop"; + string words = "co-op"; + string other = "cop"; + + showComparison(word, words); + showComparison(word, other); + showComparison(words, other); + void showComparison(string one, string two) + { + int compareLinguistic = String.Compare(one, two, StringComparison.InvariantCulture); + int compareOrdinal = String.Compare(one, two, StringComparison.Ordinal); + if (compareLinguistic < 0) + { + Console.WriteLine($"<{one}> is less than <{two}> using invariant culture"); + } + else if (compareLinguistic > 0) + { + Console.WriteLine($"<{one}> is greater than <{two}> using invariant culture"); + } + else + { + Console.WriteLine($"<{one}> and <{two}> are equivalent in order using invariant culture"); + } + + if (compareOrdinal < 0) + { + Console.WriteLine($"<{one}> is less than <{two}> using ordinal comparison"); + } + else if (compareOrdinal > 0) + { + Console.WriteLine($"<{one}> is greater than <{two}> using ordinal comparison"); + } + else + { + Console.WriteLine($"<{one}> and <{two}> are equivalent in order using ordinal comparison"); + } + } + // + } + private static void LinguisticComparisons() + { + // + string first = "Sie tanzen auf der Straße."; + string second = "Sie tanzen auf der Strasse."; + + Console.WriteLine($"First sentence is <{first}>"); + Console.WriteLine($"Second sentence is <{second}>"); + + var en = new System.Globalization.CultureInfo("en-US"); + + // For culture-sensitive comparisons, use the String.Compare + // overload that takes a StringComparison value. + int i = String.Compare(first, second, en, System.Globalization.CompareOptions.None); + Console.WriteLine($"Comparing in {en.Name} returns {i}."); + + var de = new System.Globalization.CultureInfo("de-DE"); + i = String.Compare(first, second, de, System.Globalization.CompareOptions.None); + Console.WriteLine($"Comparing in {de.Name} returns {i}."); + + bool b = String.Equals(first, second, StringComparison.CurrentCulture); + Console.WriteLine($"The two strings {(b ? "are" : "are not")} equal."); + + string word = "coop"; + string words = "co-op"; + string other = "cop"; + + showComparison(word, words, en); + showComparison(word, other, en); + showComparison(words, other, en); + void showComparison(string one, string two, System.Globalization.CultureInfo culture) + { + int compareLinguistic = String.Compare(one, two, en, System.Globalization.CompareOptions.None); + int compareOrdinal = String.Compare(one, two, StringComparison.Ordinal); + if (compareLinguistic < 0) + { + Console.WriteLine($"<{one}> is less than <{two}> using en-US culture"); + } + else if (compareLinguistic > 0) + { + Console.WriteLine($"<{one}> is greater than <{two}> using en-US culture"); + } + else + { + Console.WriteLine($"<{one}> and <{two}> are equivalent in order using en-US culture"); + } + + if (compareOrdinal < 0) + { + Console.WriteLine($"<{one}> is less than <{two}> using ordinal comparison"); + } + else if (compareOrdinal > 0) + { + Console.WriteLine($"<{one}> is greater than <{two}> using ordinal comparison"); + } + else + { + Console.WriteLine($"<{one}> and <{two}> are equivalent in order using ordinal comparison"); + } + } + // + } + + private static void SortArrayOfStrings() + { + // + string[] lines = new string[] + { + @"c:\public\textfile.txt", + @"c:\public\textFile.TXT", + @"c:\public\Text.txt", + @"c:\public\testfile2.txt" + }; + + Console.WriteLine("Non-sorted order:"); + foreach (string s in lines) + { + Console.WriteLine($" {s}"); + } + + Console.WriteLine("\n\rSorted order:"); + + // Specify Ordinal to demonstrate the different behavior. + Array.Sort(lines, StringComparer.CurrentCulture); + + foreach (string s in lines) + { + Console.WriteLine($" {s}"); + } + // + } + + private static void SearchSortedArray() + { + // + string[] lines = + [ + @"c:\public\textfile.txt", + @"c:\public\textFile.TXT", + @"c:\public\Text.txt", + @"c:\public\testfile2.txt" + ]; + Array.Sort(lines, StringComparer.CurrentCulture); + + string searchString = @"c:\public\TEXTFILE.TXT"; + Console.WriteLine($"Binary search for <{searchString}>"); + int result = Array.BinarySearch(lines, searchString, StringComparer.CurrentCulture); + ShowWhere(lines, result); + + Console.WriteLine($"{(result > 0 ? "Found" : "Did not find")} {searchString}"); + + void ShowWhere(T[] array, int index) + { + if (index < 0) + { + index = ~index; + + Console.Write("Not found. Sorts between: "); + + if (index == 0) + { + Console.Write("beginning of sequence and "); + } + else + { + Console.Write($"{array[index - 1]} and "); + } + + if (index == array.Length) + { + Console.WriteLine("end of sequence."); + } + else + { + Console.WriteLine($"{array[index]}."); + } + } + else + { + Console.WriteLine($"Found at index {index}."); + } + } + // + } + + private static void SortListOfStrings() + { + // + List lines = + [ + @"c:\public\textfile.txt", + @"c:\public\textFile.TXT", + @"c:\public\Text.txt", + @"c:\public\testfile2.txt" + ]; + + Console.WriteLine("Non-sorted order:"); + foreach (string s in lines) + { + Console.WriteLine($" {s}"); + } + + Console.WriteLine("\n\rSorted order:"); + + lines.Sort((left, right) => left.CompareTo(right)); + foreach (string s in lines) + { + Console.WriteLine($" {s}"); + } + // + } + + private static void SearchSortedList() + { + // + List lines = + [ + @"c:\public\textfile.txt", + @"c:\public\textFile.TXT", + @"c:\public\Text.txt", + @"c:\public\testfile2.txt" + ]; + lines.Sort((left, right) => left.CompareTo(right)); + + string searchString = @"c:\public\TEXTFILE.TXT"; + Console.WriteLine($"Binary search for <{searchString}>"); + int result = lines.BinarySearch(searchString); + ShowWhere(lines, result); + + Console.WriteLine($"{(result > 0 ? "Found" : "Did not find")} {searchString}"); + + void ShowWhere(IList collection, int index) + { + if (index < 0) + { + index = ~index; + + Console.Write("Not found. Sorts between: "); + + if (index == 0) + { + Console.Write("beginning of sequence and "); + } + else + { + Console.Write($"{collection[index - 1]} and "); + } + + if (index == collection.Count) + { + Console.WriteLine("end of sequence."); + } + else + { + Console.WriteLine($"{collection[index]}."); + } + } + else + { + Console.WriteLine($"Found at index {index}."); + } + } + // + } +} diff --git a/docs/csharp/how-to/snippets/strings/Concatenate.cs b/docs/csharp/how-to/snippets/strings/Concatenate.cs new file mode 100644 index 0000000000000..b3e10829c5b20 --- /dev/null +++ b/docs/csharp/how-to/snippets/strings/Concatenate.cs @@ -0,0 +1,100 @@ +using System.Text; + +namespace HowToStrings; + +static public class Concatenate +{ + public static void Examples() + { + UsingAddWithConstantStrings(); + UsingAddWithVariables(); + UsingInterpolationWithVariables(); + UsingStringBuilder(); + UsingConcatAndJoin(); + UsingAggregate(); + } + + private static void UsingAddWithConstantStrings() + { + // + // Concatenation of literals is performed at compile time, not run time. + string text = "Historically, the world of data and the world of objects " + + "have not been well integrated. Programmers work in C# or Visual Basic " + + "and also in SQL or XQuery. On the one side are concepts such as classes, " + + "objects, fields, inheritance, and .NET Framework APIs. On the other side " + + "are tables, columns, rows, nodes, and separate languages for dealing with " + + "them. Data types often require translation between the two worlds; there are " + + "different standard functions. Because the object world has no notion of query, a " + + "query can only be represented as a string without compile-time type checking or " + + "IntelliSense support in the IDE. Transferring data from SQL tables or XML trees to " + + "objects in memory is often tedious and error-prone."; + + Console.WriteLine(text); + // + } + + private static void UsingAddWithVariables() + { + // + string userName = ""; + string dateString = DateTime.Today.ToShortDateString(); + + // Use the + and += operators for one-time concatenations. + string str = "Hello " + userName + ". Today is " + dateString + "."; + Console.WriteLine(str); + + str += " How are you today?"; + Console.WriteLine(str); + // + } + private static void UsingInterpolationWithVariables() + { + // + string userName = ""; + string date = DateTime.Today.ToShortDateString(); + + // Use string interpolation to concatenate strings. + string str = $"Hello {userName}. Today is {date}."; + Console.WriteLine(str); + + str = $"{str} How are you today?"; + Console.WriteLine(str); + // + } + + private static void UsingStringBuilder() + { + // + // Use StringBuilder for concatenation in tight loops. + var sb = new StringBuilder(); + for (int i = 0; i < 20; i++) + { + sb.AppendLine(i.ToString()); + } + Console.WriteLine(sb.ToString()); + // + } + + private static void UsingConcatAndJoin() + { + // + string[] words = ["The", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog."]; + + var unreadablePhrase = string.Concat(words); + Console.WriteLine(unreadablePhrase); + + var readablePhrase = string.Join(" ", words); + Console.WriteLine(readablePhrase); + // + } + + private static void UsingAggregate() + { + // + string[] words = ["The", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog."]; + + var phrase = words.Aggregate((partialPhrase, word) =>$"{partialPhrase} {word}"); + Console.WriteLine(phrase); + // + } +} diff --git a/docs/csharp/how-to/snippets/strings/ModifyStrings.cs b/docs/csharp/how-to/snippets/strings/ModifyStrings.cs new file mode 100644 index 0000000000000..68982c1dd1e60 --- /dev/null +++ b/docs/csharp/how-to/snippets/strings/ModifyStrings.cs @@ -0,0 +1,144 @@ +namespace HowToStrings; + +public static class ModifyStrings +{ + public static void Examples() + { + ReplaceCreatesNewString(); + ReplaceChars(); + TrimWhitespace(); + RemoveText(); + ReplaceWithRegEx(); + ReplaceCharArray(); + UsingStringCreate(); + } + + private static void ReplaceCreatesNewString() + { + // + string source = "The mountains are behind the clouds today."; + + // Replace one substring with another with String.Replace. + // Only exact matches are supported. + var replacement = source.Replace("mountains", "peaks"); + Console.WriteLine($"The source string is <{source}>"); + Console.WriteLine($"The updated string is <{replacement}>"); + // + } + + private static void ReplaceChars() + { + // + string source = "The mountains are behind the clouds today."; + + // Replace all occurrences of one char with another. + var replacement = source.Replace(' ', '_'); + Console.WriteLine(source); + Console.WriteLine(replacement); + // + } + + private static void TrimWhitespace() + { + // + // Remove trailing and leading white space. + string source = " I'm wider than I need to be. "; + // Store the results in a new string variable. + var trimmedResult = source.Trim(); + var trimLeading = source.TrimStart(); + var trimTrailing = source.TrimEnd(); + Console.WriteLine($"<{source}>"); + Console.WriteLine($"<{trimmedResult}>"); + Console.WriteLine($"<{trimLeading}>"); + Console.WriteLine($"<{trimTrailing}>"); + // + } + + private static void RemoveText() + { + // + string source = "Many mountains are behind many clouds today."; + // Remove a substring from the middle of the string. + string toRemove = "many "; + string result = string.Empty; + int i = source.IndexOf(toRemove); + if (i >= 0) + { + result= source.Remove(i, toRemove.Length); + } + Console.WriteLine(source); + Console.WriteLine(result); + // + } + + private static void ReplaceWithRegEx() + { + // + string source = "The mountains are still there behind the clouds today."; + + // Use Regex.Replace for more flexibility. + // Replace "the" or "The" with "many" or "Many". + // using System.Text.RegularExpressions + string replaceWith = "many "; + source = System.Text.RegularExpressions.Regex.Replace(source, """the\s""", LocalReplaceMatchCase, + System.Text.RegularExpressions.RegexOptions.IgnoreCase); + Console.WriteLine(source); + + string LocalReplaceMatchCase(System.Text.RegularExpressions.Match matchExpression) + { + // Test whether the match is capitalized + if (Char.IsUpper(matchExpression.Value[0])) + { + // Capitalize the replacement string + System.Text.StringBuilder replacementBuilder = new System.Text.StringBuilder(replaceWith); + replacementBuilder[0] = Char.ToUpper(replacementBuilder[0]); + return replacementBuilder.ToString(); + } + else + { + return replaceWith; + } + } + // + } + + private static void ReplaceCharArray() + { + // + string phrase = "The quick brown fox jumps over the fence"; + Console.WriteLine(phrase); + + char[] phraseAsChars = phrase.ToCharArray(); + int animalIndex = phrase.IndexOf("fox"); + if (animalIndex != -1) + { + phraseAsChars[animalIndex++] = 'c'; + phraseAsChars[animalIndex++] = 'a'; + phraseAsChars[animalIndex] = 't'; + } + + string updatedPhrase = new string(phraseAsChars); + Console.WriteLine(updatedPhrase); + // + } + + private static void UsingStringCreate() + { + // + // constructing a string from a char array, prefix it with some additional characters + char[] chars = [ 'a', 'b', 'c', 'd', '\0' ]; + int length = chars.Length + 2; + string result = string.Create(length, chars, (Span strContent, char[] charArray) => + { + strContent[0] = '0'; + strContent[1] = '1'; + for (int i = 0; i < charArray.Length; i++) + { + strContent[i + 2] = charArray[i]; + } + }); + + Console.WriteLine(result); + // + } +} diff --git a/docs/csharp/how-to/snippets/strings/ParseStringsUsingSplit.cs b/docs/csharp/how-to/snippets/strings/ParseStringsUsingSplit.cs new file mode 100644 index 0000000000000..c2da2416e2a22 --- /dev/null +++ b/docs/csharp/how-to/snippets/strings/ParseStringsUsingSplit.cs @@ -0,0 +1,141 @@ +namespace HowToStrings; + +public static class ParseStringsUsingSplit +{ + public static void Examples() + { + Console.WriteLine("Split words"); + Console.WriteLine(); + SplitWords(); + + Console.WriteLine("Enumerate words"); + Console.WriteLine(); + EnumerateWords(); + + Console.WriteLine("Split words with repeated separators"); + Console.WriteLine(); + SplitWordsWithRepeatedSeparators(); + + Console.WriteLine("Split on multiple chars"); + Console.WriteLine(); + SplitOnMultipleChars(); + + Console.WriteLine("Split on multiple chars with gaps"); + Console.WriteLine(); + SplitOnMultipleCharsWithGaps(); + + Console.WriteLine("Split using strings"); + Console.WriteLine(); + SplitUsingStrings(); + + Console.WriteLine("Split into no more than four substrings"); + Console.WriteLine(); + SplitFourTimes(); + } + + private static void SplitWords() + { + // + string phrase = "The quick brown fox jumps over the lazy dog."; + string[] words = phrase.Split(' '); + + foreach (var word in words) + { + Console.WriteLine($"<{word}>"); + } + // + } + + private static void EnumerateWords() + { + // + string phrase = "The quick brown fox jumps over the lazy dog."; + string[] words = phrase.Split(' '); + + for (int i = 0; i < words.Length; i++) + { + Console.WriteLine($"Index {i}: <{words[i]}>"); + } + // + } + + private static void SplitWordsWithRepeatedSeparators() + { + // + string phrase = "The quick brown fox jumps over the lazy dog."; + string[] words = phrase.Split(' '); + + foreach (var word in words) + { + Console.WriteLine($"<{word}>"); + } + // + } + + private static void SplitOnMultipleChars() + { + // + char[] delimiterChars = [' ', ',', '.', ':', '\t']; + + string text = "one\ttwo three:four,five six seven"; + Console.WriteLine($"Original text: '{text}'"); + + string[] words = text.Split(delimiterChars); + Console.WriteLine($"{words.Length} words in text:"); + + foreach (var word in words) + { + Console.WriteLine($"<{word}>"); + } + // + } + + private static void SplitOnMultipleCharsWithGaps() + { + // + char[] delimiterChars = [' ', ',', '.', ':', '\t']; + + string text = "one\ttwo :,five six seven"; + Console.WriteLine($"Original text: '{text}'"); + + string[] words = text.Split(delimiterChars); + Console.WriteLine($"{words.Length} words in text:"); + + foreach (var word in words) + { + Console.WriteLine($"<{word}>"); + } + // + } + + private static void SplitUsingStrings() + { + // + string[] separatingStrings = ["<<", "..."]; + + string text = "one< + } + + private static void SplitFourTimes() + { + // + string phrase = "The quick brown fox jumps over the lazy dog."; + string[] words = phrase.Split(' ', 4, StringSplitOptions.None); + + foreach (var word in words) + { + Console.WriteLine($"<{word}>"); + } + // + } +} diff --git a/docs/csharp/how-to/snippets/strings/Program.cs b/docs/csharp/how-to/snippets/strings/Program.cs new file mode 100644 index 0000000000000..78067d0124cfb --- /dev/null +++ b/docs/csharp/how-to/snippets/strings/Program.cs @@ -0,0 +1,17 @@ +using HowToStrings; + +Console.WriteLine("============================ String.Split examples ================================================="); +Console.WriteLine(); +ParseStringsUsingSplit.Examples(); +Console.WriteLine("============================ String concatenation examples ================================================="); +Console.WriteLine(); +Concatenate.Examples(); +Console.WriteLine("============================ String Searching examples ================================================="); +Console.WriteLine(); +SearchStrings.Examples(); +Console.WriteLine("============================ Modify string examples ================================================="); +Console.WriteLine(); +ModifyStrings.Examples(); +Console.WriteLine("============================ Compare string examples ================================================="); +Console.WriteLine(); +CompareStrings.Examples(); diff --git a/docs/csharp/how-to/snippets/strings/SearchStrings.cs b/docs/csharp/how-to/snippets/strings/SearchStrings.cs new file mode 100644 index 0000000000000..7dbf3702f50a6 --- /dev/null +++ b/docs/csharp/how-to/snippets/strings/SearchStrings.cs @@ -0,0 +1,117 @@ +namespace HowToStrings; + +public class SearchStrings +{ + public static void Examples() + { + SearchWithMethods(); + SearchByIndex(); + RegularExpressionsOne(); + RegularExpressionsValidation(); + } + + private static void SearchWithMethods() + { + // + string factMessage = "Extension methods have all the capabilities of regular static methods."; + + // Write the string and include the quotation marks. + Console.WriteLine($"\"{factMessage}\""); + + // Simple comparisons are always case sensitive! + bool containsSearchResult = factMessage.Contains("extension"); + // Raw string literals can work here because the output doesn't begin with " + Console.WriteLine($"""Contains "extension"? {containsSearchResult}"""); + + // For user input and strings that will be displayed to the end user, + // use the StringComparison parameter on methods that have it to specify how to match strings. + bool ignoreCaseSearchResult = factMessage.StartsWith("extension", System.StringComparison.CurrentCultureIgnoreCase); + Console.WriteLine($"""Starts with "extension"? {ignoreCaseSearchResult} (ignoring case)"""); + + bool endsWithSearchResult = factMessage.EndsWith(".", System.StringComparison.CurrentCultureIgnoreCase); + Console.WriteLine($"Ends with '.'? {endsWithSearchResult}"); + // + } + + private static void SearchByIndex() + { + // + string factMessage = "Extension methods have all the capabilities of regular static methods."; + + // Write the string and include the quotation marks. + Console.WriteLine($"\"{factMessage}\""); + + // This search returns the substring between two strings, so + // the first index is moved to the character just after the first string. + int first = factMessage.IndexOf("methods") + "methods".Length; + int last = factMessage.LastIndexOf("methods"); + string str2 = factMessage.Substring(first, last - first); + Console.WriteLine($"""Substring between "methods" and "methods": '{str2}'"""); + // + } + + private static void RegularExpressionsOne() + { + // + string[] sentences = + [ + "Put the water over there.", + "They're quite thirsty.", + "Their water bottles broke." + ]; + + string sPattern = "the(ir)?\\s"; + + foreach (string s in sentences) + { + Console.Write($"{s,24}"); + + if (System.Text.RegularExpressions.Regex.IsMatch(s, sPattern, System.Text.RegularExpressions.RegexOptions.IgnoreCase)) + { + Console.WriteLine($" (match for '{sPattern}' found)"); + } + else + { + Console.WriteLine(); + } + } + // + } + + private static void RegularExpressionsValidation() + { + // + string[] numbers = + [ + "123-555-0190", + "444-234-22450", + "690-555-0178", + "146-893-232", + "146-555-0122", + "4007-555-0111", + "407-555-0111", + "407-2-5555", + "407-555-8974", + "407-2ab-5555", + "690-555-8148", + "146-893-232-" + ]; + + string sPattern = """^\d{3}-\\d{3}\d{4}$"""; + + foreach (string s in numbers) + { + Console.Write($"{s,14}"); + + if (System.Text.RegularExpressions.Regex.IsMatch(s, sPattern)) + { + Console.WriteLine(" - valid"); + } + else + { + Console.WriteLine(" - invalid"); + } + } + // + } +} diff --git a/samples/snippets/csharp/how-to/strings/strings.csproj b/docs/csharp/how-to/snippets/strings/strings.csproj similarity index 62% rename from samples/snippets/csharp/how-to/strings/strings.csproj rename to docs/csharp/how-to/snippets/strings/strings.csproj index bccebfef5e970..eeafa373ee0cf 100644 --- a/samples/snippets/csharp/how-to/strings/strings.csproj +++ b/docs/csharp/how-to/snippets/strings/strings.csproj @@ -1,9 +1,10 @@ - + Exe - net8.0 + net9.0 enable + enable HowToStrings true diff --git a/docs/csharp/language-reference/operators/snippets/shared/operators.csproj b/docs/csharp/language-reference/operators/snippets/shared/operators.csproj index 390b98aae042c..c4ecbf112275d 100644 --- a/docs/csharp/language-reference/operators/snippets/shared/operators.csproj +++ b/docs/csharp/language-reference/operators/snippets/shared/operators.csproj @@ -1,8 +1,8 @@ - + Exe - net8.0 + net9.0 enable true true diff --git a/samples/snippets/csharp/how-to/strings/CompareStrings.cs b/samples/snippets/csharp/how-to/strings/CompareStrings.cs deleted file mode 100644 index 1fb3568e3a18d..0000000000000 --- a/samples/snippets/csharp/how-to/strings/CompareStrings.cs +++ /dev/null @@ -1,296 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using System.Text; - -namespace HowToStrings -{ - public static class CompareStrings - { - public static void Examples() - { - OrdinalDefaultComparisons(); - OrdinalIgnoreCaseComparisons(); - WordSortOrderInvariantCulture(); - LinguisticComparisons(); - - SortArrayOfStrings(); - SearchSortedArray(); - - SortListOfStrings(); - SearchSortedList(); - } - - private static void OrdinalDefaultComparisons() - { - // - string root = @"C:\users"; - string root2 = @"C:\Users"; - - bool result = root.Equals(root2); - Console.WriteLine($"Ordinal comparison: <{root}> and <{root2}> are {(result ? "equal." : "not equal.")}"); - - result = root.Equals(root2, StringComparison.Ordinal); - Console.WriteLine($"Ordinal comparison: <{root}> and <{root2}> are {(result ? "equal." : "not equal.")}"); - - Console.WriteLine($"Using == says that <{root}> and <{root2}> are {(root == root2 ? "equal" : "not equal")}"); - // - } - - private static void OrdinalIgnoreCaseComparisons() - { - // - string root = @"C:\users"; - string root2 = @"C:\Users"; - - bool result = root.Equals(root2, StringComparison.OrdinalIgnoreCase); - bool areEqual = String.Equals(root, root2, StringComparison.OrdinalIgnoreCase); - int comparison = String.Compare(root, root2, comparisonType: StringComparison.OrdinalIgnoreCase); - - Console.WriteLine($"Ordinal ignore case: <{root}> and <{root2}> are {(result ? "equal." : "not equal.")}"); - Console.WriteLine($"Ordinal static ignore case: <{root}> and <{root2}> are {(areEqual ? "equal." : "not equal.")}"); - if (comparison < 0) - Console.WriteLine($"<{root}> is less than <{root2}>"); - else if (comparison > 0) - Console.WriteLine($"<{root}> is greater than <{root2}>"); - else - Console.WriteLine($"<{root}> and <{root2}> are equivalent in order"); - // - } - - private static void WordSortOrderInvariantCulture() - { - // - string first = "Sie tanzen auf der Straße."; - string second = "Sie tanzen auf der Strasse."; - - Console.WriteLine($"First sentence is <{first}>"); - Console.WriteLine($"Second sentence is <{second}>"); - - bool equal = String.Equals(first, second, StringComparison.InvariantCulture); - Console.WriteLine($"The two strings {(equal == true ? "are" : "are not")} equal."); - showComparison(first, second); - - string word = "coop"; - string words = "co-op"; - string other = "cop"; - - showComparison(word, words); - showComparison(word, other); - showComparison(words, other); - void showComparison(string one, string two) - { - int compareLinguistic = String.Compare(one, two, StringComparison.InvariantCulture); - int compareOrdinal = String.Compare(one, two, StringComparison.Ordinal); - if (compareLinguistic < 0) - Console.WriteLine($"<{one}> is less than <{two}> using invariant culture"); - else if (compareLinguistic > 0) - Console.WriteLine($"<{one}> is greater than <{two}> using invariant culture"); - else - Console.WriteLine($"<{one}> and <{two}> are equivalent in order using invariant culture"); - if (compareOrdinal < 0) - Console.WriteLine($"<{one}> is less than <{two}> using ordinal comparison"); - else if (compareOrdinal > 0) - Console.WriteLine($"<{one}> is greater than <{two}> using ordinal comparison"); - else - Console.WriteLine($"<{one}> and <{two}> are equivalent in order using ordinal comparison"); - } - // - } - private static void LinguisticComparisons() - { - // - string first = "Sie tanzen auf der Straße."; - string second = "Sie tanzen auf der Strasse."; - - Console.WriteLine($"First sentence is <{first}>"); - Console.WriteLine($"Second sentence is <{second}>"); - - var en = new System.Globalization.CultureInfo("en-US"); - - // For culture-sensitive comparisons, use the String.Compare - // overload that takes a StringComparison value. - int i = String.Compare(first, second, en, System.Globalization.CompareOptions.None); - Console.WriteLine($"Comparing in {en.Name} returns {i}."); - - var de = new System.Globalization.CultureInfo("de-DE"); - i = String.Compare(first, second, de, System.Globalization.CompareOptions.None); - Console.WriteLine($"Comparing in {de.Name} returns {i}."); - - bool b = String.Equals(first, second, StringComparison.CurrentCulture); - Console.WriteLine($"The two strings {(b ? "are" : "are not")} equal."); - - string word = "coop"; - string words = "co-op"; - string other = "cop"; - - showComparison(word, words, en); - showComparison(word, other, en); - showComparison(words, other, en); - void showComparison(string one, string two, System.Globalization.CultureInfo culture) - { - int compareLinguistic = String.Compare(one, two, en, System.Globalization.CompareOptions.None); - int compareOrdinal = String.Compare(one, two, StringComparison.Ordinal); - if (compareLinguistic < 0) - Console.WriteLine($"<{one}> is less than <{two}> using en-US culture"); - else if (compareLinguistic > 0) - Console.WriteLine($"<{one}> is greater than <{two}> using en-US culture"); - else - Console.WriteLine($"<{one}> and <{two}> are equivalent in order using en-US culture"); - if (compareOrdinal < 0) - Console.WriteLine($"<{one}> is less than <{two}> using ordinal comparison"); - else if (compareOrdinal > 0) - Console.WriteLine($"<{one}> is greater than <{two}> using ordinal comparison"); - else - Console.WriteLine($"<{one}> and <{two}> are equivalent in order using ordinal comparison"); - } - // - } - - private static void SortArrayOfStrings() - { - // - string[] lines = new string[] - { - @"c:\public\textfile.txt", - @"c:\public\textFile.TXT", - @"c:\public\Text.txt", - @"c:\public\testfile2.txt" - }; - - Console.WriteLine("Non-sorted order:"); - foreach (string s in lines) - { - Console.WriteLine($" {s}"); - } - - Console.WriteLine("\n\rSorted order:"); - - // Specify Ordinal to demonstrate the different behavior. - Array.Sort(lines, StringComparer.CurrentCulture); - - foreach (string s in lines) - { - Console.WriteLine($" {s}"); - } - // - } - - private static void SearchSortedArray() - { - // - string[] lines = new string[] - { - @"c:\public\textfile.txt", - @"c:\public\textFile.TXT", - @"c:\public\Text.txt", - @"c:\public\testfile2.txt" - }; - Array.Sort(lines, StringComparer.CurrentCulture); - - string searchString = @"c:\public\TEXTFILE.TXT"; - Console.WriteLine($"Binary search for <{searchString}>"); - int result = Array.BinarySearch(lines, searchString, StringComparer.CurrentCulture); - ShowWhere(lines, result); - - Console.WriteLine($"{(result > 0 ? "Found" : "Did not find")} {searchString}"); - - void ShowWhere(T[] array, int index) - { - if (index < 0) - { - index = ~index; - - Console.Write("Not found. Sorts between: "); - - if (index == 0) - Console.Write("beginning of sequence and "); - else - Console.Write($"{array[index - 1]} and "); - - if (index == array.Length) - Console.WriteLine("end of sequence."); - else - Console.WriteLine($"{array[index]}."); - } - else - { - Console.WriteLine($"Found at index {index}."); - } - } - // - } - - private static void SortListOfStrings() - { - // - List lines = new List - { - @"c:\public\textfile.txt", - @"c:\public\textFile.TXT", - @"c:\public\Text.txt", - @"c:\public\testfile2.txt" - }; - - Console.WriteLine("Non-sorted order:"); - foreach (string s in lines) - { - Console.WriteLine($" {s}"); - } - - Console.WriteLine("\n\rSorted order:"); - - lines.Sort((left, right) => left.CompareTo(right)); - foreach (string s in lines) - { - Console.WriteLine($" {s}"); - } - // - } - - private static void SearchSortedList() - { - // - List lines = new List - { - @"c:\public\textfile.txt", - @"c:\public\textFile.TXT", - @"c:\public\Text.txt", - @"c:\public\testfile2.txt" - }; - lines.Sort((left, right) => left.CompareTo(right)); - - string searchString = @"c:\public\TEXTFILE.TXT"; - Console.WriteLine($"Binary search for <{searchString}>"); - int result = lines.BinarySearch(searchString); - ShowWhere(lines, result); - - Console.WriteLine($"{(result > 0 ? "Found" : "Did not find")} {searchString}"); - - void ShowWhere(IList collection, int index) - { - if (index < 0) - { - index = ~index; - - Console.Write("Not found. Sorts between: "); - - if (index == 0) - Console.Write("beginning of sequence and "); - else - Console.Write($"{collection[index - 1]} and "); - - if (index == collection.Count) - Console.WriteLine("end of sequence."); - else - Console.WriteLine($"{collection[index]}."); - } - else - { - Console.WriteLine($"Found at index {index}."); - } - } - // - } - } -} diff --git a/samples/snippets/csharp/how-to/strings/Concatenate.cs b/samples/snippets/csharp/how-to/strings/Concatenate.cs deleted file mode 100644 index 4109fa5ec682d..0000000000000 --- a/samples/snippets/csharp/how-to/strings/Concatenate.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System; -using System.Linq; -using System.Collections.Generic; -using System.Text; - -namespace HowToStrings -{ - static public class Concatenate - { - public static void Examples() - { - UsingAddWithConstantStrings(); - UsingAddWithVariables(); - UsingInterpolationWithVariables(); - UsingStringBuilder(); - UsingConcatAndJoin(); - UsingAggregate(); - } - - private static void UsingAddWithConstantStrings() - { - // - // Concatenation of literals is performed at compile time, not run time. - string text = "Historically, the world of data and the world of objects " + - "have not been well integrated. Programmers work in C# or Visual Basic " + - "and also in SQL or XQuery. On the one side are concepts such as classes, " + - "objects, fields, inheritance, and .NET Framework APIs. On the other side " + - "are tables, columns, rows, nodes, and separate languages for dealing with " + - "them. Data types often require translation between the two worlds; there are " + - "different standard functions. Because the object world has no notion of query, a " + - "query can only be represented as a string without compile-time type checking or " + - "IntelliSense support in the IDE. Transferring data from SQL tables or XML trees to " + - "objects in memory is often tedious and error-prone."; - - System.Console.WriteLine(text); - // - } - - private static void UsingAddWithVariables() - { - // - string userName = ""; - string dateString = DateTime.Today.ToShortDateString(); - - // Use the + and += operators for one-time concatenations. - string str = "Hello " + userName + ". Today is " + dateString + "."; - System.Console.WriteLine(str); - - str += " How are you today?"; - System.Console.WriteLine(str); - // - } - private static void UsingInterpolationWithVariables() - { - // - string userName = ""; - string date = DateTime.Today.ToShortDateString(); - - // Use string interpolation to concatenate strings. - string str = $"Hello {userName}. Today is {date}."; - System.Console.WriteLine(str); - - str = $"{str} How are you today?"; - System.Console.WriteLine(str); - // - } - - private static void UsingStringBuilder() - { - // - // Use StringBuilder for concatenation in tight loops. - var sb = new System.Text.StringBuilder(); - for (int i = 0; i < 20; i++) - { - sb.AppendLine(i.ToString()); - } - System.Console.WriteLine(sb.ToString()); - // - } - - private static void UsingConcatAndJoin() - { - // - string[] words = { "The", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog." }; - - var unreadablePhrase = string.Concat(words); - System.Console.WriteLine(unreadablePhrase); - - var readablePhrase = string.Join(" ", words); - System.Console.WriteLine(readablePhrase); - // - } - - private static void UsingAggregate() - { - // - string[] words = { "The", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog." }; - - var phrase = words.Aggregate((partialPhrase, word) =>$"{partialPhrase} {word}"); - System.Console.WriteLine(phrase); - // - } - } -} diff --git a/samples/snippets/csharp/how-to/strings/ModifyStrings.cs b/samples/snippets/csharp/how-to/strings/ModifyStrings.cs deleted file mode 100644 index c68703986b2d4..0000000000000 --- a/samples/snippets/csharp/how-to/strings/ModifyStrings.cs +++ /dev/null @@ -1,149 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Text.RegularExpressions; - -namespace HowToStrings -{ - public static class ModifyStrings - { - public static void Examples() - { - ReplaceCreatesNewString(); - ReplaceChars(); - TrimWhitespace(); - RemoveText(); - ReplaceWithRegEx(); - ReplaceCharArray(); - } - - private static void ReplaceCreatesNewString() - { - // - string source = "The mountains are behind the clouds today."; - - // Replace one substring with another with String.Replace. - // Only exact matches are supported. - var replacement = source.Replace("mountains", "peaks"); - Console.WriteLine($"The source string is <{source}>"); - Console.WriteLine($"The updated string is <{replacement}>"); - // - } - - private static void ReplaceChars() - { - // - string source = "The mountains are behind the clouds today."; - - // Replace all occurrences of one char with another. - var replacement = source.Replace(' ', '_'); - Console.WriteLine(source); - Console.WriteLine(replacement); - // - } - - private static void TrimWhitespace() - { - // - // Remove trailing and leading white space. - string source = " I'm wider than I need to be. "; - // Store the results in a new string variable. - var trimmedResult = source.Trim(); - var trimLeading = source.TrimStart(); - var trimTrailing = source.TrimEnd(); - Console.WriteLine($"<{source}>"); - Console.WriteLine($"<{trimmedResult}>"); - Console.WriteLine($"<{trimLeading}>"); - Console.WriteLine($"<{trimTrailing}>"); - // - } - - private static void RemoveText() - { - // - string source = "Many mountains are behind many clouds today."; - // Remove a substring from the middle of the string. - string toRemove = "many "; - string result = string.Empty; - int i = source.IndexOf(toRemove); - if (i >= 0) - { - result= source.Remove(i, toRemove.Length); - } - Console.WriteLine(source); - Console.WriteLine(result); - // - } - - private static void ReplaceWithRegEx() - { - // - string source = "The mountains are still there behind the clouds today."; - - // Use Regex.Replace for more flexibility. - // Replace "the" or "The" with "many" or "Many". - // using System.Text.RegularExpressions - string replaceWith = "many "; - source = System.Text.RegularExpressions.Regex.Replace(source, "the\\s", LocalReplaceMatchCase, - System.Text.RegularExpressions.RegexOptions.IgnoreCase); - Console.WriteLine(source); - - string LocalReplaceMatchCase(System.Text.RegularExpressions.Match matchExpression) - { - // Test whether the match is capitalized - if (Char.IsUpper(matchExpression.Value[0])) - { - // Capitalize the replacement string - System.Text.StringBuilder replacementBuilder = new System.Text.StringBuilder(replaceWith); - replacementBuilder[0] = Char.ToUpper(replacementBuilder[0]); - return replacementBuilder.ToString(); - } - else - { - return replaceWith; - } - } - // - } - - private static void ReplaceCharArray() - { - // - string phrase = "The quick brown fox jumps over the fence"; - Console.WriteLine(phrase); - - char[] phraseAsChars = phrase.ToCharArray(); - int animalIndex = phrase.IndexOf("fox"); - if (animalIndex != -1) - { - phraseAsChars[animalIndex++] = 'c'; - phraseAsChars[animalIndex++] = 'a'; - phraseAsChars[animalIndex] = 't'; - } - - string updatedPhrase = new string(phraseAsChars); - Console.WriteLine(updatedPhrase); - // - } - - private static void UsingStringCreate() - { - // - // constructing a string from a char array, prefix it with some additional characters - char[] chars = { 'a', 'b', 'c', 'd', '\0' }; - int length = chars.Length + 2; - string result = string.Create(length, chars, (Span strContent, char[] charArray) => - { - strContent[0] = '0'; - strContent[1] = '1'; - for (int i = 0; i < charArray.Length; i++) - { - strContent[i + 2] = charArray[i]; - } - }); - - Console.WriteLine(result); - // - } - } -} diff --git a/samples/snippets/csharp/how-to/strings/ParseStringsUsingSplit.cs b/samples/snippets/csharp/how-to/strings/ParseStringsUsingSplit.cs deleted file mode 100644 index bae0d26ca0b2c..0000000000000 --- a/samples/snippets/csharp/how-to/strings/ParseStringsUsingSplit.cs +++ /dev/null @@ -1,145 +0,0 @@ -using System; -using System.Linq; - -namespace HowToStrings -{ - public static class ParseStringsUsingSplit - { - public static void Examples() - { - Console.WriteLine("Split words"); - Console.WriteLine(); - SplitWords(); - - Console.WriteLine("Enumerate words"); - Console.WriteLine(); - EnumerateWords(); - - Console.WriteLine("Split words with repeated separators"); - Console.WriteLine(); - SplitWordsWithRepeatedSeparators(); - - Console.WriteLine("Split on multiple chars"); - Console.WriteLine(); - SplitOnMultipleChars(); - - Console.WriteLine("Split on multiple chars with gaps"); - Console.WriteLine(); - SplitOnMultipleCharsWithGaps(); - - Console.WriteLine("Split using strings"); - Console.WriteLine(); - SplitUsingStrings(); - - Console.WriteLine("Split into no more than four substrings"); - Console.WriteLine(); - SplitFourTimes(); - } - - private static void SplitWords() - { - // - string phrase = "The quick brown fox jumps over the lazy dog."; - string[] words = phrase.Split(' '); - - foreach (var word in words) - { - System.Console.WriteLine($"<{word}>"); - } - // - } - - private static void EnumerateWords() - { - // - string phrase = "The quick brown fox jumps over the lazy dog."; - string[] words = phrase.Split(' '); - - for (int i = 0; i < words.Length; i++) - { - System.Console.WriteLine($"Index {i}: <{words[i]}>"); - } - // - } - - private static void SplitWordsWithRepeatedSeparators() - { - // - string phrase = "The quick brown fox jumps over the lazy dog."; - string[] words = phrase.Split(' '); - - foreach (var word in words) - { - System.Console.WriteLine($"<{word}>"); - } - // - } - - private static void SplitOnMultipleChars() - { - // - char[] delimiterChars = { ' ', ',', '.', ':', '\t' }; - - string text = "one\ttwo three:four,five six seven"; - System.Console.WriteLine($"Original text: '{text}'"); - - string[] words = text.Split(delimiterChars); - System.Console.WriteLine($"{words.Length} words in text:"); - - foreach (var word in words) - { - System.Console.WriteLine($"<{word}>"); - } - // - } - - private static void SplitOnMultipleCharsWithGaps() - { - // - char[] delimiterChars = { ' ', ',', '.', ':', '\t' }; - - string text = "one\ttwo :,five six seven"; - System.Console.WriteLine($"Original text: '{text}'"); - - string[] words = text.Split(delimiterChars); - System.Console.WriteLine($"{words.Length} words in text:"); - - foreach (var word in words) - { - System.Console.WriteLine($"<{word}>"); - } - // - } - - private static void SplitUsingStrings() - { - // - string[] separatingStrings = { "<<", "..." }; - - string text = "one< - } - - private static void SplitFourTimes() - { - // - string phrase = "The quick brown fox jumps over the lazy dog."; - string[] words = phrase.Split(' ', 4, System.StringSplitOptions.None); - - foreach (var word in words) - { - System.Console.WriteLine($"<{word}>"); - } - // - } - } -} diff --git a/samples/snippets/csharp/how-to/strings/Program.cs b/samples/snippets/csharp/how-to/strings/Program.cs deleted file mode 100644 index 04110e3a95676..0000000000000 --- a/samples/snippets/csharp/how-to/strings/Program.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; - -namespace HowToStrings -{ - class Program - { - static void Main(string[] args) - { - Console.WriteLine("============================ String.Split examples ================================================="); - Console.WriteLine(); - ParseStringsUsingSplit.Examples(); - Console.WriteLine("============================ String concatenation examples ================================================="); - Console.WriteLine(); - Concatenate.Examples(); - Console.WriteLine("============================ String Searching examples ================================================="); - Console.WriteLine(); - SearchStrings.Examples(); - Console.WriteLine("============================ Modify string examples ================================================="); - Console.WriteLine(); - ModifyStrings.Examples(); - Console.WriteLine("============================ Compare string examples ================================================="); - Console.WriteLine(); - CompareStrings.Examples(); - } - } -} diff --git a/samples/snippets/csharp/how-to/strings/SearchStrings.cs b/samples/snippets/csharp/how-to/strings/SearchStrings.cs deleted file mode 100644 index e94860e0e89ee..0000000000000 --- a/samples/snippets/csharp/how-to/strings/SearchStrings.cs +++ /dev/null @@ -1,121 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace HowToStrings -{ - public class SearchStrings - { - public static void Examples() - { - SearchWithMethods(); - SearchByIndex(); - RegularExpressionsOne(); - RegularExpressionsValidation(); - } - - private static void SearchWithMethods() - { - // - string factMessage = "Extension methods have all the capabilities of regular static methods."; - - // Write the string and include the quotation marks. - Console.WriteLine($"\"{factMessage}\""); - - // Simple comparisons are always case sensitive! - bool containsSearchResult = factMessage.Contains("extension"); - Console.WriteLine($"Contains \"extension\"? {containsSearchResult}"); - - // For user input and strings that will be displayed to the end user, - // use the StringComparison parameter on methods that have it to specify how to match strings. - bool ignoreCaseSearchResult = factMessage.StartsWith("extension", System.StringComparison.CurrentCultureIgnoreCase); - Console.WriteLine($"Starts with \"extension\"? {ignoreCaseSearchResult} (ignoring case)"); - - bool endsWithSearchResult = factMessage.EndsWith(".", System.StringComparison.CurrentCultureIgnoreCase); - Console.WriteLine($"Ends with '.'? {endsWithSearchResult}"); - // - } - - private static void SearchByIndex() - { - // - string factMessage = "Extension methods have all the capabilities of regular static methods."; - - // Write the string and include the quotation marks. - Console.WriteLine($"\"{factMessage}\""); - - // This search returns the substring between two strings, so - // the first index is moved to the character just after the first string. - int first = factMessage.IndexOf("methods") + "methods".Length; - int last = factMessage.LastIndexOf("methods"); - string str2 = factMessage.Substring(first, last - first); - Console.WriteLine($"Substring between \"methods\" and \"methods\": '{str2}'"); - // - } - - private static void RegularExpressionsOne() - { - // - string[] sentences = - { - "Put the water over there.", - "They're quite thirsty.", - "Their water bottles broke." - }; - - string sPattern = "the(ir)?\\s"; - - foreach (string s in sentences) - { - Console.Write($"{s,24}"); - - if (System.Text.RegularExpressions.Regex.IsMatch(s, sPattern, System.Text.RegularExpressions.RegexOptions.IgnoreCase)) - { - Console.WriteLine($" (match for '{sPattern}' found)"); - } - else - { - Console.WriteLine(); - } - } - // - } - - private static void RegularExpressionsValidation() - { - // - string[] numbers = - { - "123-555-0190", - "444-234-22450", - "690-555-0178", - "146-893-232", - "146-555-0122", - "4007-555-0111", - "407-555-0111", - "407-2-5555", - "407-555-8974", - "407-2ab-5555", - "690-555-8148", - "146-893-232-" - }; - - string sPattern = "^\\d{3}-\\d{3}-\\d{4}$"; - - foreach (string s in numbers) - { - Console.Write($"{s,14}"); - - if (System.Text.RegularExpressions.Regex.IsMatch(s, sPattern)) - { - Console.WriteLine(" - valid"); - } - else - { - Console.WriteLine(" - invalid"); - } - } - // - } - } -}