diff --git a/snippets/csharp/System.Text.RegularExpressions/Regex/Match/Project.csproj b/snippets/csharp/System.Text/Encoding/Overview/Project.csproj similarity index 64% rename from snippets/csharp/System.Text.RegularExpressions/Regex/Match/Project.csproj rename to snippets/csharp/System.Text/Encoding/Overview/Project.csproj index 0735dba1f6d..874c98f3477 100644 --- a/snippets/csharp/System.Text.RegularExpressions/Regex/Match/Project.csproj +++ b/snippets/csharp/System.Text/Encoding/Overview/Project.csproj @@ -2,7 +2,7 @@ Library - net6.0 + net10.0 - - + + diff --git a/snippets/csharp/System.Text/Encoding/Overview/convert.cs b/snippets/csharp/System.Text/Encoding/Overview/convert.cs index 8fa227775b0..59060114673 100644 --- a/snippets/csharp/System.Text/Encoding/Overview/convert.cs +++ b/snippets/csharp/System.Text/Encoding/Overview/convert.cs @@ -2,9 +2,9 @@ using System; using System.Text; -class Example +class ConvertExample { - static void Main() + static void Run() { string unicodeString = "This string contains the unicode character Pi (\u03a0)"; @@ -28,6 +28,7 @@ static void Main() Console.WriteLine("Ascii converted string: {0}", asciiString); } } + // The example displays the following output: // Original string: This string contains the unicode character Pi (Π) // Ascii converted string: This string contains the unicode character Pi (?) diff --git a/snippets/csharp/System.Text/Encoding/Overview/getencoding1.cs b/snippets/csharp/System.Text/Encoding/Overview/getencoding1.cs new file mode 100644 index 00000000000..01030c658a4 --- /dev/null +++ b/snippets/csharp/System.Text/Encoding/Overview/getencoding1.cs @@ -0,0 +1,91 @@ +// +using System; +using System.Text; + +public class GetEncodingExample +{ + public static void Run() + { + Encoding enc = Encoding.GetEncoding(1253); + Encoding altEnc = Encoding.GetEncoding("windows-1253"); + Console.WriteLine($"{enc.EncodingName} = Code Page {altEnc.CodePage}: {enc.Equals(altEnc)}"); + string greekAlphabet = "Α α Β β Γ γ Δ δ Ε ε Ζ ζ Η η " + + "Θ θ Ι ι Κ κ Λ λ Μ μ Ν ν Ξ ξ " + + "Ο ο Π π Ρ ρ Σ σ ς Τ τ Υ υ " + + "Φ φ Χ χ Ψ ψ Ω ω"; + Console.OutputEncoding = Encoding.UTF8; + byte[] bytes = enc.GetBytes(greekAlphabet); + Console.WriteLine("{0,-12} {1,20} {2,20:X2}", "Character", + "Unicode Code Point", "Code Page 1253"); + for (int ctr = 0; ctr < bytes.Length; ctr++) { + if (greekAlphabet[ctr].Equals(' ')) + continue; + + Console.WriteLine("{0,-12} {1,20} {2,20:X2}", greekAlphabet[ctr], + GetCodePoint(greekAlphabet[ctr]), bytes[ctr]); + } + } + + private static string GetCodePoint(char ch) + { + string retVal = "u+"; + byte[] bytes = Encoding.Unicode.GetBytes(ch.ToString()); + for (int ctr = bytes.Length - 1; ctr >= 0; ctr--) + retVal += bytes[ctr].ToString("X2"); + + return retVal; + } +} + +// The example displays the following output: +// Character Unicode Code Point Code Page 1253 +// Α u+0391 C1 +// α u+03B1 E1 +// Β u+0392 C2 +// β u+03B2 E2 +// Γ u+0393 C3 +// γ u+03B3 E3 +// Δ u+0394 C4 +// δ u+03B4 E4 +// Ε u+0395 C5 +// ε u+03B5 E5 +// Ζ u+0396 C6 +// ζ u+03B6 E6 +// Η u+0397 C7 +// η u+03B7 E7 +// Θ u+0398 C8 +// θ u+03B8 E8 +// Ι u+0399 C9 +// ι u+03B9 E9 +// Κ u+039A CA +// κ u+03BA EA +// Λ u+039B CB +// λ u+03BB EB +// Μ u+039C CC +// μ u+03BC EC +// Ν u+039D CD +// ν u+03BD ED +// Ξ u+039E CE +// ξ u+03BE EE +// Ο u+039F CF +// ο u+03BF EF +// Π u+03A0 D0 +// π u+03C0 F0 +// Ρ u+03A1 D1 +// ρ u+03C1 F1 +// Σ u+03A3 D3 +// σ u+03C3 F3 +// ς u+03C2 F2 +// Τ u+03A4 D4 +// τ u+03C4 F4 +// Υ u+03A5 D5 +// υ u+03C5 F5 +// Φ u+03A6 D6 +// φ u+03C6 F6 +// Χ u+03A7 D7 +// χ u+03C7 F7 +// Ψ u+03A8 D8 +// ψ u+03C8 F8 +// Ω u+03A9 D9 +// ω u+03C9 F9 +// diff --git a/snippets/csharp/System.Text/StringBuilder/Overview/Project.csproj b/snippets/csharp/System.Text/StringBuilder/Overview/Project.csproj new file mode 100644 index 00000000000..22dd9034898 --- /dev/null +++ b/snippets/csharp/System.Text/StringBuilder/Overview/Project.csproj @@ -0,0 +1,9 @@ + + + + Library + net10.0 + true + + + diff --git a/snippets/csharp/System.Text/StringBuilder/Overview/call1.cs b/snippets/csharp/System.Text/StringBuilder/Overview/call1.cs new file mode 100644 index 00000000000..ed96e1ca314 --- /dev/null +++ b/snippets/csharp/System.Text/StringBuilder/Overview/call1.cs @@ -0,0 +1,19 @@ +// +using System; +using System.Text; + +public class Example +{ + public static void Main() + { + StringBuilder sb = new StringBuilder(); + sb.Append("This is the beginning of a sentence, "); + sb.Replace("the beginning of ", ""); + sb.Insert(sb.ToString().IndexOf("a ") + 2, "complete "); + sb.Replace(",", "."); + Console.WriteLine(sb.ToString()); + } +} +// The example displays the following output: +// This is a complete sentence. +// diff --git a/snippets/csharp/System.Text/StringBuilder/Overview/call2.cs b/snippets/csharp/System.Text/StringBuilder/Overview/call2.cs new file mode 100644 index 00000000000..9fe17b881df --- /dev/null +++ b/snippets/csharp/System.Text/StringBuilder/Overview/call2.cs @@ -0,0 +1,17 @@ +// +using System; +using System.Text; + +public class Example2 +{ + public static void Main() + { + StringBuilder sb = new StringBuilder("This is the beginning of a sentence, "); + sb.Replace("the beginning of ", "").Insert(sb.ToString().IndexOf("a ") + 2, + "complete ").Replace(",", "."); + Console.WriteLine(sb.ToString()); + } +} +// The example displays the following output: +// This is a complete sentence. +// diff --git a/snippets/csharp/System.Text/StringBuilder/Overview/chars1.cs b/snippets/csharp/System.Text/StringBuilder/Overview/chars1.cs new file mode 100644 index 00000000000..85b3c3c6645 --- /dev/null +++ b/snippets/csharp/System.Text/StringBuilder/Overview/chars1.cs @@ -0,0 +1,46 @@ +// +using System; +using System.Globalization; +using System.Text; + +public class Example3 +{ + public static void Main() + { + Random rnd = new Random(); + StringBuilder sb = new StringBuilder(); + + // Generate 10 random numbers and store them in a StringBuilder. + for (int ctr = 0; ctr <= 9; ctr++) + sb.Append(rnd.Next().ToString("N5")); + + Console.WriteLine("The original string:"); + Console.WriteLine(sb.ToString()); + + // Decrease each number by one. + for (int ctr = 0; ctr < sb.Length; ctr++) + { + if (Char.GetUnicodeCategory(sb[ctr]) == UnicodeCategory.DecimalDigitNumber) + { + int number = (int)Char.GetNumericValue(sb[ctr]); + number--; + if (number < 0) number = 9; + + sb[ctr] = number.ToString()[0]; + } + } + Console.WriteLine("\nThe new string:"); + Console.WriteLine(sb.ToString()); + } +} +// The example displays the following output: +// The original string: +// 1,457,531,530.00000940,522,609.000001,668,113,564.000001,998,992,883.000001,792,660,834.00 +// 000101,203,251.000002,051,183,075.000002,066,000,067.000001,643,701,043.000001,702,382,508 +// .00000 +// +// The new string: +// 0,346,420,429.99999839,411,598.999990,557,002,453.999990,887,881,772.999990,681,559,723.99 +// 999090,192,140.999991,940,072,964.999991,955,999,956.999990,532,690,932.999990,691,271,497 +// .99999 +// diff --git a/snippets/csharp/System.Text/StringBuilder/Overview/default1.cs b/snippets/csharp/System.Text/StringBuilder/Overview/default1.cs new file mode 100644 index 00000000000..76998f10013 --- /dev/null +++ b/snippets/csharp/System.Text/StringBuilder/Overview/default1.cs @@ -0,0 +1,45 @@ +// +using System; +using System.Reflection; +using System.Text; + +public class Example4 +{ + public static void Main() + { + StringBuilder sb = new StringBuilder(); + ShowSBInfo(sb); + sb.Append("This is a sentence."); + ShowSBInfo(sb); + for (int ctr = 0; ctr <= 10; ctr++) + { + sb.Append("This is an additional sentence."); + ShowSBInfo(sb); + } + } + + private static void ShowSBInfo(StringBuilder sb) + { + foreach (var prop in sb.GetType().GetProperties()) + { + if (prop.GetIndexParameters().Length == 0) + Console.Write("{0}: {1:N0} ", prop.Name, prop.GetValue(sb)); + } + Console.WriteLine(); + } +} +// The example displays the following output: +// Capacity: 16 MaxCapacity: 2,147,483,647 Length: 0 +// Capacity: 32 MaxCapacity: 2,147,483,647 Length: 19 +// Capacity: 64 MaxCapacity: 2,147,483,647 Length: 50 +// Capacity: 128 MaxCapacity: 2,147,483,647 Length: 81 +// Capacity: 128 MaxCapacity: 2,147,483,647 Length: 112 +// Capacity: 256 MaxCapacity: 2,147,483,647 Length: 143 +// Capacity: 256 MaxCapacity: 2,147,483,647 Length: 174 +// Capacity: 256 MaxCapacity: 2,147,483,647 Length: 205 +// Capacity: 256 MaxCapacity: 2,147,483,647 Length: 236 +// Capacity: 512 MaxCapacity: 2,147,483,647 Length: 267 +// Capacity: 512 MaxCapacity: 2,147,483,647 Length: 298 +// Capacity: 512 MaxCapacity: 2,147,483,647 Length: 329 +// Capacity: 512 MaxCapacity: 2,147,483,647 Length: 360 +// diff --git a/snippets/csharp/System.Text/StringBuilder/Overview/delete1.cs b/snippets/csharp/System.Text/StringBuilder/Overview/delete1.cs new file mode 100644 index 00000000000..4d12e85f086 --- /dev/null +++ b/snippets/csharp/System.Text/StringBuilder/Overview/delete1.cs @@ -0,0 +1,44 @@ +// +using System; +using System.Text; + +public class Example5 +{ + public static void Main() + { + StringBuilder sb = new StringBuilder("A StringBuilder object"); + ShowSBInfo(sb); + // Remove "object" from the text. + string textToRemove = "object"; + int pos = sb.ToString().IndexOf(textToRemove); + if (pos >= 0) + { + sb.Remove(pos, textToRemove.Length); + ShowSBInfo(sb); + } + // Clear the StringBuilder contents. + sb.Clear(); + ShowSBInfo(sb); + } + + public static void ShowSBInfo(StringBuilder sb) + { + Console.WriteLine($"\nValue: {sb.ToString()}"); + foreach (var prop in sb.GetType().GetProperties()) + { + if (prop.GetIndexParameters().Length == 0) + Console.Write("{0}: {1:N0} ", prop.Name, prop.GetValue(sb)); + } + Console.WriteLine(); + } +} +// The example displays the following output: +// Value: A StringBuilder object +// Capacity: 22 MaxCapacity: 2,147,483,647 Length: 22 +// +// Value: A StringBuilder +// Capacity: 22 MaxCapacity: 2,147,483,647 Length: 16 +// +// Value: +// Capacity: 22 MaxCapacity: 2,147,483,647 Length: 0 +// diff --git a/snippets/csharp/System.Text/StringBuilder/Overview/expand1.cs b/snippets/csharp/System.Text/StringBuilder/Overview/expand1.cs new file mode 100644 index 00000000000..50353a4619a --- /dev/null +++ b/snippets/csharp/System.Text/StringBuilder/Overview/expand1.cs @@ -0,0 +1,48 @@ +// +using System; +using System.Text; + +public class Example6 +{ + public static void Main() + { + // Create a StringBuilder object with no text. + StringBuilder sb = new StringBuilder(); + // Append some text. + sb.Append('*', 10).Append(" Adding Text to a StringBuilder Object ").Append('*', 10); + sb.AppendLine("\n"); + sb.AppendLine("Some code points and their corresponding characters:"); + // Append some formatted text. + for (int ctr = 50; ctr <= 60; ctr++) + { + sb.AppendFormat("{0,12:X4} {1,12}", ctr, Convert.ToChar(ctr)); + sb.AppendLine(); + } + // Find the end of the introduction to the column. + int pos = sb.ToString().IndexOf("characters:") + 11 + + Environment.NewLine.Length; + // Insert a column header. + sb.Insert(pos, $"{Environment.NewLine}{"Code Unit",12} {"Character",12}{Environment.NewLine}"); + + // Convert the StringBuilder to a string and display it. + Console.WriteLine(sb.ToString()); + } +} +// The example displays the following output: +// ********** Adding Text to a StringBuilder Object ********** +// +// Some code points and their corresponding characters: +// +// Code Unit Character +// 0032 2 +// 0033 3 +// 0034 4 +// 0035 5 +// 0036 6 +// 0037 7 +// 0038 8 +// 0039 9 +// 003A : +// 003B ; +// 003C < +// diff --git a/snippets/csharp/System.Text/StringBuilder/Overview/immutability2.cs b/snippets/csharp/System.Text/StringBuilder/Overview/immutability2.cs new file mode 100644 index 00000000000..1bdd80a7212 --- /dev/null +++ b/snippets/csharp/System.Text/StringBuilder/Overview/immutability2.cs @@ -0,0 +1,21 @@ +// +using System; + +public class Example7 +{ + public unsafe static void Main() + { + string value = "This is the first sentence" + "."; + fixed (char* start = value) + { + value = String.Concat(value, "This is the second sentence. "); + fixed (char* current = value) + { + Console.WriteLine(start == current); + } + } + } +} +// The example displays the following output: +// False +// diff --git a/snippets/csharp/System.Text/StringBuilder/Overview/instantiate1.cs b/snippets/csharp/System.Text/StringBuilder/Overview/instantiate1.cs new file mode 100644 index 00000000000..0d91bfb11e7 --- /dev/null +++ b/snippets/csharp/System.Text/StringBuilder/Overview/instantiate1.cs @@ -0,0 +1,48 @@ +// +using System; +using System.Text; + +public class Example8 +{ + public static void Main() + { + string value = "An ordinary string"; + int index = value.IndexOf("An ") + 3; + int capacity = 0xFFFF; + + // Instantiate a StringBuilder from a string. + StringBuilder sb1 = new StringBuilder(value); + ShowSBInfo(sb1); + + // Instantiate a StringBuilder from string and define a capacity. + StringBuilder sb2 = new StringBuilder(value, capacity); + ShowSBInfo(sb2); + + // Instantiate a StringBuilder from substring and define a capacity. + StringBuilder sb3 = new StringBuilder(value, index, + value.Length - index, + capacity); + ShowSBInfo(sb3); + } + + public static void ShowSBInfo(StringBuilder sb) + { + Console.WriteLine($"\nValue: {sb.ToString()}"); + foreach (var prop in sb.GetType().GetProperties()) + { + if (prop.GetIndexParameters().Length == 0) + Console.Write("{0}: {1:N0} ", prop.Name, prop.GetValue(sb)); + } + Console.WriteLine(); + } +} +// The example displays the following output: +// Value: An ordinary string +// Capacity: 18 MaxCapacity: 2,147,483,647 Length: 18 +// +// Value: An ordinary string +// Capacity: 65,535 MaxCapacity: 2,147,483,647 Length: 18 +// +// Value: ordinary string +// Capacity: 65,535 MaxCapacity: 2,147,483,647 Length: 15 +// diff --git a/snippets/csharp/System.Text/StringBuilder/Overview/pattern1.cs b/snippets/csharp/System.Text/StringBuilder/Overview/pattern1.cs new file mode 100644 index 00000000000..afb671908bd --- /dev/null +++ b/snippets/csharp/System.Text/StringBuilder/Overview/pattern1.cs @@ -0,0 +1,66 @@ +// +using System; +using System.Text; + +public class Example9 +{ + public static void Main() + { + Random rnd = new Random(); + string[] tempF = { "47.6F", "51.3F", "49.5F", "62.3F" }; + string[] tempC = { "21.2C", "16.1C", "23.5C", "22.9C" }; + string[][] temps = { tempF, tempC }; + + StringBuilder sb = new StringBuilder(); + var f = new StringBuilderFinder(sb, "F"); + var baseDate = new DateTime(2013, 5, 1); + String[] temperatures = temps[rnd.Next(2)]; + bool isFahrenheit = false; + foreach (var temperature in temperatures) + { + if (isFahrenheit) + sb.AppendFormat("{0:d}: {1}\n", baseDate, temperature); + else + isFahrenheit = f.SearchAndAppend(String.Format("{0:d}: {1}\n", + baseDate, temperature)); + baseDate = baseDate.AddDays(1); + } + if (isFahrenheit) + { + sb.Insert(0, "Average Daily Temperature in Degrees Fahrenheit"); + sb.Insert(47, "\n\n"); + } + else + { + sb.Insert(0, "Average Daily Temperature in Degrees Celsius"); + sb.Insert(44, "\n\n"); + } + Console.WriteLine(sb.ToString()); + } +} + +public class StringBuilderFinder +{ + private StringBuilder sb; + private String text; + + public StringBuilderFinder(StringBuilder sb, String textToFind) + { + this.sb = sb; + this.text = textToFind; + } + + public bool SearchAndAppend(String stringToSearch) + { + sb.Append(stringToSearch); + return stringToSearch.Contains(text); + } +} +// The example displays output similar to the following: +// Average Daily Temperature in Degrees Celsius +// +// 5/1/2013: 21.2C +// 5/2/2013: 16.1C +// 5/3/2013: 23.5C +// 5/4/2013: 22.9C +// diff --git a/snippets/csharp/System.Text/StringBuilder/Overview/pattern2.cs b/snippets/csharp/System.Text/StringBuilder/Overview/pattern2.cs new file mode 100644 index 00000000000..baa5e9f78d8 --- /dev/null +++ b/snippets/csharp/System.Text/StringBuilder/Overview/pattern2.cs @@ -0,0 +1,45 @@ +// +using System; +using System.Text; +using System.Text.RegularExpressions; + +public class Example10 +{ + public static void Main() + { + // Create a StringBuilder object with 4 successive occurrences + // of each character in the English alphabet. + StringBuilder sb = new StringBuilder(); + for (ushort ctr = (ushort)'a'; ctr <= (ushort)'z'; ctr++) + sb.Append(Convert.ToChar(ctr), 4); + + // Create a parallel string object. + String sbString = sb.ToString(); + // Determine where each new character sequence begins. + String pattern = @"(\w)\1+"; + MatchCollection matches = Regex.Matches(sbString, pattern); + + // Uppercase the first occurrence of the sequence, and separate it + // from the previous sequence by an underscore character. + for (int ctr = matches.Count - 1; ctr >= 0; ctr--) + { + Match m = matches[ctr]; + sb[m.Index] = Char.ToUpper(sb[m.Index]); + if (m.Index > 0) sb.Insert(m.Index, "_"); + } + // Display the resulting string. + sbString = sb.ToString(); + int line = 0; + do + { + int nChars = line * 80 + 79 <= sbString.Length ? + 80 : sbString.Length - line * 80; + Console.WriteLine(sbString.Substring(line * 80, nChars)); + line++; + } while (line * 80 < sbString.Length); + } +} +// The example displays the following output: +// Aaaa_Bbbb_Cccc_Dddd_Eeee_Ffff_Gggg_Hhhh_Iiii_Jjjj_Kkkk_Llll_Mmmm_Nnnn_Oooo_Pppp_ +// Qqqq_Rrrr_Ssss_Tttt_Uuuu_Vvvv_Wwww_Xxxx_Yyyy_Zzzz +// diff --git a/snippets/csharp/System.Text/StringBuilder/Overview/pattern3.cs b/snippets/csharp/System.Text/StringBuilder/Overview/pattern3.cs new file mode 100644 index 00000000000..4415ba820ca --- /dev/null +++ b/snippets/csharp/System.Text/StringBuilder/Overview/pattern3.cs @@ -0,0 +1,48 @@ +// +using System; +using System.Text; + +public class Example11 +{ + public static void Main() + { + // Create a StringBuilder object with 4 successive occurrences + // of each character in the English alphabet. + StringBuilder sb = new StringBuilder(); + for (ushort ctr = (ushort)'a'; ctr <= (ushort)'z'; ctr++) + sb.Append(Convert.ToChar(ctr), 4); + + // Iterate the text to determine when a new character sequence occurs. + int position = 0; + Char current = '\u0000'; + do + { + if (sb[position] != current) + { + current = sb[position]; + sb[position] = Char.ToUpper(sb[position]); + if (position > 0) + sb.Insert(position, "_"); + position += 2; + } + else + { + position++; + } + } while (position <= sb.Length - 1); + // Display the resulting string. + String sbString = sb.ToString(); + int line = 0; + do + { + int nChars = line * 80 + 79 <= sbString.Length ? + 80 : sbString.Length - line * 80; + Console.WriteLine(sbString.Substring(line * 80, nChars)); + line++; + } while (line * 80 < sbString.Length); + } +} +// The example displays the following output: +// Aaaa_Bbbb_Cccc_Dddd_Eeee_Ffff_Gggg_Hhhh_Iiii_Jjjj_Kkkk_Llll_Mmmm_Nnnn_Oooo_Pppp_ +// Qqqq_Rrrr_Ssss_Tttt_Uuuu_Vvvv_Wwww_Xxxx_Yyyy_Zzzz +// diff --git a/snippets/csharp/System.Text/StringBuilder/Overview/pattern4.cs b/snippets/csharp/System.Text/StringBuilder/Overview/pattern4.cs new file mode 100644 index 00000000000..c19bb283e94 --- /dev/null +++ b/snippets/csharp/System.Text/StringBuilder/Overview/pattern4.cs @@ -0,0 +1,41 @@ +// +using System; +using System.Text; +using System.Text.RegularExpressions; + +public class Example12 +{ + public static void Main() + { + // Create a StringBuilder object with 4 successive occurrences + // of each character in the English alphabet. + StringBuilder sb = new StringBuilder(); + for (ushort ctr = (ushort)'a'; ctr <= (ushort)'z'; ctr++) + sb.Append(Convert.ToChar(ctr), 4); + + // Convert it to a string. + String sbString = sb.ToString(); + + // Use a regex to uppercase the first occurrence of the sequence, + // and separate it from the previous sequence by an underscore. + string pattern = @"(\w)(\1+)"; + sbString = Regex.Replace(sbString, pattern, + m => (m.Index > 0 ? "_" : "") + + m.Groups[1].Value.ToUpper() + + m.Groups[2].Value); + + // Display the resulting string. + int line = 0; + do + { + int nChars = line * 80 + 79 <= sbString.Length ? + 80 : sbString.Length - line * 80; + Console.WriteLine(sbString.Substring(line * 80, nChars)); + line++; + } while (line * 80 < sbString.Length); + } +} +// The example displays the following output: +// Aaaa_Bbbb_Cccc_Dddd_Eeee_Ffff_Gggg_Hhhh_Iiii_Jjjj_Kkkk_Llll_Mmmm_Nnnn_Oooo_Pppp_ +// Qqqq_Rrrr_Ssss_Tttt_Uuuu_Vvvv_Wwww_Xxxx_Yyyy_Zzzz +// diff --git a/snippets/csharp/System.Text/StringBuilder/Overview/replace1.cs b/snippets/csharp/System.Text/StringBuilder/Overview/replace1.cs new file mode 100644 index 00000000000..10cbf950948 --- /dev/null +++ b/snippets/csharp/System.Text/StringBuilder/Overview/replace1.cs @@ -0,0 +1,16 @@ +// +using System; +using System.Text; + +public class Example13 +{ + public static void Main() + { + StringBuilder MyStringBuilder = new StringBuilder("Hello World!"); + MyStringBuilder.Replace('!', '?'); + Console.WriteLine(MyStringBuilder); + } +} +// The example displays the following output: +// Hello World? +// diff --git a/snippets/visualbasic/System.Text/Encoding/Overview/Project.vbproj b/snippets/visualbasic/System.Text/Encoding/Overview/Project.vbproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/visualbasic/System.Text/Encoding/Overview/Project.vbproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/visualbasic/System.Text/Encoding/Overview/convert.vb b/snippets/visualbasic/System.Text/Encoding/Overview/convert.vb index 20f3dbe6698..c35aa53e99d 100644 --- a/snippets/visualbasic/System.Text/Encoding/Overview/convert.vb +++ b/snippets/visualbasic/System.Text/Encoding/Overview/convert.vb @@ -1,8 +1,8 @@ ' Imports System.Text -Class Example - Shared Sub Main() +Class Example1 + Shared Sub Run() Dim unicodeString As String = "This string contains the unicode character Pi (" & ChrW(&H03A0) & ")" ' Create two different encodings. diff --git a/snippets/visualbasic/System.Text/Encoding/Overview/getencoding1.vb b/snippets/visualbasic/System.Text/Encoding/Overview/getencoding1.vb new file mode 100644 index 00000000000..07a785983e5 --- /dev/null +++ b/snippets/visualbasic/System.Text/Encoding/Overview/getencoding1.vb @@ -0,0 +1,90 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Text + +Module Example2 + Public Sub Run() + Dim enc As Encoding = Encoding.GetEncoding(1253) + Dim altEnc As Encoding = Encoding.GetEncoding("windows-1253") + Console.WriteLine("{0} = Code Page {1}: {2}", enc.EncodingName, + altEnc.CodePage, enc.Equals(altEnc)) + Dim greekAlphabet As String = "Α α Β β Γ γ Δ δ Ε ε Ζ ζ Η η " + + "Θ θ Ι ι Κ κ Λ λ Μ μ Ν ν Ξ ξ " + + "Ο ο Π π Ρ ρ Σ σ ς Τ τ Υ υ " + + "Φ φ Χ χ Ψ ψ Ω ω" + Console.OutputEncoding = Encoding.UTF8 + Dim bytes() As Byte = enc.GetBytes(greekAlphabet) + Console.WriteLine("{0,-12} {1,20} {2,20:X2}", "Character", + "Unicode Code Point", "Code Page 1253") + For ctr As Integer = 0 To bytes.Length - 1 + If greekAlphabet(ctr).Equals(" "c) Then Continue For + + Console.WriteLine("{0,-12} {1,20} {2,20:X2}", greekAlphabet(ctr), + GetCodePoint(greekAlphabet(ctr)), bytes(ctr)) + Next + + End Sub + + Private Function GetCodePoint(ch As String) As String + Dim retVal As String = "u+" + Dim bytes() As Byte = Encoding.Unicode.GetBytes(ch) + For ctr As Integer = bytes.Length - 1 To 0 Step -1 + retVal += bytes(ctr).ToString("X2") + Next + Return retVal + End Function +End Module +' The example displays the following output: +' Character Unicode Code Point Code Page 1253 +' Α u+0391 C1 +' α u+03B1 E1 +' Β u+0392 C2 +' β u+03B2 E2 +' Γ u+0393 C3 +' γ u+03B3 E3 +' Δ u+0394 C4 +' δ u+03B4 E4 +' Ε u+0395 C5 +' ε u+03B5 E5 +' Ζ u+0396 C6 +' ζ u+03B6 E6 +' Η u+0397 C7 +' η u+03B7 E7 +' Θ u+0398 C8 +' θ u+03B8 E8 +' Ι u+0399 C9 +' ι u+03B9 E9 +' Κ u+039A CA +' κ u+03BA EA +' Λ u+039B CB +' λ u+03BB EB +' Μ u+039C CC +' μ u+03BC EC +' Ν u+039D CD +' ν u+03BD ED +' Ξ u+039E CE +' ξ u+03BE EE +' Ο u+039F CF +' ο u+03BF EF +' Π u+03A0 D0 +' π u+03C0 F0 +' Ρ u+03A1 D1 +' ρ u+03C1 F1 +' Σ u+03A3 D3 +' σ u+03C3 F3 +' ς u+03C2 F2 +' Τ u+03A4 D4 +' τ u+03C4 F4 +' Υ u+03A5 D5 +' υ u+03C5 F5 +' Φ u+03A6 D6 +' φ u+03C6 F6 +' Χ u+03A7 D7 +' χ u+03C7 F7 +' Ψ u+03A8 D8 +' ψ u+03C8 F8 +' Ω u+03A9 D9 +' ω u+03C9 F9 +' diff --git a/snippets/visualbasic/System.Text/StringBuilder/Overview/Project.vbproj b/snippets/visualbasic/System.Text/StringBuilder/Overview/Project.vbproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/visualbasic/System.Text/StringBuilder/Overview/Project.vbproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/visualbasic/System.Text/StringBuilder/Overview/call1.vb b/snippets/visualbasic/System.Text/StringBuilder/Overview/call1.vb new file mode 100644 index 00000000000..71c9e10dac0 --- /dev/null +++ b/snippets/visualbasic/System.Text/StringBuilder/Overview/call1.vb @@ -0,0 +1,19 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Text + +Module Example2 + Public Sub Main() + Dim sb As New StringBuilder() + sb.Append("This is the beginning of a sentence, ") + sb.Replace("the beginning of ", "") + sb.Insert(sb.ToString().IndexOf("a ") + 2, "complete ") + sb.Replace(",", ".") + Console.WriteLine(sb.ToString()) + End Sub +End Module +' The example displays the following output: +' This is a complete sentence. +' diff --git a/snippets/visualbasic/System.Text/StringBuilder/Overview/call2.vb b/snippets/visualbasic/System.Text/StringBuilder/Overview/call2.vb new file mode 100644 index 00000000000..358d0a456b4 --- /dev/null +++ b/snippets/visualbasic/System.Text/StringBuilder/Overview/call2.vb @@ -0,0 +1,17 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Text + +Module Example3 + Public Sub Main() + Dim sb As New StringBuilder("This is the beginning of a sentence, ") + sb.Replace("the beginning of ", "").Insert(sb.ToString().IndexOf("a ") + 2, + "complete ").Replace(", ", ".") + Console.WriteLine(sb.ToString()) + End Sub +End Module +' The example displays the following output: +' This is a complete sentence. +' diff --git a/snippets/visualbasic/System.Text/StringBuilder/Overview/chars1.vb b/snippets/visualbasic/System.Text/StringBuilder/Overview/chars1.vb new file mode 100644 index 00000000000..68f7824256a --- /dev/null +++ b/snippets/visualbasic/System.Text/StringBuilder/Overview/chars1.vb @@ -0,0 +1,46 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Globalization +Imports System.Text + +Module Example4 + Public Sub Main() + Dim rnd As New Random() + Dim sb As New StringBuilder() + + ' Generate 10 random numbers and store them in a StringBuilder. + For ctr As Integer = 0 To 9 + sb.Append(rnd.Next().ToString("N5")) + Next + Console.WriteLine("The original string:") + Console.WriteLine(sb.ToString()) + Console.WriteLine() + + ' Decrease each number by one. + For ctr As Integer = 0 To sb.Length - 1 + If Char.GetUnicodeCategory(sb(ctr)) = UnicodeCategory.DecimalDigitNumber Then + Dim number As Integer = CType(Char.GetNumericValue(sb(ctr)), Integer) + number -= 1 + If number < 0 Then number = 9 + + sb(ctr) = number.ToString()(0) + End If + Next + Console.WriteLine("The new string:") + Console.WriteLine(sb.ToString()) + End Sub +End Module +' The example displays the following output: +' The original string: +' 1,457,531,530.00000940,522,609.000001,668,113,564.000001,998,992,883.000001,792,660,834.00 +' 000101,203,251.000002,051,183,075.000002,066,000,067.000001,643,701,043.000001,702,382,508 +' .00000 +' +' The new string: +' 0,346,420,429.99999839,411,598.999990,557,002,453.999990,887,881,772.999990,681,559,723.99 +' 999090,192,140.999991,940,072,964.999991,955,999,956.999990,532,690,932.999990,691,271,497 +' .99999 +' + diff --git a/snippets/visualbasic/System.Text/StringBuilder/Overview/default1.vb b/snippets/visualbasic/System.Text/StringBuilder/Overview/default1.vb new file mode 100644 index 00000000000..60388e491b3 --- /dev/null +++ b/snippets/visualbasic/System.Text/StringBuilder/Overview/default1.vb @@ -0,0 +1,43 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Reflection +Imports System.Text + +Module Example5 + Public Sub Main() + Dim sb As New StringBuilder() + ShowSBInfo(sb) + sb.Append("This is a sentence.") + ShowSBInfo(sb) + For ctr As Integer = 0 To 10 + sb.Append("This is an additional sentence.") + ShowSBInfo(sb) + Next + End Sub + + Public Sub ShowSBInfo(sb As StringBuilder) + For Each prop In sb.GetType().GetProperties + If prop.GetIndexParameters().Length = 0 Then + Console.Write("{0}: {1:N0} ", prop.Name, prop.GetValue(sb)) + End If + Next + Console.WriteLine() + End Sub +End Module +' The example displays the following output: +' Capacity: 16 MaxCapacity: 2,147,483,647 Length: 0 +' Capacity: 32 MaxCapacity: 2,147,483,647 Length: 19 +' Capacity: 64 MaxCapacity: 2,147,483,647 Length: 50 +' Capacity: 128 MaxCapacity: 2,147,483,647 Length: 81 +' Capacity: 128 MaxCapacity: 2,147,483,647 Length: 112 +' Capacity: 256 MaxCapacity: 2,147,483,647 Length: 143 +' Capacity: 256 MaxCapacity: 2,147,483,647 Length: 174 +' Capacity: 256 MaxCapacity: 2,147,483,647 Length: 205 +' Capacity: 256 MaxCapacity: 2,147,483,647 Length: 236 +' Capacity: 512 MaxCapacity: 2,147,483,647 Length: 267 +' Capacity: 512 MaxCapacity: 2,147,483,647 Length: 298 +' Capacity: 512 MaxCapacity: 2,147,483,647 Length: 329 +' Capacity: 512 MaxCapacity: 2,147,483,647 Length: 360 +' diff --git a/snippets/visualbasic/System.Text/StringBuilder/Overview/delete1.vb b/snippets/visualbasic/System.Text/StringBuilder/Overview/delete1.vb new file mode 100644 index 00000000000..905d4bd6f64 --- /dev/null +++ b/snippets/visualbasic/System.Text/StringBuilder/Overview/delete1.vb @@ -0,0 +1,44 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Text + +Module Example6 + Public Sub Main() + Dim sb As New StringBuilder("A StringBuilder object") + ShowSBInfo(sb) + ' Remove "object" from the text. + Dim textToRemove As String = "object" + Dim pos As Integer = sb.ToString().IndexOf(textToRemove) + If pos >= 0 Then + sb.Remove(pos, textToRemove.Length) + ShowSBInfo(sb) + End If + ' Clear the StringBuilder contents. + sb.Clear() + ShowSBInfo(sb) + End Sub + + Public Sub ShowSBInfo(sb As StringBuilder) + Console.WriteLine() + Console.WriteLine("Value: {0}", sb.ToString()) + For Each prop In sb.GetType().GetProperties + If prop.GetIndexParameters().Length = 0 Then + Console.Write("{0}: {1:N0} ", prop.Name, prop.GetValue(sb)) + End If + Next + Console.WriteLine() + End Sub +End Module +' The example displays the following output: +' Value: A StringBuilder object +' Capacity: 22 MaxCapacity: 2,147,483,647 Length: 22 +' +' Value: A StringBuilder +' Capacity: 22 MaxCapacity: 2,147,483,647 Length: 16 +' +' Value: +' Capacity: 22 MaxCapacity: 2,147,483,647 Length: 0 +' + diff --git a/snippets/visualbasic/System.Text/StringBuilder/Overview/expand1.vb b/snippets/visualbasic/System.Text/StringBuilder/Overview/expand1.vb new file mode 100644 index 00000000000..6e400655e5f --- /dev/null +++ b/snippets/visualbasic/System.Text/StringBuilder/Overview/expand1.vb @@ -0,0 +1,49 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Text + +Module Example7 + Public Sub Main() + ' Create a StringBuilder object with no text. + Dim sb As New StringBuilder() + ' Append some text. + sb.Append("*"c, 10).Append(" Adding Text to a StringBuilder Object ").Append("*"c, 10) + sb.AppendLine() + sb.AppendLine() + sb.AppendLine("Some code points and their corresponding characters:") + ' Append some formatted text. + For ctr = 50 To 60 + sb.AppendFormat("{0,12:X4} {1,12}", ctr, Convert.ToChar(ctr)) + sb.AppendLine() + Next + ' Find the end of the introduction to the column. + Dim pos As Integer = sb.ToString().IndexOf("characters:") + 11 + + Environment.NewLine.Length + ' Insert a column header. + sb.Insert(pos, String.Format("{2}{0,12} {1,12}{2}", "Code Unit", + "Character", vbCrLf)) + + ' Convert the StringBuilder to a string and display it. + Console.WriteLine(sb.ToString()) + End Sub +End Module +' The example displays the following output: +' ********** Adding Text to a StringBuilder Object ********** +' +' Some code points and their corresponding characters: +' +' Code Unit Character +' 0032 2 +' 0033 3 +' 0034 4 +' 0035 5 +' 0036 6 +' 0037 7 +' 0038 8 +' 0039 9 +' 003A : +' 003B ; +' 003C < +' diff --git a/snippets/visualbasic/System.Text/StringBuilder/Overview/instantiate1.vb b/snippets/visualbasic/System.Text/StringBuilder/Overview/instantiate1.vb new file mode 100644 index 00000000000..a2ecb1f9a8c --- /dev/null +++ b/snippets/visualbasic/System.Text/StringBuilder/Overview/instantiate1.vb @@ -0,0 +1,49 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Text + +Module Example8 + Public Sub Main() + Dim value As String = "An ordinary string" + Dim index As Integer = value.IndexOf("An ") + 3 + Dim capacity As Integer = &HFFFF + + ' Instantiate a StringBuilder from a string. + Dim sb1 As New StringBuilder(value) + ShowSBInfo(sb1) + + ' Instantiate a StringBuilder from string and define a capacity. + Dim sb2 As New StringBuilder(value, capacity) + ShowSBInfo(sb2) + + ' Instantiate a StringBuilder from substring and define a capacity. + Dim sb3 As New StringBuilder(value, index, + value.Length - index, + capacity) + ShowSBInfo(sb3) + End Sub + + Public Sub ShowSBInfo(sb As StringBuilder) + Console.WriteLine() + Console.WriteLine("Value: {0}", sb.ToString()) + For Each prop In sb.GetType().GetProperties + If prop.GetIndexParameters().Length = 0 Then + Console.Write("{0}: {1:N0} ", prop.Name, prop.GetValue(sb)) + End If + Next + Console.WriteLine() + End Sub +End Module +' The example displays the following output: +' Value: An ordinary string +' Capacity: 18 MaxCapacity: 2,147,483,647 Length: 18 +' +' Value: An ordinary string +' Capacity: 65,535 MaxCapacity: 2,147,483,647 Length: 18 +' +' Value: ordinary string +' Capacity: 65,535 MaxCapacity: 2,147,483,647 Length: 15 +' + diff --git a/snippets/visualbasic/System.Text/StringBuilder/Overview/pattern1.vb b/snippets/visualbasic/System.Text/StringBuilder/Overview/pattern1.vb new file mode 100644 index 00000000000..bfef80bcabc --- /dev/null +++ b/snippets/visualbasic/System.Text/StringBuilder/Overview/pattern1.vb @@ -0,0 +1,60 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Text + +Module Example9 + Public Sub Main() + Dim rnd As New Random() + Dim tempF() As String = {"47.6F", "51.3F", "49.5F", "62.3F"} + Dim tempC() As String = {"21.2C", "16.1C", "23.5C", "22.9C"} + Dim temps()() As String = {tempF, tempC} + + Dim sb As StringBuilder = New StringBuilder() + Dim f As New StringBuilderFinder(sb, "F") + Dim baseDate As New DateTime(2013, 5, 1) + Dim temperatures() As String = temps(rnd.Next(2)) + Dim isFahrenheit As Boolean = False + For Each temperature In temperatures + If isFahrenheit Then + sb.AppendFormat("{0:d}: {1}{2}", baseDate, temperature, vbCrLf) + Else + isFahrenheit = f.SearchAndAppend(String.Format("{0:d}: {1}{2}", + baseDate, temperature, vbCrLf)) + End If + baseDate = baseDate.AddDays(1) + Next + If isFahrenheit Then + sb.Insert(0, "Average Daily Temperature in Degrees Fahrenheit") + sb.Insert(47, vbCrLf + vbCrLf) + Else + sb.Insert(0, "Average Daily Temperature in Degrees Celsius") + sb.Insert(44, vbCrLf + vbCrLf) + End If + Console.WriteLine(sb.ToString()) + End Sub +End Module + +Public Class StringBuilderFinder + Private sb As StringBuilder + Private text As String + + Public Sub New(sb As StringBuilder, textToFind As String) + Me.sb = sb + text = textToFind + End Sub + + Public Function SearchAndAppend(stringToSearch As String) As Boolean + sb.Append(stringToSearch) + Return stringToSearch.Contains(text) + End Function +End Class +' The example displays output similar to the following: +' Average Daily Temperature in Degrees Celsius +' +' 5/1/2013: 21.2C +' 5/2/2013: 16.1C +' 5/3/2013: 23.5C +' 5/4/2013: 22.9C +' diff --git a/snippets/visualbasic/System.Text/StringBuilder/Overview/pattern2.vb b/snippets/visualbasic/System.Text/StringBuilder/Overview/pattern2.vb new file mode 100644 index 00000000000..0fa2ece1e7b --- /dev/null +++ b/snippets/visualbasic/System.Text/StringBuilder/Overview/pattern2.vb @@ -0,0 +1,43 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Text +Imports System.Text.RegularExpressions + +Module Example10 + Public Sub Main() + ' Create a StringBuilder object with 4 successive occurrences + ' of each character in the English alphabet. + Dim sb As New StringBuilder() + For ctr As UShort = AscW("a") To AscW("z") + sb.Append(ChrW(ctr), 4) + Next + ' Create a parallel string object. + Dim sbString As String = sb.ToString() + ' Determine where each new character sequence begins. + Dim pattern As String = "(\w)\1+" + Dim matches As MatchCollection = Regex.Matches(sbString, pattern) + + ' Uppercase the first occurrence of the sequence, and separate it + ' from the previous sequence by an underscore character. + For ctr As Integer = matches.Count - 1 To 0 Step -1 + Dim m As Match = matches(ctr) + sb.Chars(m.Index) = Char.ToUpper(sb.Chars(m.Index)) + If m.Index > 0 Then sb.Insert(m.Index, "_") + Next + ' Display the resulting string. + sbString = sb.ToString() + Dim line As Integer = 0 + Do + Dim nChars As Integer = If(line * 80 + 79 <= sbString.Length, + 80, sbString.Length - line * 80) + Console.WriteLine(sbString.Substring(line * 80, nChars)) + line += 1 + Loop While line * 80 < sbString.Length + End Sub +End Module +' The example displays the following output: +' Aaaa_Bbbb_Cccc_Dddd_Eeee_Ffff_Gggg_Hhhh_Iiii_Jjjj_Kkkk_Llll_Mmmm_Nnnn_Oooo_Pppp_ +' Qqqq_Rrrr_Ssss_Tttt_Uuuu_Vvvv_Wwww_Xxxx_Yyyy_Zzzz +' diff --git a/snippets/visualbasic/System.Text/StringBuilder/Overview/pattern3.vb b/snippets/visualbasic/System.Text/StringBuilder/Overview/pattern3.vb new file mode 100644 index 00000000000..7ecbaa54107 --- /dev/null +++ b/snippets/visualbasic/System.Text/StringBuilder/Overview/pattern3.vb @@ -0,0 +1,42 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Text + +Module Example11 + Public Sub Main() + ' Create a StringBuilder object with 4 successive occurrences + ' of each character in the English alphabet. + Dim sb As New StringBuilder() + For ctr As UShort = AscW("a") To AscW("z") + sb.Append(ChrW(ctr), 4) + Next + ' Iterate the text to determine when a new character sequence occurs. + Dim position As Integer = 0 + Dim current As Char = ChrW(0) + Do + If sb(position) <> current Then + current = sb(position) + sb(position) = Char.ToUpper(sb(position)) + If position > 0 Then sb.Insert(position, "_") + position += 2 + Else + position += 1 + End If + Loop While position <= sb.Length - 1 + ' Display the resulting string. + Dim sbString As String = sb.ToString() + Dim line As Integer = 0 + Do + Dim nChars As Integer = If(line * 80 + 79 <= sbString.Length, + 80, sbString.Length - line * 80) + Console.WriteLine(sbString.Substring(line * 80, nChars)) + line += 1 + Loop While line * 80 < sbString.Length + End Sub +End Module +' The example displays the following output: +' Aaaa_Bbbb_Cccc_Dddd_Eeee_Ffff_Gggg_Hhhh_Iiii_Jjjj_Kkkk_Llll_Mmmm_Nnnn_Oooo_Pppp_ +' Qqqq_Rrrr_Ssss_Tttt_Uuuu_Vvvv_Wwww_Xxxx_Yyyy_Zzzz +' diff --git a/snippets/visualbasic/System.Text/StringBuilder/Overview/pattern4.vb b/snippets/visualbasic/System.Text/StringBuilder/Overview/pattern4.vb new file mode 100644 index 00000000000..9fb52dbd596 --- /dev/null +++ b/snippets/visualbasic/System.Text/StringBuilder/Overview/pattern4.vb @@ -0,0 +1,40 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Text +Imports System.Text.RegularExpressions + +Module Example12 + Public Sub Main() + ' Create a StringBuilder object with 4 successive occurrences + ' of each character in the English alphabet. + Dim sb As New StringBuilder() + For ctr As UShort = AscW("a") To AscW("z") + sb.Append(ChrW(ctr), 4) + Next + ' Convert it to a string. + Dim sbString As String = sb.ToString() + + ' Use a regex to uppercase the first occurrence of the sequence, + ' and separate it from the previous sequence by an underscore. + Dim pattern As String = "(\w)(\1+)" + sbString = Regex.Replace(sbString, pattern, + Function(m) If(m.Index > 0, "_", "") + + m.Groups(1).Value.ToUpper + + m.Groups(2).Value) + + ' Display the resulting string. + Dim line As Integer = 0 + Do + Dim nChars As Integer = If(line * 80 + 79 <= sbString.Length, + 80, sbString.Length - line * 80) + Console.WriteLine(sbString.Substring(line * 80, nChars)) + line += 1 + Loop While line * 80 < sbString.Length + End Sub +End Module +' The example displays the following output: +' Aaaa_Bbbb_Cccc_Dddd_Eeee_Ffff_Gggg_Hhhh_Iiii_Jjjj_Kkkk_Llll_Mmmm_Nnnn_Oooo_Pppp_ +' Qqqq_Rrrr_Ssss_Tttt_Uuuu_Vvvv_Wwww_Xxxx_Yyyy_Zzzz +' diff --git a/snippets/visualbasic/System.Text/StringBuilder/Overview/replace1.vb b/snippets/visualbasic/System.Text/StringBuilder/Overview/replace1.vb new file mode 100644 index 00000000000..7da78f82ca4 --- /dev/null +++ b/snippets/visualbasic/System.Text/StringBuilder/Overview/replace1.vb @@ -0,0 +1,16 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Text + +Module Example + Public Sub Main() + Dim MyStringBuilder As New StringBuilder("Hello World!") + MyStringBuilder.Replace("!"c, "?"c) + Console.WriteLine(MyStringBuilder) + End Sub +End Module +' The example displays the following output: +' Hello World? +' diff --git a/snippets/visualbasic/System.Threading.Tasks/Task/Overview/Project.vbproj b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/Project.vbproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/Project.vbproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/visualbasic/System.Threading.Tasks/Task/Overview/Wait1.vb b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/Wait1.vb new file mode 100644 index 00000000000..914b7bce249 --- /dev/null +++ b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/Wait1.vb @@ -0,0 +1,24 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Threading +Imports System.Threading.Tasks + +Module Example4 + Public Sub Main() + ' Wait on a single task with no timeout specified. + Dim taskA = Task.Run(Sub() Thread.Sleep(2000)) + Console.WriteLine("taskA Status: {0}", taskA.Status) + Try + taskA.Wait() + Console.WriteLine("taskA Status: {0}", taskA.Status) + Catch e As AggregateException + Console.WriteLine("Exception in taskA.") + End Try + End Sub +End Module +' The example displays output like the following: +' taskA Status: WaitingToRun +' taskA Status: RanToCompletion +' diff --git a/snippets/visualbasic/System.Threading.Tasks/Task/Overview/Wait2.vb b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/Wait2.vb new file mode 100644 index 00000000000..5831bede59b --- /dev/null +++ b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/Wait2.vb @@ -0,0 +1,28 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Threading +Imports System.Threading.Tasks + +Module Example5 + Public Sub Main() + ' Wait on a single task with a timeout specified. + Dim taskA As Task = Task.Run(Sub() Thread.Sleep(2000)) + Try + taskA.Wait(1000) ' Wait for 1 second. + Dim completed As Boolean = taskA.IsCompleted + Console.WriteLine("Task.Completed: {0}, Status: {1}", + completed, taskA.Status) + If Not completed Then + Console.WriteLine("Timed out before task A completed.") + End If + Catch e As AggregateException + Console.WriteLine("Exception in taskA.") + End Try + End Sub +End Module +' The example displays the following output: +' Task A completed: False, Status: Running +' Timed out before task A completed. +' diff --git a/snippets/visualbasic/System.Threading.Tasks/Task/Overview/WaitAll1.vb b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/WaitAll1.vb new file mode 100644 index 00000000000..fc512ca31a2 --- /dev/null +++ b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/WaitAll1.vb @@ -0,0 +1,42 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Threading +Imports System.Threading.Tasks + +Module Example6 + Public Sub Main() + ' Wait for all tasks to complete. + Dim tasks(9) As Task + For i As Integer = 0 To 9 + tasks(i) = Task.Run(Sub() Thread.Sleep(2000)) + Next + Try + Task.WaitAll(tasks) + Catch ae As AggregateException + Console.WriteLine("One or more exceptions occurred: ") + For Each ex In ae.Flatten().InnerExceptions + Console.WriteLine(" {0}", ex.Message) + Next + End Try + + Console.WriteLine("Status of completed tasks:") + For Each t In tasks + Console.WriteLine(" Task #{0}: {1}", t.Id, t.Status) + Next + End Sub +End Module +' The example displays the following output: +' Status of completed tasks: +' Task #2: RanToCompletion +' Task #1: RanToCompletion +' Task #3: RanToCompletion +' Task #4: RanToCompletion +' Task #6: RanToCompletion +' Task #5: RanToCompletion +' Task #7: RanToCompletion +' Task #8: RanToCompletion +' Task #9: RanToCompletion +' Task #10: RanToCompletion +' diff --git a/snippets/visualbasic/System.Threading.Tasks/Task/Overview/WaitAll2.vb b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/WaitAll2.vb new file mode 100644 index 00000000000..91cea251e4b --- /dev/null +++ b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/WaitAll2.vb @@ -0,0 +1,98 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Threading +Imports System.Threading.Tasks + +Module Example7 + Public Sub Main() + ' Create a cancellation token and cancel it. + Dim source1 As New CancellationTokenSource() + Dim token1 As CancellationToken = source1.Token + source1.Cancel() + ' Create a cancellation token for later cancellation. + Dim source2 As New CancellationTokenSource() + Dim token2 As CancellationToken = source2.Token + + ' Create a series of tasks that will complete, be cancelled, + ' timeout, or throw an exception. + Dim tasks(11) As Task + For i As Integer = 0 To 11 + Select Case i Mod 4 + ' Task should run to completion. + Case 0 + tasks(i) = Task.Run(Sub() Thread.Sleep(2000)) + ' Task should be set to canceled state. + Case 1 + tasks(i) = Task.Run(Sub() Thread.Sleep(2000), token1) + Case 2 + ' Task should throw an exception. + tasks(i) = Task.Run(Sub() + Throw New NotSupportedException() + End Sub) + Case 3 + ' Task should examine cancellation token. + tasks(i) = Task.Run(Sub() + Thread.Sleep(2000) + If token2.IsCancellationRequested Then + token2.ThrowIfCancellationRequested() + End If + Thread.Sleep(500) + End Sub, token2) + End Select + Next + Thread.Sleep(250) + source2.Cancel() + + Try + Task.WaitAll(tasks) + Catch ae As AggregateException + Console.WriteLine("One or more exceptions occurred:") + For Each ex In ae.InnerExceptions + Console.WriteLine(" {0}: {1}", ex.GetType().Name, ex.Message) + Next + End Try + Console.WriteLine() + + Console.WriteLine("Status of tasks:") + For Each t In tasks + Console.WriteLine(" Task #{0}: {1}", t.Id, t.Status) + If t.Exception IsNot Nothing Then + For Each ex In t.Exception.InnerExceptions + Console.WriteLine(" {0}: {1}", ex.GetType().Name, + ex.Message) + Next + End If + Next + End Sub +End Module +' The example displays output like the following: +' One or more exceptions occurred: +' TaskCanceledException: A task was canceled. +' NotSupportedException: Specified method is not supported. +' TaskCanceledException: A task was canceled. +' TaskCanceledException: A task was canceled. +' NotSupportedException: Specified method is not supported. +' TaskCanceledException: A task was canceled. +' TaskCanceledException: A task was canceled. +' NotSupportedException: Specified method is not supported. +' TaskCanceledException: A task was canceled. +' +' Status of tasks: +' Task #13: RanToCompletion +' Task #1: Canceled +' Task #3: Faulted +' NotSupportedException: Specified method is not supported. +' Task #8: Canceled +' Task #14: RanToCompletion +' Task #4: Canceled +' Task #6: Faulted +' NotSupportedException: Specified method is not supported. +' Task #7: Canceled +' Task #15: RanToCompletion +' Task #9: Canceled +' Task #11: Faulted +' NotSupportedException: Specified method is not supported. +' Task #12: Canceled +' diff --git a/snippets/visualbasic/System.Threading.Tasks/Task/Overview/WaitAny1.vb b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/WaitAny1.vb new file mode 100644 index 00000000000..31c1dbeb1e5 --- /dev/null +++ b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/WaitAny1.vb @@ -0,0 +1,36 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Threading +Imports System.Threading.Tasks + +Module Example8 + Public Sub Main() + Dim tasks(2) As Task + Dim rnd As New Random() + For ctr As Integer = 0 To 2 + tasks(ctr) = Task.Run(Sub() Thread.Sleep(rnd.Next(500, 3000))) + Next + + Try + Dim index As Integer = Task.WaitAny(tasks) + Console.WriteLine("Task #{0} completed first.", tasks(index).Id) + Console.WriteLine() + Console.WriteLine("Status of all tasks:") + For Each t In tasks + Console.WriteLine(" Task #{0}: {1}", t.Id, t.Status) + Next + Catch e As AggregateException + Console.WriteLine("An exception occurred.") + End Try + End Sub +End Module +' The example displays output like the following: +' Task #1 completed first. +' +' Status of all tasks: +' Task #3: Running +' Task #1: RanToCompletion +' Task #4: Running +' diff --git a/snippets/visualbasic/System.Threading.Tasks/Task/Overview/run1.vb b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/run1.vb new file mode 100644 index 00000000000..1c5ed25f062 --- /dev/null +++ b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/run1.vb @@ -0,0 +1,22 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Threading.Tasks + +Module Example1 + Public Sub Main() + Dim t As Task = Task.Run(Sub() + ' Just loop. + Dim ctr As Integer = 0 + For ctr = 0 To 1000000 + Next + Console.WriteLine("Finished {0} loop iterations", + ctr) + End Sub) + t.Wait() + End Sub +End Module +' The example displays the following output: +' Finished 1000001 loop iterations +' diff --git a/snippets/visualbasic/System.Threading.Tasks/Task/Overview/startnew.vb b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/startnew.vb new file mode 100644 index 00000000000..855e0f8297b --- /dev/null +++ b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/startnew.vb @@ -0,0 +1,54 @@ +' +Imports System.Threading +Imports System.Threading.Tasks + +Module Example2 + Public Sub Main() + Dim action As Action(Of Object) = + Sub(obj As Object) + Console.WriteLine("Task={0}, obj={1}, Thread={2}", + Task.CurrentId, obj, + Thread.CurrentThread.ManagedThreadId) + End Sub + + ' Construct an unstarted task + Dim t1 As New Task(action, "alpha") + + ' Construct a started task + Dim t2 As Task = Task.Factory.StartNew(action, "beta") + ' Block the main thread to demonstrate that t2 is executing + t2.Wait() + + ' Launch t1 + t1.Start() + Console.WriteLine("t1 has been launched. (Main Thread={0})", + Thread.CurrentThread.ManagedThreadId) + ' Wait for the task to finish. + t1.Wait() + + ' Construct a started task using Task.Run. + Dim taskData As String = "delta" + Dim t3 As Task = Task.Run(Sub() + Console.WriteLine("Task={0}, obj={1}, Thread={2}", + Task.CurrentId, taskData, + Thread.CurrentThread.ManagedThreadId) + End Sub) + ' Wait for the task to finish. + t3.Wait() + + ' Construct an unstarted task + Dim t4 As New Task(action, "gamma") + ' Run it synchronously + t4.RunSynchronously() + ' Although the task was run synchronously, it is a good practice + ' to wait for it in the event exceptions were thrown by the task. + t4.Wait() + End Sub +End Module +' The example displays output like the following: +' Task=1, obj=beta, Thread=3 +' t1 has been launched. (Main Thread=1) +' Task=2, obj=alpha, Thread=3 +' Task=3, obj=delta, Thread=3 +' Task=4, obj=gamma, Thread=1 +' diff --git a/snippets/visualbasic/System.Threading.Tasks/Task/Overview/startnew1.vb b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/startnew1.vb new file mode 100644 index 00000000000..c8653513f1f --- /dev/null +++ b/snippets/visualbasic/System.Threading.Tasks/Task/Overview/startnew1.vb @@ -0,0 +1,22 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Threading.Tasks + +Module Example3 + Public Sub Main() + Dim t As Task = Task.Factory.StartNew(Sub() + ' Just loop. + Dim ctr As Integer = 0 + For ctr = 0 To 1000000 + Next + Console.WriteLine("Finished {0} loop iterations", + ctr) + End Sub) + t.Wait() + End Sub +End Module +' The example displays the following output: +' Finished 1000001 loop iterations +' diff --git a/snippets/visualbasic/System.Threading/Monitor/Overview/Pattern2.vb b/snippets/visualbasic/System.Threading/Monitor/Overview/Pattern2.vb new file mode 100644 index 00000000000..1bb579c6cbc --- /dev/null +++ b/snippets/visualbasic/System.Threading/Monitor/Overview/Pattern2.vb @@ -0,0 +1,32 @@ +' Visual Basic .NET Document +Option Strict On + +Imports System.Runtime.CompilerServices +Imports System.Threading + +Module Example5 + Public Sub Main() + ' + ' Define the lock object. + Dim obj As New Object() + + ' Define the critical section. + Monitor.Enter(obj) + Try + ' Code to execute one thread at a time. + + ' catch blocks go here. + Finally + Monitor.Exit(obj) + End Try + ' + End Sub + + ' + + Sub MethodToLock() + ' Method implementation. + End Sub + ' +End Module + diff --git a/snippets/visualbasic/System.Threading/Monitor/Overview/Project.vbproj b/snippets/visualbasic/System.Threading/Monitor/Overview/Project.vbproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/visualbasic/System.Threading/Monitor/Overview/Project.vbproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/visualbasic/System.Threading/Monitor/Overview/badbox1.vb b/snippets/visualbasic/System.Threading/Monitor/Overview/badbox1.vb new file mode 100644 index 00000000000..d044f7b82bb --- /dev/null +++ b/snippets/visualbasic/System.Threading/Monitor/Overview/badbox1.vb @@ -0,0 +1,47 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Collections.Generic +Imports System.Threading +Imports System.Threading.Tasks + +Module Example2 + Public Sub Main() + Dim nTasks As Integer = 0 + Dim o As Object = nTasks + Dim tasks As New List(Of Task)() + + Try + For ctr As Integer = 0 To 9 + tasks.Add(Task.Run(Sub() + ' Instead of doing some work, just sleep. + Thread.Sleep(250) + ' Increment the number of tasks. + Monitor.Enter(o) + Try + nTasks += 1 + Finally + Monitor.Exit(o) + End Try + End Sub)) + Next + Task.WaitAll(tasks.ToArray()) + Console.WriteLine("{0} tasks started and executed.", nTasks) + Catch e As AggregateException + Dim msg As String = String.Empty + For Each ie In e.InnerExceptions + Console.WriteLine("{0}", ie.GetType().Name) + If Not msg.Contains(ie.Message) Then + msg += ie.Message + Environment.NewLine + End If + Next + Console.WriteLine(vbCrLf + "Exception Message(s):") + Console.WriteLine(msg) + End Try + End Sub +End Module +' The example displays the following output: +' 10 tasks started and executed. +' + diff --git a/snippets/visualbasic/System.Threading/Monitor/Overview/badlock1.vb b/snippets/visualbasic/System.Threading/Monitor/Overview/badlock1.vb new file mode 100644 index 00000000000..423f706a8c4 --- /dev/null +++ b/snippets/visualbasic/System.Threading/Monitor/Overview/badlock1.vb @@ -0,0 +1,60 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Collections.Generic +Imports System.Threading +Imports System.Threading.Tasks + +Module Example3 + Public Sub Main() + Dim nTasks As Integer = 0 + Dim tasks As New List(Of Task)() + + Try + For ctr As Integer = 0 To 9 + tasks.Add(Task.Run(Sub() + ' Instead of doing some work, just sleep. + Thread.Sleep(250) + ' Increment the number of tasks. + Monitor.Enter(nTasks) + Try + nTasks += 1 + Finally + Monitor.Exit(nTasks) + End Try + End Sub)) + Next + Task.WaitAll(tasks.ToArray()) + Console.WriteLine("{0} tasks started and executed.", nTasks) + Catch e As AggregateException + Dim msg As String = String.Empty + For Each ie In e.InnerExceptions + Console.WriteLine("{0}", ie.GetType().Name) + If Not msg.Contains(ie.Message) Then + msg += ie.Message + Environment.NewLine + End If + Next + Console.WriteLine(vbCrLf + "Exception Message(s):") + Console.WriteLine(msg) + End Try + End Sub +End Module +' The example displays the following output: +' SynchronizationLockException +' SynchronizationLockException +' SynchronizationLockException +' SynchronizationLockException +' SynchronizationLockException +' SynchronizationLockException +' SynchronizationLockException +' SynchronizationLockException +' SynchronizationLockException +' SynchronizationLockException +' +' Exception Message(s): +' Object synchronization method was called from an unsynchronized block of code. +' + + + diff --git a/snippets/visualbasic/System.Threading/Monitor/Overview/example1.vb b/snippets/visualbasic/System.Threading/Monitor/Overview/example1.vb new file mode 100644 index 00000000000..26508642524 --- /dev/null +++ b/snippets/visualbasic/System.Threading/Monitor/Overview/example1.vb @@ -0,0 +1,66 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Collections.Generic +Imports System.Threading +Imports System.Threading.Tasks + +Module Example4 + Public Sub Main() + Dim tasks As New List(Of Task)() + Dim rnd As New Random() + Dim total As Long = 0 + Dim n As Integer = 0 + + For taskCtr As Integer = 0 To 9 + tasks.Add(Task.Run(Sub() + Dim values(9999) As Integer + Dim taskTotal As Integer = 0 + Dim taskN As Integer = 0 + Dim ctr As Integer = 0 + Monitor.Enter(rnd) + ' Generate 10,000 random integers. + For ctr = 0 To 9999 + values(ctr) = rnd.Next(0, 1001) + Next + Monitor.Exit(rnd) + taskN = ctr + For Each value In values + taskTotal += value + Next + + Console.WriteLine("Mean for task {0,2}: {1:N2} (N={2:N0})", + Task.CurrentId, taskTotal / taskN, + taskN) + Interlocked.Add(n, taskN) + Interlocked.Add(total, taskTotal) + End Sub)) + Next + + Try + Task.WaitAll(tasks.ToArray()) + Console.WriteLine() + Console.WriteLine("Mean for all tasks: {0:N2} (N={1:N0})", + (total * 1.0) / n, n) + Catch e As AggregateException + For Each ie In e.InnerExceptions + Console.WriteLine("{0}: {1}", ie.GetType().Name, ie.Message) + Next + End Try + End Sub +End Module +' The example displays output like the following: +' Mean for task 1: 499.04 (N=10,000) +' Mean for task 2: 500.42 (N=10,000) +' Mean for task 3: 499.65 (N=10,000) +' Mean for task 8: 502.59 (N=10,000) +' Mean for task 5: 502.75 (N=10,000) +' Mean for task 4: 494.88 (N=10,000) +' Mean for task 7: 499.22 (N=10,000) +' Mean for task 10: 496.45 (N=10,000) +' Mean for task 6: 499.75 (N=10,000) +' Mean for task 9: 502.79 (N=10,000) +' +' Mean for all tasks: 499.75 (N=100,000) +' diff --git a/snippets/visualbasic/System.Threading/Monitor/Overview/source.vb b/snippets/visualbasic/System.Threading/Monitor/Overview/source.vb new file mode 100644 index 00000000000..9c553540239 --- /dev/null +++ b/snippets/visualbasic/System.Threading/Monitor/Overview/source.vb @@ -0,0 +1,110 @@ +' +Imports System.Threading + +Friend Class SyncResource + ' Use a monitor to enforce synchronization. + Public Sub Access() + SyncLock Me + Console.WriteLine("Starting synchronized resource access on thread #{0}", + Thread.CurrentThread.ManagedThreadId) + If Thread.CurrentThread.ManagedThreadId Mod 2 = 0 Then + Thread.Sleep(2000) + End If + Thread.Sleep(200) + Console.WriteLine("Stopping synchronized resource access on thread #{0}", + Thread.CurrentThread.ManagedThreadId) + End SyncLock + End Sub +End Class + +Friend Class UnSyncResource + ' Do not enforce synchronization. + Public Sub Access() + Console.WriteLine("Starting unsynchronized resource access on Thread #{0}", + Thread.CurrentThread.ManagedThreadId) + If Thread.CurrentThread.ManagedThreadId Mod 2 = 0 Then + Thread.Sleep(2000) + End If + Thread.Sleep(200) + Console.WriteLine("Stopping unsynchronized resource access on thread #{0}", + Thread.CurrentThread.ManagedThreadId) + End Sub +End Class + +Public Module App + Private numOps As Integer + Private opsAreDone As New AutoResetEvent(False) + Private SyncRes As New SyncResource() + Private UnSyncRes As New UnSyncResource() + + Public Sub Main() + ' Set the number of synchronized calls. + numOps = 5 + For ctr As Integer = 0 To 4 + ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf SyncUpdateResource)) + Next + ' Wait until this WaitHandle is signaled. + opsAreDone.WaitOne() + Console.WriteLine(vbTab + Environment.NewLine + "All synchronized operations have completed.") + Console.WriteLine() + + numOps = 5 + ' Reset the count for unsynchronized calls. + For ctr As Integer = 0 To 4 + ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf UnSyncUpdateResource)) + Next + + ' Wait until this WaitHandle is signaled. + opsAreDone.WaitOne() + Console.WriteLine(vbTab + Environment.NewLine + "All unsynchronized thread operations have completed.") + End Sub + + Sub SyncUpdateResource() + ' Call the internal synchronized method. + SyncRes.Access() + + ' Ensure that only one thread can decrement the counter at a time. + If Interlocked.Decrement(numOps) = 0 Then + ' Announce to Main that in fact all thread calls are done. + opsAreDone.Set() + End If + End Sub + + Sub UnSyncUpdateResource() + ' Call the unsynchronized method. + UnSyncRes.Access() + + ' Ensure that only one thread can decrement the counter at a time. + If Interlocked.Decrement(numOps) = 0 Then + ' Announce to Main that in fact all thread calls are done. + opsAreDone.Set() + End If + End Sub +End Module +' The example displays output like the following: +' Starting synchronized resource access on thread #6 +' Stopping synchronized resource access on thread #6 +' Starting synchronized resource access on thread #7 +' Stopping synchronized resource access on thread #7 +' Starting synchronized resource access on thread #3 +' Stopping synchronized resource access on thread #3 +' Starting synchronized resource access on thread #4 +' Stopping synchronized resource access on thread #4 +' Starting synchronized resource access on thread #5 +' Stopping synchronized resource access on thread #5 +' +' All synchronized operations have completed. +' +' Starting unsynchronized resource access on Thread #7 +' Starting unsynchronized resource access on Thread #9 +' Starting unsynchronized resource access on Thread #10 +' Starting unsynchronized resource access on Thread #6 +' Starting unsynchronized resource access on Thread #3 +' Stopping unsynchronized resource access on thread #7 +' Stopping unsynchronized resource access on thread #9 +' Stopping unsynchronized resource access on thread #3 +' Stopping unsynchronized resource access on thread #10 +' Stopping unsynchronized resource access on thread #6 +' +' All unsynchronized thread operations have completed. +' diff --git a/snippets/visualbasic/System.Threading/ReaderWriterLockSlim/Overview/Project.vbproj b/snippets/visualbasic/System.Threading/ReaderWriterLockSlim/Overview/Project.vbproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/visualbasic/System.Threading/ReaderWriterLockSlim/Overview/Project.vbproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/visualbasic/System.Threading/ReaderWriterLockSlim/Overview/classexample1.vb b/snippets/visualbasic/System.Threading/ReaderWriterLockSlim/Overview/classexample1.vb new file mode 100644 index 00000000000..d7943bc2c4c --- /dev/null +++ b/snippets/visualbasic/System.Threading/ReaderWriterLockSlim/Overview/classexample1.vb @@ -0,0 +1,211 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Collections.Generic +Imports System.Threading +Imports System.Threading.Tasks + +' + +' +Public Class SynchronizedCache + Private cacheLock As New ReaderWriterLockSlim() + Private innerCache As New Dictionary(Of Integer, String) + + Public ReadOnly Property Count As Integer + Get + Return innerCache.Count + End Get + End Property + + Public Function Read(ByVal key As Integer) As String + cacheLock.EnterReadLock() + Try + Return innerCache(key) + Finally + cacheLock.ExitReadLock() + End Try + End Function + + Public Sub Add(ByVal key As Integer, ByVal value As String) + cacheLock.EnterWriteLock() + Try + innerCache.Add(key, value) + Finally + cacheLock.ExitWriteLock() + End Try + End Sub + + Public Function AddWithTimeout(ByVal key As Integer, ByVal value As String, _ + ByVal timeout As Integer) As Boolean + If cacheLock.TryEnterWriteLock(timeout) Then + Try + innerCache.Add(key, value) + Finally + cacheLock.ExitWriteLock() + End Try + Return True + Else + Return False + End If + End Function + + Public Function AddOrUpdate(ByVal key As Integer, _ + ByVal value As String) As AddOrUpdateStatus + cacheLock.EnterUpgradeableReadLock() + Try + Dim result As String = Nothing + If innerCache.TryGetValue(key, result) Then + If result = value Then + Return AddOrUpdateStatus.Unchanged + Else + cacheLock.EnterWriteLock() + Try + innerCache.Item(key) = value + Finally + cacheLock.ExitWriteLock() + End Try + Return AddOrUpdateStatus.Updated + End If + Else + cacheLock.EnterWriteLock() + Try + innerCache.Add(key, value) + Finally + cacheLock.ExitWriteLock() + End Try + Return AddOrUpdateStatus.Added + End If + Finally + cacheLock.ExitUpgradeableReadLock() + End Try + End Function + + Public Sub Delete(ByVal key As Integer) + cacheLock.EnterWriteLock() + Try + innerCache.Remove(key) + Finally + cacheLock.ExitWriteLock() + End Try + End Sub + + Public Enum AddOrUpdateStatus + Added + Updated + Unchanged + End Enum + + Protected Overrides Sub Finalize() + If cacheLock IsNot Nothing Then cacheLock.Dispose() + End Sub +End Class +' + +' +Public Module Example + Public Sub Main() + Dim sc As New SynchronizedCache() + Dim tasks As New List(Of Task) + Dim itemsWritten As Integer + + ' Execute a writer. + tasks.Add(Task.Run( Sub() + Dim vegetables() As String = { "broccoli", "cauliflower", + "carrot", "sorrel", "baby turnip", + "beet", "brussel sprout", + "cabbage", "plantain", + "spinach", "grape leaves", + "lime leaves", "corn", + "radish", "cucumber", + "raddichio", "lima beans" } + For ctr As Integer = 1 to vegetables.Length + sc.Add(ctr, vegetables(ctr - 1)) + Next + itemsWritten = vegetables.Length + Console.WriteLine("Task {0} wrote {1} items{2}", + Task.CurrentId, itemsWritten, vbCrLf) + End Sub)) + ' Execute two readers, one to read from first to last and the second from last to first. + For ctr As Integer = 0 To 1 + Dim flag As Integer = ctr + tasks.Add(Task.Run( Sub() + Dim start, last, stp As Integer + Dim items As Integer + Do + Dim output As String = String.Empty + items = sc.Count + If flag = 0 Then + start = 1 : stp = 1 : last = items + Else + start = items : stp = -1 : last = 1 + End If + For index As Integer = start To last Step stp + output += String.Format("[{0}] ", sc.Read(index)) + Next + Console.WriteLine("Task {0} read {1} items: {2}{3}", + Task.CurrentId, items, output, + vbCrLf) + Loop While items < itemsWritten Or itemsWritten = 0 + End Sub)) + Next + ' Execute a read/update task. + tasks.Add(Task.Run( Sub() + For ctr As Integer = 1 To sc.Count + Dim value As String = sc.Read(ctr) + If value = "cucumber" Then + If sc.AddOrUpdate(ctr, "green bean") <> SynchronizedCache.AddOrUpdateStatus.Unchanged Then + Console.WriteLine("Changed 'cucumber' to 'green bean'") + End If + End If + Next + End Sub )) + + ' Wait for all three tasks to complete. + Task.WaitAll(tasks.ToArray()) + + ' Display the final contents of the cache. + Console.WriteLine() + Console.WriteLine("Values in synchronized cache: ") + For ctr As Integer = 1 To sc.Count + Console.WriteLine(" {0}: {1}", ctr, sc.Read(ctr)) + Next + End Sub +End Module +' The example displays output like the following: +' Task 1 read 0 items: +' +' Task 3 wrote 17 items +' +' Task 1 read 17 items: [broccoli] [cauliflower] [carrot] [sorrel] [baby turnip] [ +' beet] [brussel sprout] [cabbage] [plantain] [spinach] [grape leaves] [lime leave +' s] [corn] [radish] [cucumber] [raddichio] [lima beans] +' +' Task 2 read 0 items: +' +' Task 2 read 17 items: [lima beans] [raddichio] [cucumber] [radish] [corn] [lime +' leaves] [grape leaves] [spinach] [plantain] [cabbage] [brussel sprout] [beet] [b +' aby turnip] [sorrel] [carrot] [cauliflower] [broccoli] +' +' Changed 'cucumber' to 'green bean' +' +' Values in synchronized cache: +' 1: broccoli +' 2: cauliflower +' 3: carrot +' 4: sorrel +' 5: baby turnip +' 6: beet +' 7: brussel sprout +' 8: cabbage +' 9: plantain +' 10: spinach +' 11: grape leaves +' 12: lime leaves +' 13: corn +' 14: radish +' 15: green bean +' 16: raddichio +' 17: lima beans +' diff --git a/snippets/visualbasic/System.Threading/Thread/Overview/BackgroundEx1.vb b/snippets/visualbasic/System.Threading/Thread/Overview/BackgroundEx1.vb new file mode 100644 index 00000000000..f3020b9ae83 --- /dev/null +++ b/snippets/visualbasic/System.Threading/Thread/Overview/BackgroundEx1.vb @@ -0,0 +1,39 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Diagnostics +Imports System.Threading + +Module Example1 + Public Sub Main() + Dim th As New Thread(AddressOf ExecuteInForeground) + th.IsBackground = True + th.Start() + Thread.Sleep(1000) + Console.WriteLine("Main thread ({0}) exiting...", Thread.CurrentThread.ManagedThreadId) + End Sub + + Private Sub ExecuteInForeground() + Dim start As DateTime = DateTime.Now + Dim sw As Stopwatch = Stopwatch.StartNew() + Console.WriteLine("Thread {0}: {1}, Priority {2}", + Thread.CurrentThread.ManagedThreadId, + Thread.CurrentThread.ThreadState, + Thread.CurrentThread.Priority) + Do + Console.WriteLine("Thread {0}: Elapsed {1:N2} seconds", + Thread.CurrentThread.ManagedThreadId, + sw.ElapsedMilliseconds / 1000) + Thread.Sleep(500) + Loop While sw.ElapsedMilliseconds <= 5000 + sw.Stop() + End Sub +End Module +' The example displays output like the following: +' Thread 3: Background, Priority Normal +' Thread 3: Elapsed 0.00 seconds +' Thread 3: Elapsed 0.51 seconds +' Main thread (1) exiting... +' + diff --git a/snippets/visualbasic/System.Threading/Thread/Overview/Instance1.vb b/snippets/visualbasic/System.Threading/Thread/Overview/Instance1.vb new file mode 100644 index 00000000000..8f6d5ae3a6e --- /dev/null +++ b/snippets/visualbasic/System.Threading/Thread/Overview/Instance1.vb @@ -0,0 +1,63 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Threading + +Module Example2 + Private lock As New Object() + + Public Sub Main() + ThreadPool.QueueUserWorkItem(AddressOf ShowThreadInformation) + Dim th1 As New Thread(AddressOf ShowThreadInformation) + th1.Start() + Dim th2 As New Thread(AddressOf ShowThreadInformation) + th2.IsBackground = True + th2.Start() + Thread.Sleep(500) + ShowThreadInformation(Nothing) + End Sub + + Private Sub ShowThreadInformation(state As Object) + SyncLock lock + Dim th As Thread = Thread.CurrentThread + Console.WriteLine("Managed thread #{0}: ", th.ManagedThreadId) + Console.WriteLine(" Background thread: {0}", th.IsBackground) + Console.WriteLine(" Thread pool thread: {0}", th.IsThreadPoolThread) + Console.WriteLine(" Priority: {0}", th.Priority) + Console.WriteLine(" Culture: {0}", th.CurrentCulture.Name) + Console.WriteLine(" UI culture: {0}", th.CurrentUICulture.Name) + Console.WriteLine() + End SyncLock + End Sub +End Module +' The example displays output like the following: +' ' Managed thread #6: +' Background thread: True +' Thread pool thread: False +' Priority: Normal +' Culture: en-US +' UI culture: en-US +' +' Managed thread #3: +' Background thread: True +' Thread pool thread: True +' Priority: Normal +' Culture: en-US +' UI culture: en-US +' +' Managed thread #4: +' Background thread: False +' Thread pool thread: False +' Priority: Normal +' Culture: en-US +' UI culture: en-US +' +' Managed thread #1: +' Background thread: False +' Thread pool thread: False +' Priority: Normal +' Culture: en-US +' UI culture: en-US +' + diff --git a/snippets/visualbasic/System.Threading/Thread/Overview/Project.vbproj b/snippets/visualbasic/System.Threading/Thread/Overview/Project.vbproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/visualbasic/System.Threading/Thread/Overview/Project.vbproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/visualbasic/System.Threading/Thread/Overview/ThreadStart1.vb b/snippets/visualbasic/System.Threading/Thread/Overview/ThreadStart1.vb new file mode 100644 index 00000000000..4ddc5ac250a --- /dev/null +++ b/snippets/visualbasic/System.Threading/Thread/Overview/ThreadStart1.vb @@ -0,0 +1,46 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Diagnostics +Imports System.Threading + +Module Example3 + Public Sub Main() + Dim th As New Thread(AddressOf ExecuteInForeground) + th.Start() + Thread.Sleep(1000) + Console.WriteLine("Main thread ({0}) exiting...", Thread.CurrentThread.ManagedThreadId) + End Sub + + Private Sub ExecuteInForeground() + Dim start As DateTime = DateTime.Now + Dim sw As Stopwatch = Stopwatch.StartNew() + Console.WriteLine("Thread {0}: {1}, Priority {2}", + Thread.CurrentThread.ManagedThreadId, + Thread.CurrentThread.ThreadState, + Thread.CurrentThread.Priority) + Do + Console.WriteLine("Thread {0}: Elapsed {1:N2} seconds", + Thread.CurrentThread.ManagedThreadId, + sw.ElapsedMilliseconds / 1000) + Thread.Sleep(500) + Loop While sw.ElapsedMilliseconds <= 5000 + sw.Stop() + End Sub +End Module +' The example displays output like the following: +' Thread 3: Running, Priority Normal +' Thread 3: Elapsed 0.00 seconds +' Thread 3: Elapsed 0.51 seconds +' Main thread (1) exiting... +' Thread 3: Elapsed 1.02 seconds +' Thread 3: Elapsed 1.53 seconds +' Thread 3: Elapsed 2.05 seconds +' Thread 3: Elapsed 2.55 seconds +' Thread 3: Elapsed 3.07 seconds +' Thread 3: Elapsed 3.57 seconds +' Thread 3: Elapsed 4.07 seconds +' Thread 3: Elapsed 4.58 seconds +' + diff --git a/snippets/visualbasic/System.Threading/Thread/Overview/ThreadStart2.vb b/snippets/visualbasic/System.Threading/Thread/Overview/ThreadStart2.vb new file mode 100644 index 00000000000..8bad0fa3512 --- /dev/null +++ b/snippets/visualbasic/System.Threading/Thread/Overview/ThreadStart2.vb @@ -0,0 +1,51 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Diagnostics +Imports System.Threading + +Module Example4 + Public Sub Main() + Dim th As New Thread(AddressOf ExecuteInForeground) + th.Start(4500) + Thread.Sleep(1000) + Console.WriteLine("Main thread ({0}) exiting...", Thread.CurrentThread.ManagedThreadId) + End Sub + + Private Sub ExecuteInForeground(obj As Object) + Dim interval As Integer + If IsNumeric(obj) Then + interval = CInt(obj) + Else + interval = 5000 + End If + Dim start As DateTime = DateTime.Now + Dim sw As Stopwatch = Stopwatch.StartNew() + Console.WriteLine("Thread {0}: {1}, Priority {2}", + Thread.CurrentThread.ManagedThreadId, + Thread.CurrentThread.ThreadState, + Thread.CurrentThread.Priority) + Do + Console.WriteLine("Thread {0}: Elapsed {1:N2} seconds", + Thread.CurrentThread.ManagedThreadId, + sw.ElapsedMilliseconds / 1000) + Thread.Sleep(500) + Loop While sw.ElapsedMilliseconds <= interval + sw.Stop() + End Sub +End Module +' The example displays output like the following: +' Thread 3: Running, Priority Normal +' Thread 3: Elapsed 0.00 seconds +' Thread 3: Elapsed 0.52 seconds +' Main thread (1) exiting... +' Thread 3: Elapsed 1.03 seconds +' Thread 3: Elapsed 1.55 seconds +' Thread 3: Elapsed 2.06 seconds +' Thread 3: Elapsed 2.58 seconds +' Thread 3: Elapsed 3.09 seconds +' Thread 3: Elapsed 3.61 seconds +' Thread 3: Elapsed 4.12 seconds +' + diff --git a/snippets/visualbasic/System.Threading/Thread/Overview/source.vb b/snippets/visualbasic/System.Threading/Thread/Overview/source.vb new file mode 100644 index 00000000000..7f9837184ec --- /dev/null +++ b/snippets/visualbasic/System.Threading/Thread/Overview/source.vb @@ -0,0 +1,45 @@ +' +Imports System.Threading + +' Simple threading scenario: Start a Shared method running +' on a second thread. +Public Class ThreadExample + ' The ThreadProc method is called when the thread starts. + ' It loops ten times, writing to the console and yielding + ' the rest of its time slice each time, and then ends. + Public Shared Sub ThreadProc() + Dim i As Integer + For i = 0 To 9 + Console.WriteLine("ThreadProc: {0}", i) + ' Yield the rest of the time slice. + Thread.Sleep(0) + Next + End Sub + + Public Shared Sub Main() + Console.WriteLine("Main thread: Start a second thread.") + ' The constructor for the Thread class requires a ThreadStart + ' delegate. The Visual Basic AddressOf operator creates this + ' delegate for you. + Dim t As New Thread(AddressOf ThreadProc) + + ' Start ThreadProc. Note that on a uniprocessor, the new + ' thread does not get any processor time until the main thread + ' is preempted or yields. Uncomment the Thread.Sleep that + ' follows t.Start() to see the difference. + t.Start() + 'Thread.Sleep(0) + + Dim i As Integer + For i = 1 To 4 + Console.WriteLine("Main thread: Do some work.") + Thread.Sleep(0) + Next + + Console.WriteLine("Main thread: Call Join(), to wait until ThreadProc ends.") + t.Join() + Console.WriteLine("Main thread: ThreadProc.Join has returned. Press Enter to end program.") + Console.ReadLine() + End Sub +End Class +' diff --git a/xml/System.Text.RegularExpressions/Regex.xml b/xml/System.Text.RegularExpressions/Regex.xml index 89292b8a774..2c835398007 100644 --- a/xml/System.Text.RegularExpressions/Regex.xml +++ b/xml/System.Text.RegularExpressions/Regex.xml @@ -3531,11 +3531,7 @@ specified starting position in the string. An object that contains information about the match. - - For more information about , see - - Supplemental API remarks for Regex.Match. - + To be added. Regular Expression Language - Quick Reference diff --git a/xml/System.Text/Encoding.xml b/xml/System.Text/Encoding.xml index 9c342d046fe..276eb22f5af 100644 --- a/xml/System.Text/Encoding.xml +++ b/xml/System.Text/Encoding.xml @@ -75,7 +75,211 @@ Represents a character encoding. - For more information about this API, see Supplemental API remarks for Encoding. + + class represents a character encoding. + +Encoding is the process of transforming a set of Unicode characters into a sequence of bytes. In contrast, decoding is the process of transforming a sequence of encoded bytes into a set of Unicode characters. For information about the Unicode Transformation Formats (UTFs) and other encodings supported by , see [Character Encoding in .NET](/dotnet/standard/base-types/character-encoding). + + is intended to operate on Unicode characters instead of arbitrary binary data, such as byte arrays. If you must encode arbitrary binary data into text, you should use a protocol such as uuencode, which is implemented by methods such as . + +.NET provides the following implementations of the class to support current Unicode encodings and other encodings: + +- encodes Unicode characters as single 7-bit ASCII characters. This encoding only supports character values between U+0000 and U+007F. Code page 20127. Also available through the property. + +- encodes Unicode characters using the UTF-7 encoding. This encoding supports all Unicode character values. Code page 65000. Also available through the property. + +- encodes Unicode characters using the UTF-8 encoding. This encoding supports all Unicode character values. Code page 65001. Also available through the property. + +- encodes Unicode characters using the UTF-16 encoding. Both little endian and big endian byte orders are supported. Also available through the property and the property. + +- encodes Unicode characters using the UTF-32 encoding. Both little endian (code page 12000) and big endian (code page 12001) byte orders are supported. Also available through the property. + +The class is primarily intended to convert between different encodings and Unicode. Often one of the derived Unicode classes is the correct choice for your app. + +Use the method to obtain other encodings, and call the method to get a list of all encodings. + +## List of encodings + +The following table lists the encodings supported by .NET. It lists each encoding's code page number and the values of the encoding's and properties. A check mark in the **.NET Framework support**, **.NET Core support**, or **.NET 5 and later support** column indicates that the code page is natively supported by that .NET implementation, regardless of the underlying platform. For .NET Framework, the availability of other encodings listed in the table depends on the operating system. For .NET Core and .NET 5 and later versions, other encodings are available by using the class or by deriving from the class. + +> [!NOTE] +> Code pages whose property corresponds to an international standard do not necessarily comply in full with that standard. + +|Code page|Name|Display name|.NET Framework support| .NET Core support | .NET 5 and later support | +|---------|----|------------|----------------------|-------------------|----------------------------| +|37|IBM037|IBM EBCDIC (US-Canada)|||| +|437|IBM437|OEM United States|||| +|500|IBM500|IBM EBCDIC (International)|||| +|708|ASMO-708|Arabic (ASMO 708)|||| +|720|DOS-720|Arabic (DOS)|||| +|737|ibm737|Greek (DOS)|||| +|775|ibm775|Baltic (DOS)|||| +|850|ibm850|Western European (DOS)|||| +|852|ibm852|Central European (DOS)|||| +|855|IBM855|OEM Cyrillic|||| +|857|ibm857|Turkish (DOS)|||| +|858|IBM00858|OEM Multilingual Latin I|||| +|860|IBM860|Portuguese (DOS)|||| +|861|ibm861|Icelandic (DOS)|||| +|862|DOS-862|Hebrew (DOS)|||| +|863|IBM863|French Canadian (DOS)|||| +|864|IBM864|Arabic (864)|||| +|865|IBM865|Nordic (DOS)|||| +|866|cp866|Cyrillic (DOS)|||| +|869|ibm869|Greek, Modern (DOS)|||| +|870|IBM870|IBM EBCDIC (Multilingual Latin-2)|||| +|874|windows-874|Thai (Windows)|||| +|875|cp875|IBM EBCDIC (Greek Modern)|||| +|932|shift_jis|Japanese (Shift-JIS)|||| +|936|gb2312|Chinese Simplified (GB2312)|✓||| +|949|ks_c_5601-1987|Korean|||| +|950|big5|Chinese Traditional (Big5)|||| +|1026|IBM1026|IBM EBCDIC (Turkish Latin-5)|||| +|1047|IBM01047|IBM Latin-1|||| +|1140|IBM01140|IBM EBCDIC (US-Canada-Euro)|||| +|1141|IBM01141|IBM EBCDIC (Germany-Euro)|||| +|1142|IBM01142|IBM EBCDIC (Denmark-Norway-Euro)|||| +|1143|IBM01143|IBM EBCDIC (Finland-Sweden-Euro)|||| +|1144|IBM01144|IBM EBCDIC (Italy-Euro)|||| +|1145|IBM01145|IBM EBCDIC (Spain-Euro)|||| +|1146|IBM01146|IBM EBCDIC (UK-Euro)|||| +|1147|IBM01147|IBM EBCDIC (France-Euro)|||| +|1148|IBM01148|IBM EBCDIC (International-Euro)|||| +|1149|IBM01149|IBM EBCDIC (Icelandic-Euro)|||| +|1200|utf-16|Unicode|✓|✓|✓| +|1201|unicodeFFFE|Unicode (Big endian)|✓|✓|✓| +|1250|windows-1250|Central European (Windows)|||| +|1251|windows-1251|Cyrillic (Windows)|||| +|1252|Windows-1252|Western European (Windows)|✓||| +|1253|windows-1253|Greek (Windows)|||| +|1254|windows-1254|Turkish (Windows)|||| +|1255|windows-1255|Hebrew (Windows)|||| +|1256|windows-1256|Arabic (Windows)|||| +|1257|windows-1257|Baltic (Windows)|||| +|1258|windows-1258|Vietnamese (Windows)|||| +|1361|Johab|Korean (Johab)|||| +|10000|macintosh|Western European (Mac)|||| +|10001|x-mac-japanese|Japanese (Mac)|||| +|10002|x-mac-chinesetrad|Chinese Traditional (Mac)|||| +|10003|x-mac-korean|Korean (Mac)|✓||| +|10004|x-mac-arabic|Arabic (Mac)|||| +|10005|x-mac-hebrew|Hebrew (Mac)|||| +|10006|x-mac-greek|Greek (Mac)|||| +|10007|x-mac-cyrillic|Cyrillic (Mac)|||| +|10008|x-mac-chinesesimp|Chinese Simplified (Mac)|✓||| +|10010|x-mac-romanian|Romanian (Mac)|||| +|10017|x-mac-ukrainian|Ukrainian (Mac)|||| +|10021|x-mac-thai|Thai (Mac)|||| +|10029|x-mac-ce|Central European (Mac)|||| +|10079|x-mac-icelandic|Icelandic (Mac)|||| +|10081|x-mac-turkish|Turkish (Mac)|||| +|10082|x-mac-croatian|Croatian (Mac)|||| +|12000|utf-32|Unicode (UTF-32)|✓|✓|✓| +|12001|utf-32BE|Unicode (UTF-32 Big endian)|✓|✓|✓| +|20000|x-Chinese-CNS|Chinese Traditional (CNS)|||| +|20001|x-cp20001|TCA Taiwan|||| +|20002|x-Chinese-Eten|Chinese Traditional (Eten)|||| +|20003|x-cp20003|IBM5550 Taiwan|||| +|20004|x-cp20004|TeleText Taiwan|||| +|20005|x-cp20005|Wang Taiwan|||| +|20105|x-IA5|Western European (IA5)|||| +|20106|x-IA5-German|German (IA5)|||| +|20107|x-IA5-Swedish|Swedish (IA5)|||| +|20108|x-IA5-Norwegian|Norwegian (IA5)|||| +|20127|us-ascii|US-ASCII|✓|✓|✓| +|20261|x-cp20261|T.61|||| +|20269|x-cp20269|ISO-6937|||| +|20273|IBM273|IBM EBCDIC (Germany)|||| +|20277|IBM277|IBM EBCDIC (Denmark-Norway)|||| +|20278|IBM278|IBM EBCDIC (Finland-Sweden)|||| +|20280|IBM280|IBM EBCDIC (Italy)|||| +|20284|IBM284|IBM EBCDIC (Spain)|||| +|20285|IBM285|IBM EBCDIC (UK)|||| +|20290|IBM290|IBM EBCDIC (Japanese katakana)|||| +|20297|IBM297|IBM EBCDIC (France)|||| +|20420|IBM420|IBM EBCDIC (Arabic)|||| +|20423|IBM423|IBM EBCDIC (Greek)|||| +|20424|IBM424|IBM EBCDIC (Hebrew)|||| +|20833|x-EBCDIC-KoreanExtended|IBM EBCDIC (Korean Extended)|||| +|20838|IBM-Thai|IBM EBCDIC (Thai)|||| +|20866|koi8-r|Cyrillic (KOI8-R)|||| +|20871|IBM871|IBM EBCDIC (Icelandic)|||| +|20880|IBM880|IBM EBCDIC (Cyrillic Russian)|||| +|20905|IBM905|IBM EBCDIC (Turkish)|||| +|20924|IBM00924|IBM Latin-1|||| +|20932|EUC-JP|Japanese (JIS 0208-1990 and 0212-1990)|||| +|20936|x-cp20936|Chinese Simplified (GB2312-80)|✓||| +|20949|x-cp20949|Korean Wansung|✓||| +|21025|cp1025|IBM EBCDIC (Cyrillic Serbian-Bulgarian)|||| +|21866|koi8-u|Cyrillic (KOI8-U)|||| +|28591|iso-8859-1|Western European (ISO)|✓|✓|✓| +|28592|iso-8859-2|Central European (ISO)|||| +|28593|iso-8859-3|Latin 3 (ISO)|||| +|28594|iso-8859-4|Baltic (ISO)|||| +|28595|iso-8859-5|Cyrillic (ISO)|||| +|28596|iso-8859-6|Arabic (ISO)|||| +|28597|iso-8859-7|Greek (ISO)|||| +|28598|iso-8859-8|Hebrew (ISO-Visual)|✓||| +|28599|iso-8859-9|Turkish (ISO)|||| +|28603|iso-8859-13|Estonian (ISO)|||| +|28605|iso-8859-15|Latin 9 (ISO)|||| +|29001|x-Europa|Europa|||| +|38598|iso-8859-8-i|Hebrew (ISO-Logical)|✓||| +|50220|iso-2022-jp|Japanese (JIS)|✓||| +|50221|csISO2022JP|Japanese (JIS-Allow 1 byte Kana)|✓||| +|50222|iso-2022-jp|Japanese (JIS-Allow 1 byte Kana - SO/SI)|✓||| +|50225|iso-2022-kr|Korean (ISO)|✓||| +|50227|x-cp50227|Chinese Simplified (ISO-2022)|✓||| +|51932|euc-jp|Japanese (EUC)|✓||| +|51936|EUC-CN|Chinese Simplified (EUC)|✓||| +|51949|euc-kr|Korean (EUC)|✓||| +|52936|hz-gb-2312|Chinese Simplified (HZ)|✓||| +|54936|GB18030|Chinese Simplified (GB18030)|✓||| +|57002|x-iscii-de|ISCII Devanagari|✓||| +|57003|x-iscii-be|ISCII Bengali|✓||| +|57004|x-iscii-ta|ISCII Tamil|✓||| +|57005|x-iscii-te|ISCII Telugu|✓||| +|57006|x-iscii-as|ISCII Assamese|✓||| +|57007|x-iscii-or|ISCII Oriya|✓||| +|57008|x-iscii-ka|ISCII Kannada|✓||| +|57009|x-iscii-ma|ISCII Malayalam|✓||| +|57010|x-iscii-gu|ISCII Gujarati|✓||| +|57011|x-iscii-pa|ISCII Punjabi|✓||| +|65000|utf-7|Unicode (UTF-7)|✓|✓|| +|65001|utf-8|Unicode (UTF-8)|✓|✓|✓| + +The following example calls the and methods to get the Greek (Windows) code page encoding. It compares the objects returned by the method calls to show that they are equal, and then maps displays the Unicode code point and the corresponding code page value for each character in the Greek alphabet. + +:::code language="csharp" source="~/snippets/csharp/System.Text/Encoding/Overview/getencoding1.cs" id="Snippet1"::: +:::code language="vb" source="~/snippets/visualbasic/System.Text/Encoding/Overview/getencoding1.vb" id="Snippet1"::: + +If the data to be converted is available only in sequential blocks (such as data read from a stream) or if the amount of data is so large that it needs to be divided into smaller blocks, you should use the or the provided by the method or the method, respectively, of a derived class. + +The UTF-16 and the UTF-32 encoders can use the big endian byte order (most significant byte first) or the little endian byte order (least significant byte first). For example, the Latin Capital Letter A (U+0041) is serialized as follows (in hexadecimal): + +- UTF-16 big endian byte order: 00 41 +- UTF-16 little endian byte order: 41 00 +- UTF-32 big endian byte order: 00 00 00 41 +- UTF-32 little endian byte order: 41 00 00 00 + +It is generally more efficient to store Unicode characters using the native byte order. For example, it is better to use the little endian byte order on little endian platforms, such as Intel computers. + +The method retrieves an array of bytes that includes the byte order mark (BOM). If this byte array is prefixed to an encoded stream, it helps the decoder to identify the encoding format used. + +For more information on byte order and the byte order mark, see The Unicode Standard at the [Unicode home page](https://home.unicode.org/). + +Note that the encoding classes allow errors to: + +- Silently change to a "?" character. +- Use a "best fit" character. +- Change to an application-specific behavior through use of the and classes with the U+FFFD Unicode replacement character. + +You should throw an exception on any data stream error. An app either uses a "throwonerror" flag when applicable or uses the and classes. Best fit fallback is often not recommended because it can cause data loss or confusion and is slower than simple character replacements. For ANSI encodings, the best fit behavior is the default. + + ]]> + object that is returned by this property may not have the appropriate behavior for your app. It uses replacement fallback to replace each string that it cannot encode and each byte that it cannot decode with a question mark ("?") character. Instead, you can call the constructor to instantiate a big endian object whose fallback is either an or a , as the following example illustrates. + The object that is returned by this property might not have the appropriate behavior for your app. It uses replacement fallback to replace each string that it cannot encode and each byte that it cannot decode with a question mark ("?") character. Instead, you can call the constructor to instantiate a big endian object whose fallback is either an or a , as the following example illustrates. :::code language="csharp" source="~/snippets/csharp/System.Text/Encoding/BigEndianUnicode/bigendianunicode1.cs" id="Snippet2"::: :::code language="vb" source="~/snippets/visualbasic/System.Text/Encoding/BigEndianUnicode/bigendianunicode1.vb" id="Snippet2"::: @@ -956,7 +1160,10 @@ The property always returns a or with "utf-8". -For more information about this API, see Supplemental API remarks for Encoding.Default. +> [!WARNING] +> Different computers can use different encodings as the default, and the default encoding can change on a single computer. If you use the encoding to encode and decode data streamed between computers or retrieved at different times on the same computer, it might translate that data incorrectly. In addition, the encoding returned by the property uses best-fit fallback to map unsupported characters to characters supported by the code page. For these reasons, using the default encoding is not recommended. To ensure that encoded bytes are decoded properly, you should use a Unicode encoding, such as or . You could also use a higher-level protocol to ensure that the same format is used for encoding and decoding. + +The property always returns the . UTF-8 is supported on all the operating systems (Windows, Linux, and macOS) on which .NET apps run. ]]> diff --git a/xml/System.Text/Rune.xml b/xml/System.Text/Rune.xml index e748b542c16..01e262d58dc 100644 --- a/xml/System.Text/Rune.xml +++ b/xml/System.Text/Rune.xml @@ -71,7 +71,199 @@ Represents a Unicode scalar value ([ U+0000..U+D7FF ], inclusive; or [ U+E000..U+10FFFF ], inclusive). - For more information about this API, see Supplemental API remarks for Rune. + + instance represents a Unicode scalar value, which means any code point excluding the surrogate range (U+D800..U+DFFF). The type's constructors and conversion operators validate the input, so consumers can call the APIs assuming that the underlying instance is well-formed. + +If you aren't familiar with the terms Unicode scalar value, code point, surrogate range, and well-formed, see [Introduction to character encoding in .NET](/dotnet/standard/base-types/character-encoding-introduction). + +## When to use the Rune type + +Consider using the `Rune` type if your code: + +* Calls APIs that require Unicode scalar values +* Explicitly handles surrogate pairs + +### APIs that require Unicode scalar values + +If your code iterates through the `char` instances in a `string` or a `ReadOnlySpan`, some of the `char` methods won't work correctly on `char` instances that are in the surrogate range. For example, the following APIs require a scalar value `char` to work correctly: + +* +* +* +* +* +* +* +* +* +* + +The following example shows code that won't work correctly if any of the `char` instances are surrogate code points: + +:::code language="csharp" source="~/snippets/csharp/System.Text/Rune/Overview/CountLettersInString.cs" id="SnippetBadExample"::: +:::code language="fsharp" source="~/snippets/fsharp/System.Text/Rune/Overview/CountLettersInString.fs" id="SnippetBadExample"::: + +Here's equivalent code that works with a `ReadOnlySpan`: + +:::code language="csharp" source="~/snippets/csharp/System.Text/Rune/Overview/CountLettersInSpan.cs" id="SnippetBadExample"::: + +The preceding code works correctly with some languages such as English: + +```csharp +CountLettersInString("Hello") +// Returns 5 +``` + +But it won't work correctly for languages outside the Basic Multilingual Plane, such as Osage: + +```csharp +CountLettersInString("𐓏𐓘𐓻𐓘𐓻𐓟 𐒻𐓟") +// Returns 0 +``` + +The reason this method returns incorrect results for Osage text is that the `char` instances for Osage letters are surrogate code points. No single surrogate code point has enough information to determine if it's a letter. + +If you change this code to use `Rune` instead of `char`, the method works correctly with code points outside the Basic Multilingual Plane: + +:::code language="csharp" source="~/snippets/csharp/System.Text/Rune/Overview/CountLettersInString.cs" id="SnippetGoodExample"::: +:::code language="fsharp" source="~/snippets/fsharp/System.Text/Rune/Overview/CountLettersInString.fs" id="SnippetGoodExample"::: + +Here's equivalent code that works with a `ReadOnlySpan`: + +:::code language="csharp" source="~/snippets/csharp/System.Text/Rune/Overview/CountLettersInSpan.cs" id="SnippetGoodExample"::: + +The preceding code counts Osage letters correctly: + +```csharp +CountLettersInString("𐓏𐓘𐓻𐓘𐓻𐓟 𐒻𐓟") +// Returns 8 +``` + +### Code that explicitly handles surrogate pairs + +Consider using the `Rune` type if your code calls APIs that explicitly operate on surrogate code points, such as the following methods: + +* +* +* +* +* +* + +For example, the following method has special logic to deal with surrogate `char` pairs: + +:::code language="csharp" source="~/snippets/csharp/System.Text/Rune/Overview/WorkWithSurrogates.cs" id="SnippetUseChar"::: + +Such code is simpler if it uses `Rune`, as in the following example: + +:::code language="csharp" source="~/snippets/csharp/System.Text/Rune/Overview/WorkWithSurrogates.cs" id="SnippetUseRune"::: + +## When not to use `Rune` + +You don't need to use the `Rune` type if your code: + +* Looks for exact `char` matches +* Splits a string on a known char value + +Using the `Rune` type may return incorrect results if your code: + +* Counts the number of display characters in a `string` + +### Look for exact `char` matches + +The following code iterates through a `string` looking for specific characters, returning the index of the first match. There's no need to change this code to use `Rune`, as the code is looking for characters that are represented by a single `char`. + +:::code language="csharp" source="~/snippets/csharp/System.Text/Rune/Overview/FindFirstLetter.cs" id="SnippetExample"::: + +### Split a string on a known `char` + +It's common to call `string.Split` and use delimiters such as `' '` (space) or `','` (comma), as in the following example: + +:::code language="csharp" source="~/snippets/csharp/System.Text/Rune/Overview/SplitStringOnChar.cs" id="SnippetExample"::: + +There is no need to use `Rune` here, because the code is looking for characters that are represented by a single `char`. + +### Count the number of display characters in a `string` + +The number of `Rune` instances in a string might not match the number of user-perceivable characters shown when displaying the string. + +Since `Rune` instances represent Unicode scalar values, components that follow the [Unicode text segmentation guidelines](https://www.unicode.org/reports/tr29/) can use `Rune` as a building block for counting display characters. + +The type can be used to count display characters, but it doesn't count correctly in all scenarios for .NET implementations other than .NET 5+. + +For more information, see [Grapheme clusters](https://learn.microsoft.com/dotnet/standard/base-types/character-encoding-introduction#grapheme-clusters). + +## How to instantiate a `Rune` + +There are several ways to get a `Rune` instance. You can use a constructor to create a `Rune` directly from: + +* A code point. + + :::code language="csharp" source="~/snippets/csharp/System.Text/Rune/Overview/InstantiateRunes.cs" id="SnippetCodePoint"::: + +* A single `char`. + + :::code language="csharp" source="~/snippets/csharp/System.Text/Rune/Overview/InstantiateRunes.cs" id="SnippetChar"::: + +* A surrogate `char` pair. + + :::code language="csharp" source="~/snippets/csharp/System.Text/Rune/Overview/InstantiateRunes.cs" id="SnippetSurrogate"::: + +All of the constructors throw an `ArgumentException` if the input doesn't represent a valid Unicode scalar value. + +There are methods available for callers who don't want exceptions to be thrown on failure. + +`Rune` instances can also be read from existing input sequences. For instance, given a `ReadOnlySpan` that represents UTF-16 data, the method returns the first `Rune` instance at the beginning of the input span. The method operates similarly, accepting a `ReadOnlySpan` parameter that represents UTF-8 data. There are equivalent methods to read from the end of the span instead of the beginning of the span. + +## Query properties of a `Rune` + +To get the integer code point value of a `Rune` instance, use the property. + +:::code language="csharp" source="~/snippets/csharp/System.Text/Rune/Overview/InstantiateRunes.cs" id="SnippetValue"::: + +Many of the static APIs available on the `char` type are also available on the `Rune` type. For instance, and are equivalents to and methods. The `Rune` methods correctly handle surrogate pairs. + +The following example code takes a `ReadOnlySpan` as input and trims from both the start and the end of the span every `Rune` that isn't a letter or a digit. + +:::code language="csharp" source="~/snippets/csharp/System.Text/Rune/Overview/TrimNonLettersAndNonDigits.cs" id="SnippetExample"::: + +There are some API differences between `char` and `Rune`. For example: + +* There is no `Rune` equivalent to , since `Rune` instances by definition can never be surrogate code points. +* The doesn't always return the same result as . It does return the same value as . For more information, see the **Remarks** on . + +## Convert a `Rune` to UTF-8 or UTF-16 + +Since a `Rune` is a Unicode scalar value, it can be converted to UTF-8, UTF-16, or UTF-32 encoding. The `Rune` type has built-in support for conversion to UTF-8 and UTF-16. + +The converts a `Rune` instance to `char` instances. To query the number of `char` instances that would result from converting a `Rune` instance to UTF-16, use the property. Similar methods exist for UTF-8 conversion. + +The following example converts a `Rune` instance to a `char` array. The code assumes you have a `Rune` instance in the `rune` variable: + +:::code language="csharp" source="~/snippets/csharp/System.Text/Rune/Overview/EncodeRune.cs" id="SnippetUtf16CharArray"::: + +Since a `string` is a sequence of UTF-16 chars, the following example also converts a `Rune` instance to UTF-16: + +:::code language="csharp" source="~/snippets/csharp/System.Text/Rune/Overview/EncodeRune.cs" id="SnippetUtf16String"::: + +The following example converts a `Rune` instance to a `UTF-8` byte array: + +:::code language="csharp" source="~/snippets/csharp/System.Text/Rune/Overview/EncodeRune.cs" id="SnippetUtf8ByteArray"::: + +The and methods return the actual number of elements written. They throw an exception if the destination buffer is too short to contain the result. There are non-throwing and methods as well for callers who want to avoid exceptions. + +## Rune in .NET vs. other languages + +The term "rune" is not defined in the Unicode Standard. The term dates back to [the creation of UTF-8](https://www.cl.cam.ac.uk/~mgk25/ucs/utf-8-history.txt). Rob Pike and Ken Thompson were looking for a term to describe what would eventually become known as a code point. [They settled on the term "rune"](https://twitter.com/rob_pike/status/732353233474064384), and Rob Pike's later influence over the Go programming language helped popularize the term. + +However, the .NET `Rune` type is not the equivalent of the Go `rune` type. In Go, the `rune` type is an [alias for `int32`](https://blog.golang.org/strings). A Go rune is intended to represent a Unicode code point, but it can be any 32-bit value, including surrogate code points and values that are not legal Unicode code points. + +For similar types in other programming languages, see [Rust's primitive `char` type](https://doc.rust-lang.org/std/primitive.char.html) or [Swift's `Unicode.Scalar` type](https://developer.apple.com/documentation/swift/unicode/scalar), both of which represent Unicode scalar values. They provide functionality similar to .NET's `Rune` type, and they disallow instantiation of values that are not legal Unicode scalar values. + + ]]> + diff --git a/xml/System.Text/StringBuilder.xml b/xml/System.Text/StringBuilder.xml index e7a95437c29..7a6691a92f9 100644 --- a/xml/System.Text/StringBuilder.xml +++ b/xml/System.Text/StringBuilder.xml @@ -64,7 +64,206 @@ Represents a mutable string of characters. This class cannot be inherited. - For more information about this API, see Supplemental API remarks for StringBuilder. + + class represents a string-like object whose value is a mutable sequence of characters. + +## StringBuilder versus String type + +Although and both represent sequences of characters, they are implemented differently. is an immutable type. That is, each operation that appears to modify a object actually creates a new string. + +For example, the call to the method in the following C# example appears to change the value of a string variable named `value`. In fact, the method returns a `value` object that has a different value and address from the `value` object that was passed to the method. Note that the example must be compiled using the `/unsafe` compiler option. + +:::code language="csharp" source="~/snippets/csharp/System.Text/StringBuilder/Overview/immutability2.cs" id="Snippet1"::: +:::code language="fsharp" source="~/snippets/fsharp/System.Text/StringBuilder/Overview/immutability2.fs" id="Snippet1"::: + +For routines that perform extensive string manipulation (such as apps that modify a string numerous times in a loop), modifying a string repeatedly can exert a significant performance penalty. The alternative is to use , which is a mutable string class. Mutability means that once an instance of the class has been created, it can be modified by appending, removing, replacing, or inserting characters. + +> [!IMPORTANT] +> Although the class generally offers better performance than the class, you should not automatically replace with whenever you want to manipulate strings. Performance depends on the size of the string, the amount of memory to be allocated for the new string, the system on which your code is executing, and the type of operation. You should be prepared to test your code to determine whether actually offers a significant performance improvement. + +Consider using the class under these conditions: + +- When the number of changes that your code will make to a string is small. In these cases, might offer negligible or no performance improvement over . +- When you perform a fixed number of concatenation operations, particularly with string literals. In this case, the compiler might combine the concatenation operations into a single operation. +- When you have to perform extensive search operations while you are building your string. The class lacks search methods such as `IndexOf` or `StartsWith`. You'll have to convert the object to a for these operations, and this can negate the performance benefit from using . For more information, see the [Search the text in a StringBuilder object](#search-the-text-in-a-stringbuilder-object) section. + +Consider using the class under these conditions: + +- When you expect your code to make an unknown number of changes to a string at design time (for example, when you use a loop to concatenate a random number of strings that contain user input). +- When you expect your code to make a significant number of changes to a string. + +## How StringBuilder works + +The property indicates the number of characters the object currently contains. If you add characters to the object, its length increases until it equals the size of the property, which defines the number of characters that the object can contain. If the number of added characters causes the length of the object to exceed its current capacity, new memory is allocated, the value of the property is doubled, new characters are added to the object, and its property is adjusted. Additional memory for the object is allocated dynamically until it reaches the value defined by the property. When the maximum capacity is reached, no further memory can be allocated for the object, and trying to add characters or expand it beyond its maximum capacity throws either an or an exception. + +The following example illustrates how a object allocates new memory and increases its capacity dynamically as the string assigned to the object expands. The code creates a object by calling its default (parameterless) constructor. The default capacity of this object is 16 characters, and its maximum capacity is more than 2 billion characters. Appending the string "This is a sentence." results in a new memory allocation because the string length (19 characters) exceeds the default capacity of the object. The capacity of the object doubles to 32 characters, the new string is added, and the length of the object now equals 19 characters. The code then appends the string "This is an additional sentence." to the value of the object 11 times. Whenever the append operation causes the length of the object to exceed its capacity, its existing capacity is doubled and the operation succeeds. + +:::code language="csharp" source="~/snippets/csharp/System.Text/StringBuilder/Overview/default1.cs" id="Snippet3"::: +:::code language="fsharp" source="~/snippets/fsharp/System.Text/StringBuilder/Overview/default1.fs" id="Snippet3"::: +:::code language="vb" source="~/snippets/visualbasic/System.Text/StringBuilder/Overview/default1.vb" id="Snippet3"::: + +## Memory allocation + +The default capacity of a object is 16 characters, and its default maximum capacity is . These default values are used if you call the and constructors. + +You can explicitly define the initial capacity of a object in the following ways: + +- By calling any of the constructors that includes a `capacity` parameter when you create the object. +- By explicitly assigning a new value to the property to expand an existing object. (The property throws an exception if the new capacity is less than the existing capacity or greater than the object's maximum capacity.) +- By calling the method with the new capacity. The new capacity must not be greater than the object's maximum capacity. However, unlike an assignment to the property, does not throw an exception if the desired new capacity is less than the existing capacity. In this case, the method call has no effect. + +If the length of the string assigned to the object in the constructor call exceeds either the default capacity or the specified capacity, the property is set to the length of the string specified with the `value` parameter. + +You can explicitly define the maximum capacity of a object by calling the constructor. You can't change the maximum capacity by assigning a new value to the property, because it is read-only. + +As the previous section shows, whenever the existing capacity is inadequate, additional memory is allocated and the capacity of a object doubles up to the value defined by the property. + +In general, the default capacity and maximum capacity are adequate for most apps. You might consider setting these values under the following conditions: + +- If the eventual size of the object is likely to grow exceedingly large, typically in excess of several megabytes. In this case, there might be some performance benefit from setting the initial property to a significantly high value to eliminate the need for too many memory reallocations. +- If your code is running on a system with limited memory. In this case, you might consider setting the property to less than if your code is handling large strings that might cause it to execute in a memory-constrained environment. + +## Instantiate a StringBuilder object + +You instantiate a object by calling one of its six overloaded class constructors, which are listed in the following table. Three of the constructors instantiate a object whose value is an empty string, but set its and values differently. The remaining three constructors define a object that has a specific string value and capacity. Two of the three constructors use the default maximum capacity of , whereas the third allows you to set the maximum capacity. + +| Constructor | String value | Capacity | Maximum capacity | +|-------------|--------------|----------|------------------| +|||16|| +|||Defined by the `capacity` parameter|| +|||Defined by the `capacity` parameter|Defined by the `maxCapacity` parameter| +||Defined by the `value` parameter|16 or `value`. , whichever is greater|| +||Defined by the `value` parameter|Defined by the `capacity` parameter or `value`. , whichever is greater.|| +||Defined by `value`. (`startIndex`, `length`)|Defined by the `capacity` parameter or `value`. , whichever is greater.|| + +The following example uses three of these constructor overloads to instantiate objects. + +:::code language="csharp" source="~/snippets/csharp/System.Text/StringBuilder/Overview/instantiate1.cs" id="Snippet6"::: +:::code language="fsharp" source="~/snippets/fsharp/System.Text/StringBuilder/Overview/instantiate1.fs" id="Snippet6"::: +:::code language="vb" source="~/snippets/visualbasic/System.Text/StringBuilder/Overview/instantiate1.vb" id="Snippet6"::: + +## Call StringBuilder methods + +Most of the methods that modify the string in a instance return a reference to that same instance. This enables you to call methods in two ways: + +- You can make individual method calls and ignore the return value, as the following example does. + + :::code language="csharp" source="~/snippets/csharp/System.Text/StringBuilder/Overview/call1.cs" id="Snippet4"::: + :::code language="fsharp" source="~/snippets/fsharp/System.Text/StringBuilder/Overview/call1.fs" id="Snippet4"::: + :::code language="vb" source="~/snippets/visualbasic/System.Text/StringBuilder/Overview/call1.vb" id="Snippet4"::: + +- You can make a series of method calls in a single statement. This can be convenient if you want to write a single statement that chains successive operations. The following example consolidates three method calls from the previous example into a single line of code. + + :::code language="csharp" source="~/snippets/csharp/System.Text/StringBuilder/Overview/call2.cs" id="Snippet5"::: + :::code language="fsharp" source="~/snippets/fsharp/System.Text/StringBuilder/Overview/call2.fs" id="Snippet5"::: + :::code language="vb" source="~/snippets/visualbasic/System.Text/StringBuilder/Overview/call2.vb" id="Snippet5"::: + +## Perform StringBuilder operations + +You can use the methods of the class to iterate, add, delete, or modify characters in a object. + +### Iterate StringBuilder characters + +You can access the characters in a object by using the property. In C#, is an indexer; in Visual Basic, it is the default property of the class. This enables you to set or retrieve individual characters by using their index only, without explicitly referencing the property. Characters in a object begin at index 0 (zero) and continue to index - 1. + +The following example illustrates the property. It appends ten random numbers to a object, and then iterates each character. If the character's Unicode category is , it decreases the number by 1 (or changes the number to 9 if its value is 0). The example displays the contents of the object both before and after the values of individual characters were changed. + +:::code language="csharp" source="~/snippets/csharp/System.Text/StringBuilder/Overview/chars1.cs" id="Snippet7"::: +:::code language="fsharp" source="~/snippets/fsharp/System.Text/StringBuilder/Overview/chars1.fs" id="Snippet7"::: +:::code language="vb" source="~/snippets/visualbasic/System.Text/StringBuilder/Overview/chars1.vb" id="Snippet7"::: + +[!INCLUDE[stringbuilder-performance-note](~/includes/stringbuilder-perf-note.md)] + +### Add text to a StringBuilder object + +The class includes the following methods for expanding the contents of a object: + +- The method appends a string, a substring, a character array, a portion of a character array, a single character repeated multiple times, or the string representation of a primitive data type to a object. + +- The method appends a line terminator or a string along with a line terminator to a object. + +- The method appends a [composite format string](/dotnet/standard/base-types/composite-formatting) to a object. The string representations of objects included in the result string can reflect the formatting conventions of the current system culture or a specified culture. + +- The method inserts a string, a substring, multiple repetitions of a string, a character array, a portion of a character array, or the string representation of a primitive data type at a specified position in the object. The position is defined by a zero-based index. + +The following example uses the , , , and methods to expand the text of a object. + + :::code language="csharp" source="~/snippets/csharp/System.Text/StringBuilder/Overview/expand1.cs" id="Snippet9"::: + :::code language="fsharp" source="~/snippets/fsharp/System.Text/StringBuilder/Overview/expand1.fs" id="Snippet9"::: + :::code language="vb" source="~/snippets/visualbasic/System.Text/StringBuilder/Overview/expand1.vb" id="Snippet9"::: + +### Delete text from a StringBuilder object + +The class includes methods that can reduce the size of the current instance. The method removes all characters and sets the property to zero. The method deletes a specified number of characters starting at a particular index position. In addition, you can remove characters from the end of a object by setting its property to a value that is less than the length of the current instance. + +The following example removes some of the text from a object, displays its resulting capacity, maximum capacity, and length property values, and then calls the method to remove all the characters from the object. + +:::code language="csharp" source="~/snippets/csharp/System.Text/StringBuilder/Overview/delete1.cs" id="Snippet10"::: +:::code language="fsharp" source="~/snippets/fsharp/System.Text/StringBuilder/Overview/delete1.fs" id="Snippet10"::: +:::code language="vb" source="~/snippets/visualbasic/System.Text/StringBuilder/Overview/delete1.vb" id="Snippet10"::: + +### Modify the text in a StringBuilder object + +The method replaces all occurrences of a character or a string in the entire object or in a particular character range. The following example uses the method to replace all exclamation points (!) with question marks (?) in the object. + +:::code language="csharp" source="~/snippets/csharp/System.Text/StringBuilder/Overview/replace1.cs" id="Snippet11"::: +:::code language="fsharp" source="~/snippets/fsharp/System.Text/StringBuilder/Overview/replace1.fs" id="Snippet11"::: +:::code language="vb" source="~/snippets/visualbasic/System.Text/StringBuilder/Overview/replace1.vb" id="Snippet11"::: + +## Search the text in a StringBuilder object + +The class does not include methods similar to the , , and methods provided by the class, which allow you to search the object for a particular character or a substring. Determining the presence or starting character position of a substring requires that you search a value by using either a string search method or a regular expression method. There are four ways to implement such searches, as the following table shows. + +| Technique | Pros | Cons | +|-----------|------|------| +|Search string values before adding them to the object.|Useful for determining whether a substring exists.|Cannot be used when the index position of a substring is important.| +|Call and search the returned object.|Easy to use if you assign all the text to a object, and then begin to modify it.|Cumbersome to repeatedly call if you must make modifications before all text is added to the object.

You must remember to work from the end of the object's text if you're making changes.| +|Use the property to sequentially search a range of characters.|Useful if you're concerned with individual characters or a small substring.|Cumbersome if the number of characters to search is large or if the search logic is complex.

Results in very poor performance for objects that have grown very large through repeated method calls. | +|Convert the object to a object, and perform modifications on the object.|Useful if the number of modifications is small.|Negates the performance benefit of the class if the number of modifications is large.| + +Let's examine these techniques in greater detail. + +- If the goal of the search is to determine whether a particular substring exists (that is, if you aren't interested in the position of the substring), you can search strings before storing them in the object. The following example provides one possible implementation. It defines a `StringBuilderFinder` class whose constructor is passed a reference to a object and the substring to find in the string. In this case, the example tries to determine whether recorded temperatures are in Fahrenheit or Celsius, and adds the appropriate introductory text to the beginning of the object. A random number generator is used to select an array that contains data in either degrees Celsius or degrees Fahrenheit. + + :::code language="csharp" source="~/snippets/csharp/System.Text/StringBuilder/Overview/pattern1.cs" id="Snippet12"::: + :::code language="fsharp" source="~/snippets/fsharp/System.Text/StringBuilder/Overview/pattern1.fs" id="Snippet12"::: + :::code language="vb" source="~/snippets/visualbasic/System.Text/StringBuilder/Overview/pattern1.vb" id="Snippet12"::: + +- Call the method to convert the object to a object. You can search the string by using methods such as or , or you can use regular expressions and the class to search for patterns. Because both and objects use UTF-16 encoding to store characters, the index positions of characters, substrings, and regular expression matches are the same in both objects. This enables you to use methods to make changes at the same position at which that text is found in the object. + + > [!NOTE] + > If you adopt this approach, you should work from the end of the object to its beginning so that you don't have to repeatedly convert the object to a string. + + The following example illustrates this approach. It stores four occurrences of each letter of the English alphabet in a object. It then converts the text to a object and uses a regular expression to identify the starting position of each four-character sequence. Finally, it adds an underscore before each four-character sequence except for the first sequence, and converts the first character of the sequence to uppercase. + + :::code language="csharp" source="~/snippets/csharp/System.Text/StringBuilder/Overview/pattern2.cs" id="Snippet13"::: + :::code language="fsharp" source="~/snippets/fsharp/System.Text/StringBuilder/Overview/pattern2.fs" id="Snippet13"::: + :::code language="vb" source="~/snippets/visualbasic/System.Text/StringBuilder/Overview/pattern2.vb" id="Snippet13"::: + +- Use the property to sequentially search a range of characters in a object. This approach might not be practical if the number of characters to be searched is large or the search logic is particularly complex. For the performance implications of character-by-character index-based access for very large, chunked objects, see the documentation for the property. + + The following example is identical in functionality to the previous example but differs in implementation. It uses the property to detect when a character value has changed, inserts an underscore at that position, and converts the first character in the new sequence to uppercase. + + :::code language="csharp" source="~/snippets/csharp/System.Text/StringBuilder/Overview/pattern3.cs" id="Snippet14"::: + :::code language="fsharp" source="~/snippets/fsharp/System.Text/StringBuilder/Overview/pattern3.fs" id="Snippet14"::: + :::code language="vb" source="~/snippets/visualbasic/System.Text/StringBuilder/Overview/pattern3.vb" id="Snippet14"::: + +- Store all the unmodified text in the object, call the method to convert the object to a object, and perform the modifications on the object. You can use this approach if you have only a few modifications; otherwise, the cost of working with immutable strings might negate the performance benefits of using a object. + + The following example is identical in functionality to the previous two examples but differs in implementation. It creates a object, converts it to a object, and then uses a regular expression to perform all remaining modifications on the string. The method uses a lambda expression to perform the replacement on each match. + + :::code language="csharp" source="~/snippets/csharp/System.Text/StringBuilder/Overview/pattern4.cs" id="Snippet15"::: + :::code language="fsharp" source="~/snippets/fsharp/System.Text/StringBuilder/Overview/pattern4.fs" id="Snippet15"::: + :::code language="vb" source="~/snippets/visualbasic/System.Text/StringBuilder/Overview/pattern4.vb" id="Snippet15"::: + +## Convert the StringBuilder object to a string + +You must convert the object to a object before you can pass the string represented by the object to a method that has a parameter or display it in the user interface. You perform this conversion by calling the method. For an illustration, see the previous example, which calls the method to convert a object to a string so that it can be passed to a regular expression method. + + ]]>
+
class. diff --git a/xml/System.Threading.Tasks/Task.xml b/xml/System.Threading.Tasks/Task.xml index d370d2fe4ce..a7cc342dc93 100644 --- a/xml/System.Threading.Tasks/Task.xml +++ b/xml/System.Threading.Tasks/Task.xml @@ -76,7 +76,104 @@ Represents an asynchronous operation. - For more information about this API, see Supplemental API remarks for Task. + + class represents a single operation that does not return a value and that usually executes asynchronously. objects are one of the central components of the [task-based asynchronous pattern](/dotnet/standard/asynchronous-programming-patterns/task-based-asynchronous-pattern-tap). Because the work performed by a object typically executes asynchronously on a thread pool thread rather than synchronously on the main application thread, you can use the property, as well as the , , and properties, to determine the state of a task. Most commonly, a lambda expression is used to specify the work that the task is to perform. + +For operations that return values, you use the class. + +## Task instantiation + +The following example creates and executes four tasks. Three tasks execute an delegate named `action`, which accepts an argument of type . A fourth task executes a lambda expression (an delegate) that is defined inline in the call to the task creation method. Each task is instantiated and run in a different way: + +- Task `t1` is instantiated by calling a Task class constructor, but is started by calling its method only after task `t2` has started. + +- Task `t2` is instantiated and started in a single method call by calling the method. + +- Task `t3` is instantiated and started in a single method call by calling the method. + +- Task `t4` is executed synchronously on the main thread by calling the method. + +Because task `t4` executes synchronously, it executes on the main application thread. The remaining tasks execute asynchronously typically on one or more thread pool threads. + +:::code language="csharp" source="~/snippets/csharp/System.Threading.Tasks/Task/Overview/startnew.cs" id="Snippet01"::: +:::code language="fsharp" source="~/snippets/fsharp/System.Threading.Tasks/Task/Overview/startnew.fs" id="Snippet01"::: +:::code language="vb" source="~/snippets/visualbasic/System.Threading.Tasks/Task/Overview/startnew.vb" id="Snippet01"::: + +## Create and execute a task + +You can create instances in a variety of ways. The most common approach is to call the static method. The method provides a simple way to start a task using default values and without requiring additional parameters. The following example uses the method to start a task that loops and then displays the number of loop iterations: + +:::code language="csharp" source="~/snippets/csharp/System.Threading.Tasks/Task/Overview/run1.cs" id="Snippet6"::: +:::code language="fsharp" source="~/snippets/fsharp/System.Threading.Tasks/Task/Overview/run1.fs" id="Snippet6"::: +:::code language="vb" source="~/snippets/visualbasic/System.Threading.Tasks/Task/Overview/run1.vb" id="Snippet6"::: + +An alternative is the static method. The property returns a object. Overloads of the method let you specify parameters to pass to the task creation options and a task scheduler. The following example uses the method to start a task. It is functionally equivalent to the code in the previous example. + +:::code language="csharp" source="~/snippets/csharp/System.Threading.Tasks/Task/Overview/startnew1.cs" id="Snippet7"::: +:::code language="fsharp" source="~/snippets/fsharp/System.Threading.Tasks/Task/Overview/startnew1.fs" id="Snippet7"::: +:::code language="vb" source="~/snippets/visualbasic/System.Threading.Tasks/Task/Overview/startnew1.vb" id="Snippet7"::: + +For more complete examples, see [Task-based Asynchronous Programming](/dotnet/standard/parallel-programming/task-based-asynchronous-programming). + +## Separate task creation and execution + +The class also provides constructors that initialize the task but that do not schedule it for execution. For performance reasons, the or method is the preferred mechanism for creating and scheduling computational tasks, but for scenarios where creation and scheduling must be separated, you can use the constructors and then call the method to schedule the task for execution at a later time. + +## Wait for a task to complete + +Because tasks typically run asynchronously on a thread pool thread, the thread that creates and starts the task continues execution as soon as the task has been instantiated. In some cases, when the calling thread is the main application thread, the app may terminate before the task actually begins execution. In others, your application's logic may require that the calling thread continue execution only when one or more tasks have completed execution. You can synchronize the execution of the calling thread and the asynchronous tasks it launches by calling a `Wait` method to wait for one or more tasks to complete. + +To wait for a single task to complete, you can call its method. A call to the method blocks the calling thread until the single class instance has completed execution. + +The following example calls the parameterless method to wait unconditionally until a task completes. The task simulates work by calling the method to sleep for two seconds. + +:::code language="csharp" source="~/snippets/csharp/System.Threading.Tasks/Task/Overview/Wait1.cs" id="Snippet8"::: +:::code language="fsharp" source="~/snippets/fsharp/System.Threading.Tasks/Task/Overview/Wait1.fs" id="Snippet8"::: +:::code language="vb" source="~/snippets/visualbasic/System.Threading.Tasks/Task/Overview/Wait1.vb" id="Snippet8"::: + +You can also conditionally wait for a task to complete. The and methods block the calling thread until the task finishes or a timeout interval elapses, whichever comes first. Since the following example launches a task that sleeps for two seconds but defines a one-second timeout value, the calling thread blocks until the timeout expires and before the task has completed execution. + +:::code language="csharp" source="~/snippets/csharp/System.Threading.Tasks/Task/Overview/Wait2.cs" id="Snippet9"::: +:::code language="fsharp" source="~/snippets/fsharp/System.Threading.Tasks/Task/Overview/Wait2.fs" id="Snippet9"::: +:::code language="vb" source="~/snippets/visualbasic/System.Threading.Tasks/Task/Overview/Wait2.vb" id="Snippet9"::: + +You can also supply a cancellation token by calling the and methods. If the token's property is `true` or becomes `true` while the method is executing, the method throws an . + +In some cases, you may want to wait for the first of a series of executing tasks to complete, but don't care which task it is. For this purpose, you can call one of the overloads of the method. The following example creates three tasks, each of which sleeps for an interval determined by a random number generator. The method waits for the first task to complete. The example then displays information about the status of all three tasks. + +:::code language="csharp" source="~/snippets/csharp/System.Threading.Tasks/Task/Overview/WhenAny1.cs" id="Snippet10"::: +:::code language="fsharp" source="~/snippets/fsharp/System.Threading.Tasks/Task/Overview/WhenAny1.fs" id="Snippet10"::: +:::code language="vb" source="~/snippets/visualbasic/System.Threading.Tasks/Task/Overview/WaitAny1.vb" id="Snippet10"::: + +You can also wait for all of a series of tasks to complete by calling the method. The following example creates ten tasks, waits for all ten to complete, and then displays their status. + +:::code language="csharp" source="~/snippets/csharp/System.Threading.Tasks/Task/Overview/WaitAll1.cs" id="Snippet11"::: +:::code language="fsharp" source="~/snippets/fsharp/System.Threading.Tasks/Task/Overview/WaitAll1.fs" id="Snippet11"::: +:::code language="vb" source="~/snippets/visualbasic/System.Threading.Tasks/Task/Overview/WaitAll1.vb" id="Snippet11"::: + +Note that when you wait for one or more tasks to complete, any exceptions thrown in the running tasks are propagated on the thread that calls the `Wait` method, as the following example shows. It launches 12 tasks, three of which complete normally and three of which throw an exception. Of the remaining six tasks, three are cancelled before they start, and three are cancelled while they are executing. Exceptions are thrown in the method call and are handled by a `try`/`catch` block. + +:::code language="csharp" source="~/snippets/csharp/System.Threading.Tasks/Task/Overview/WaitAll2.cs" id="Snippet12"::: +:::code language="fsharp" source="~/snippets/fsharp/System.Threading.Tasks/Task/Overview/WaitAll2.fs" id="Snippet12"::: +:::code language="vb" source="~/snippets/visualbasic/System.Threading.Tasks/Task/Overview/WaitAll2.vb" id="Snippet12"::: + +For more information on exception handling in task-based asynchronous operations, see [Exception Handling](/dotnet/standard/parallel-programming/exception-handling-task-parallel-library). + +## Tasks and culture + +Starting with desktop apps that target .NET Framework 4.6, the culture of the thread that creates and invokes a task becomes part of the thread's context. That is, regardless of the current culture of the thread on which the task executes, the current culture of the task is the culture of the calling thread. For apps that target versions of .NET Framework prior to .NET Framework 4.6, the culture of the task is the culture of the thread on which the task executes. For more information, see the "Culture and task-based asynchronous operations" section in the topic. + +> [!NOTE] +> Store apps follow the Windows Runtime in setting and getting the default culture. + +## For debugger developers + +For developers implementing custom debuggers, several internal and private members of task may be useful (these may change from release to release). The `m_taskId` field serves as the backing store for the property, however accessing this field directly from a debugger may be more efficient than accessing the same value through the property's getter method (the `s_taskIdCounter` counter is used to retrieve the next available ID for a task). Similarly, the `m_stateFlags` field stores information about the current lifecycle stage of the task, information also accessible through the property. The `m_action` field stores a reference to the task's delegate, and the `m_stateObject` field stores the async state passed to the task by the developer. Finally, for debuggers that parse stack frames, the `InternalWait` method serves a potential marker for when a task is entering a wait operation. + + ]]> + All members of , except for , are thread-safe and may be used from multiple threads concurrently. Task Parallel Library (TPL) diff --git a/xml/System.Threading.Tasks/TaskScheduler.xml b/xml/System.Threading.Tasks/TaskScheduler.xml index 7abfcd233c7..bb3b8953674 100644 --- a/xml/System.Threading.Tasks/TaskScheduler.xml +++ b/xml/System.Threading.Tasks/TaskScheduler.xml @@ -64,13 +64,70 @@ Represents an object that handles the low-level work of queuing tasks onto threads. - For more information about this API, see Supplemental API remarks for TaskScheduler. + + class represents a task scheduler. A task scheduler ensures that the work of a task is eventually executed. + +The default task scheduler provides work-stealing for load-balancing, thread injection/retirement for maximum throughput, and overall good performance. It should be sufficient for most scenarios. + +The class also serves as the extension point for all customizable scheduling logic. This includes mechanisms such as how to schedule a task for execution, and how scheduled tasks should be exposed to debuggers. If you require special functionality, you can create a custom scheduler and enable it for specific tasks or queries. + +## The default task scheduler and the thread pool + +The default scheduler for the Task Parallel Library and PLINQ uses the .NET thread pool, which is represented by the class, to queue and execute work. The thread pool uses the information that is provided by the type to efficiently support the fine-grained parallelism (short-lived units of work) that parallel tasks and queries often represent. + +### The global queue vs. local queues + +The thread pool maintains a global FIFO (first-in, first-out) work queue for threads in each application domain. Whenever a program calls the (or ) method, the work is put on this shared queue and eventually de-queued onto the next thread that becomes available. Starting with .NET Framework 4, this queue uses a lock-free algorithm that resembles the class. By using this lock-free implementation, the thread pool spends less time when it queues and de-queues work items. This performance benefit is available to all programs that use the thread pool. + +Top-level tasks, which are tasks that are not created in the context of another task, are put on the global queue just like any other work item. However, nested or child tasks, which are created in the context of another task, are handled quite differently. A child or nested task is put on a local queue that is specific to the thread on which the parent task is executing. The parent task may be a top-level task or it also may be the child of another task. When this thread is ready for more work, it first looks in the local queue. If work items are waiting there, they can be accessed quickly. The local queues are accessed in last-in, first-out order (LIFO) to preserve cache locality and reduce contention. For more information about child tasks and nested tasks, see [Attached and Detached Child Tasks](/dotnet/standard/parallel-programming/attached-and-detached-child-tasks). + +The use of local queues not only reduces pressure on the global queue, but also takes advantage of data locality. Work items in the local queue frequently reference data structures that are physically near one another in memory. In these cases, the data is already in the cache after the first task has run and can be accessed quickly. Both [Parallel LINQ (PLINQ)](/dotnet/standard/parallel-programming/parallel-linq-plinq) and the class use nested tasks and child tasks extensively, and achieve significant speedups by using the local work queues. + +### Work stealing + +Starting with .NET Framework 4, the thread pool also features a work-stealing algorithm to help make sure that no threads are sitting idle while others still have work in their queues. When a thread-pool thread is ready for more work, it first looks at the head of its local queue, then in the global queue, and then in the local queues of other threads. If it finds a work item in the local queue of another thread, it first applies heuristics to make sure that it can run the work efficiently. If it can, it de-queues the work item from the tail (in FIFO order). This reduces contention on each local queue and preserves data locality. This architecture helps the thread pool load-balance work more efficiently than past versions did. + +### Long-running tasks + +You may want to explicitly prevent a task from being put on a local queue. For example, you may know that a particular work item will run for a relatively long time and is likely to block all other work items on the local queue. In this case, you can specify the option, which provides a hint to the scheduler that an additional thread might be required for the task so that it does not block the forward progress of other threads or work items on the local queue. By using this option you avoid the thread pool completely, including the global and local queues. + +### Task inlining + +In some cases when a is waited on, it may be executed synchronously on the thread that is performing the wait operation. This enhances performance by preventing the need for an additional thread and instead using the existing thread, which would have blocked otherwise. To prevent errors due to reentrancy, task inlining only occurs when the wait target is found in the relevant thread's local queue. + +## Specify a synchronization context + +You can use the method to specify that a task should be scheduled to run on a particular thread. This is useful in frameworks such as Windows Forms and Windows Presentation Foundation where access to user interface objects is often restricted to code that is running on the same thread on which the UI object was created. + +The following example uses the method in a Windows Presentation Foundation (WPF) app to schedule a task on the same thread that the user interface (UI) control was created on. The example creates a mosaic of images that are randomly selected from a specified directory. The WPF objects are used to load and resize the images. The raw pixels are then passed to a task that uses a loop to write the pixel data into a large single-byte array. No synchronization is required because no two tiles occupy the same array elements. The tiles can also be written in any order because their position is calculated independently of any other tile. The large array is then passed to a task that runs on the UI thread, where the pixel data is loaded into an Image control. + +The example moves data off the UI thread, modifies it by using parallel loops and objects, and then passes it back to a task that runs on the UI thread. This approach is useful when you have to use the Task Parallel Library to perform operations that either are not supported by the WPF API, or are not sufficiently fast. Another way to create an image mosaic in WPF is to use a control and add images to it. The handles the work of positioning the tiles. However, this work can only be performed on the UI thread. + +:::code language="csharp" source="~/snippets/csharp/System.Threading.Tasks/TaskScheduler/FromCurrentSynchronizationContext/mainwindow.xaml.cs" id="Snippet01"::: + +To create the example, create a WPF application project in Visual Studio and name it WPF_CS1 (for a C# WPF project) or WPF_VB1 (for a Visual Basic WPF project). Then do the following: + +1. In design view, drag an control from the **Toolbox** onto the upper left corner of the design surface. In the **Name** textbox of the **Properties** window, name the control "image". + +2. Drag a control from the **Toolbox** to the lower left part of the application window. In XAML view, specify the property of the button as "Make a mosaic", and specify its property as "100". Connect the event with the `button_Click` event handler defined in the example's code by adding `Click="button_Click"` to the `