diff --git a/snippets/cpp/System/String/.ctor/sbyte_ctor1.cpp b/snippets/cpp/System/String/.ctor/sbyte_ctor1.cpp new file mode 100644 index 00000000000..f178c345ffc --- /dev/null +++ b/snippets/cpp/System/String/.ctor/sbyte_ctor1.cpp @@ -0,0 +1,20 @@ +// SByte_Ctor1.cpp : Defines the entry point for the console application. +// + +//#include "stdafx.h" + +// +using namespace System; + +void main() +{ + char chars[] = { 'a', 'b', 'c', 'd', '\x00' }; + + char* charPtr = chars; + String^ value = gcnew String(charPtr); + + Console::WriteLine(value); +} +// The example displays the following output: +// abcd +// diff --git a/snippets/csharp/System/Double/Overview/Program.cs b/snippets/csharp/System/Double/Overview/Program.cs new file mode 100644 index 00000000000..170e0a43274 --- /dev/null +++ b/snippets/csharp/System/Double/Overview/Program.cs @@ -0,0 +1 @@ +Example9.Run(); diff --git a/snippets/csharp/System/Double/Overview/Project.csproj b/snippets/csharp/System/Double/Overview/Project.csproj new file mode 100644 index 00000000000..274b5ecb6d6 --- /dev/null +++ b/snippets/csharp/System/Double/Overview/Project.csproj @@ -0,0 +1,8 @@ + + + + Exe + net10.0 + + + diff --git a/snippets/csharp/System/Double/Overview/precisionlist1.cs b/snippets/csharp/System/Double/Overview/precisionlist1.cs new file mode 100644 index 00000000000..ce19a1e9735 --- /dev/null +++ b/snippets/csharp/System/Double/Overview/precisionlist1.cs @@ -0,0 +1,17 @@ +// +using System; + +public class Example9 +{ + public static void Run() + { + double value1 = 1 / 3.0; + float sValue2 = 1 / 3.0f; + double value2 = (double)sValue2; + Console.WriteLine($"{value1:R} = {value2:R}: {value1.Equals(value2)}"); + } +} + +// The example displays the following output: +// 0.33333333333333331 = 0.3333333432674408: False +// diff --git a/snippets/csharp/System/Double/Overview/source.cs b/snippets/csharp/System/Double/Overview/source.cs index 709b8021499..fdaf6981acd 100644 --- a/snippets/csharp/System/Double/Overview/source.cs +++ b/snippets/csharp/System/Double/Overview/source.cs @@ -213,6 +213,7 @@ public double Celsius { } // } + namespace Snippets5 { // public class Temperature { @@ -257,6 +258,7 @@ public double Celsius { } // } + namespace Snippets6 { // public class Temperature { @@ -301,6 +303,7 @@ public double Celsius { } // } + namespace Snippets7 { // public class Temperature { @@ -345,6 +348,7 @@ public double Celsius { } // } + namespace Snippets8 { // public class Temperature { diff --git a/snippets/csharp/System/FormatException/Overview/FormatExample2.cs b/snippets/csharp/System/FormatException/Overview/FormatExample2.cs new file mode 100644 index 00000000000..925589ccda8 --- /dev/null +++ b/snippets/csharp/System/FormatException/Overview/FormatExample2.cs @@ -0,0 +1,77 @@ +// +using System; + +public class TestFormatter +{ + public static void Main() + { + int acctNumber = 79203159; + Console.WriteLine(String.Format(new CustomerFormatter(), "{0}", acctNumber)); + Console.WriteLine(String.Format(new CustomerFormatter(), "{0:G}", acctNumber)); + Console.WriteLine(String.Format(new CustomerFormatter(), "{0:S}", acctNumber)); + Console.WriteLine(String.Format(new CustomerFormatter(), "{0:P}", acctNumber)); + try { + Console.WriteLine(String.Format(new CustomerFormatter(), "{0:X}", acctNumber)); + } + catch (FormatException e) { + Console.WriteLine(e.Message); + } + } +} + +public class CustomerFormatter : IFormatProvider, ICustomFormatter +{ + public object GetFormat(Type formatType) + { + if (formatType == typeof(ICustomFormatter)) + return this; + else + return null; + } + + public string Format(string format, + object arg, + IFormatProvider formatProvider) + { + if (! this.Equals(formatProvider)) + { + return null; + } + else + { + if (String.IsNullOrEmpty(format)) + format = "G"; + + string customerString = arg.ToString(); + if (customerString.Length < 8) + customerString = customerString.PadLeft(8, '0'); + + format = format.ToUpper(); + switch (format) + { + case "G": + return customerString.Substring(0, 1) + "-" + + customerString.Substring(1, 5) + "-" + + customerString.Substring(6); + case "S": + return customerString.Substring(0, 1) + "/" + + customerString.Substring(1, 5) + "/" + + customerString.Substring(6); + case "P": + return customerString.Substring(0, 1) + "." + + customerString.Substring(1, 5) + "." + + customerString.Substring(6); + default: + throw new FormatException( + String.Format("The '{0}' format specifier is not supported.", format)); + } + } + } +} +// The example displays the following output: +// 7-92031-59 +// 7-92031-59 +// 7/92031/59 +// 7.92031.59 +// The 'X' format specifier is not supported. +// diff --git a/snippets/csharp/System/FormatException/Overview/Project.csproj b/snippets/csharp/System/FormatException/Overview/Project.csproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/csharp/System/FormatException/Overview/Project.csproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/csharp/System/FormatException/Overview/example2.cs b/snippets/csharp/System/FormatException/Overview/example2.cs index 7b0564b04e5..0902cb10939 100644 --- a/snippets/csharp/System/FormatException/Overview/example2.cs +++ b/snippets/csharp/System/FormatException/Overview/example2.cs @@ -1,7 +1,7 @@ // using System; -public class Example +public class FormatExample2 { public enum TemperatureScale { Celsius, Fahrenheit, Kelvin } diff --git a/snippets/csharp/System/FormatException/Overview/example3.cs b/snippets/csharp/System/FormatException/Overview/example3.cs index a1dff5db6ac..70238dcd314 100644 --- a/snippets/csharp/System/FormatException/Overview/example3.cs +++ b/snippets/csharp/System/FormatException/Overview/example3.cs @@ -1,6 +1,6 @@ using System; -public class Example +public class FormatExample3 { public static void Main() { diff --git a/snippets/csharp/System/FormatException/Overview/format4.cs b/snippets/csharp/System/FormatException/Overview/format4.cs index 38c367ec183..772c9b37849 100644 --- a/snippets/csharp/System/FormatException/Overview/format4.cs +++ b/snippets/csharp/System/FormatException/Overview/format4.cs @@ -1,8 +1,8 @@ using System; -public class Example +public class FormatExample4 { - public static void Main() + public static void Run() { // string formatString = " {0,10} ({0,8:X8})\n" + @@ -10,9 +10,10 @@ public static void Main() " = {2,10} ({2,8:X8})"; int value1 = 16932; int value2 = 15421; - string result = String.Format(formatString, + string result = string.Format(formatString, value1, value2, value1 & value2); Console.WriteLine(result); + // The example displays the following output: // 16932 (00004224) // And 15421 (00003C3D) diff --git a/snippets/csharp/System/FormatException/Overview/format5.cs b/snippets/csharp/System/FormatException/Overview/format5.cs index 62ec752edfb..4d4adce3647 100644 --- a/snippets/csharp/System/FormatException/Overview/format5.cs +++ b/snippets/csharp/System/FormatException/Overview/format5.cs @@ -1,6 +1,6 @@ using System; -public class Example +public class FormatExample5 { public static void Main() { diff --git a/snippets/csharp/System/FormatException/Overview/format7.cs b/snippets/csharp/System/FormatException/Overview/format7.cs index 42deffaa1d6..43b1c2139dd 100644 --- a/snippets/csharp/System/FormatException/Overview/format7.cs +++ b/snippets/csharp/System/FormatException/Overview/format7.cs @@ -1,6 +1,6 @@ using System; -public class Example +public class FormatExample7 { public static void Main() { diff --git a/snippets/csharp/System/FormatException/Overview/format_paramarray1.cs b/snippets/csharp/System/FormatException/Overview/format_paramarray1.cs index a1cd7e518ad..5dcf4ae3a45 100644 --- a/snippets/csharp/System/FormatException/Overview/format_paramarray1.cs +++ b/snippets/csharp/System/FormatException/Overview/format_paramarray1.cs @@ -17,7 +17,7 @@ public CityInfo(String name, int population, Decimal area, int year) public readonly int Year; } -public class Example +public class FormatExample10 { public static void Main() { @@ -38,4 +38,4 @@ private static void ShowPopulationData(CityInfo city) // The example displays the following output: // New York in 2010: Population 8,175,133, Area 302.6 sq. feet // Seattle in 2010: Population 608,660, Area 83.9 sq. feet -// \ No newline at end of file +// diff --git a/snippets/csharp/System/FormatException/Overview/formatexample4.cs b/snippets/csharp/System/FormatException/Overview/formatexample4.cs index 8bec656f71d..6da03ced2be 100644 --- a/snippets/csharp/System/FormatException/Overview/formatexample4.cs +++ b/snippets/csharp/System/FormatException/Overview/formatexample4.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -public class Example +public class FormatExample6 { public static void Main() { diff --git a/snippets/csharp/System/FormatException/Overview/formatoverload1.cs b/snippets/csharp/System/FormatException/Overview/formatoverload1.cs new file mode 100644 index 00000000000..067922e00d7 --- /dev/null +++ b/snippets/csharp/System/FormatException/Overview/formatoverload1.cs @@ -0,0 +1,18 @@ +using System; + +public class Example2 +{ + public static void Main() + { + // + DateTime dat = new DateTime(2012, 1, 17, 9, 30, 0); + string city = "Chicago"; + int temp = -16; + string output = String.Format("At {0} in {1}, the temperature was {2} degrees.", + dat, city, temp); + Console.WriteLine(output); + // The example displays output like the following: + // At 1/17/2012 9:30:00 AM in Chicago, the temperature was -16 degrees. + // + } +} diff --git a/snippets/csharp/System/FormatException/Overview/formatoverload2.cs b/snippets/csharp/System/FormatException/Overview/formatoverload2.cs new file mode 100644 index 00000000000..9e9e5396bd6 --- /dev/null +++ b/snippets/csharp/System/FormatException/Overview/formatoverload2.cs @@ -0,0 +1,38 @@ +using System; + +public class Example3 +{ + public static void Main() + { + // + // Create array of 5-tuples with population data for three U.S. cities, 1940-1950. + Tuple[] cities = + { Tuple.Create("Los Angeles", new DateTime(1940, 1, 1), 1504277, + new DateTime(1950, 1, 1), 1970358), + Tuple.Create("New York", new DateTime(1940, 1, 1), 7454995, + new DateTime(1950, 1, 1), 7891957), + Tuple.Create("Chicago", new DateTime(1940, 1, 1), 3396808, + new DateTime(1950, 1, 1), 3620962), + Tuple.Create("Detroit", new DateTime(1940, 1, 1), 1623452, + new DateTime(1950, 1, 1), 1849568) }; + + // Display header + var header = String.Format("{0,-12}{1,8}{2,12}{1,8}{2,12}{3,14}\n", + "City", "Year", "Population", "Change (%)"); + Console.WriteLine(header); + foreach (var city in cities) { + var output = String.Format("{0,-12}{1,8:yyyy}{2,12:N0}{3,8:yyyy}{4,12:N0}{5,14:P1}", + city.Item1, city.Item2, city.Item3, city.Item4, city.Item5, + (city.Item5 - city.Item3)/ (double)city.Item3); + Console.WriteLine(output); + } + // The example displays the following output: + // City Year Population Year Population Change (%) + // + // Los Angeles 1940 1,504,277 1950 1,970,358 31.0 % + // New York 1940 7,454,995 1950 7,891,957 5.9 % + // Chicago 1940 3,396,808 1950 3,620,962 6.6 % + // Detroit 1940 1,623,452 1950 1,849,568 13.9 % + // + } +} diff --git a/snippets/csharp/System/FormatException/Overview/formatsyntax1.cs b/snippets/csharp/System/FormatException/Overview/formatsyntax1.cs new file mode 100644 index 00000000000..c11ce9190e7 --- /dev/null +++ b/snippets/csharp/System/FormatException/Overview/formatsyntax1.cs @@ -0,0 +1,12 @@ +using System; + +public class Example4 +{ + public static void Main() + { + // + var value = String.Format("{0,-10:C}", 126347.89m); + Console.WriteLine(value); + // + } +} diff --git a/snippets/csharp/System/FormatException/Overview/iformattable1.cs b/snippets/csharp/System/FormatException/Overview/iformattable1.cs index 38e4261b622..7161e9fd8dd 100644 --- a/snippets/csharp/System/FormatException/Overview/iformattable1.cs +++ b/snippets/csharp/System/FormatException/Overview/iformattable1.cs @@ -1,7 +1,7 @@ // using System; -public class Example +public class FormatExample8 { public static void Main() { diff --git a/snippets/csharp/System/FormatException/Overview/iformattable2.cs b/snippets/csharp/System/FormatException/Overview/iformattable2.cs index d6af7025d27..00c29b7425a 100644 --- a/snippets/csharp/System/FormatException/Overview/iformattable2.cs +++ b/snippets/csharp/System/FormatException/Overview/iformattable2.cs @@ -1,7 +1,7 @@ // using System; -public class Example +public class FormatExample9 { public static void Main() { diff --git a/snippets/csharp/System/FormatException/Overview/iformattable3.cs b/snippets/csharp/System/FormatException/Overview/iformattable3.cs index 9849d5ca31b..9c1eedabbba 100644 --- a/snippets/csharp/System/FormatException/Overview/iformattable3.cs +++ b/snippets/csharp/System/FormatException/Overview/iformattable3.cs @@ -1,7 +1,7 @@ // using System; -public class Example +public class IFormattableExample3 { public static void Main() { @@ -9,6 +9,7 @@ public static void Main() Console.WriteLine(Guid.ParseExact(guidString, "G")); } } + // The example displays the following output: // Unhandled Exception: System.FormatException: // Format String can be only "D", "d", "N", "n", "P", "p", "B", "b", "X" or "x". diff --git a/snippets/csharp/System/FormatException/Overview/iformattable4.cs b/snippets/csharp/System/FormatException/Overview/iformattable4.cs index eb980650b48..9169bb84335 100644 --- a/snippets/csharp/System/FormatException/Overview/iformattable4.cs +++ b/snippets/csharp/System/FormatException/Overview/iformattable4.cs @@ -1,7 +1,7 @@ // using System; -public class Example +public class FormatExample11 { public static void Main() { diff --git a/snippets/csharp/System/FormatException/Overview/interceptor2.cs b/snippets/csharp/System/FormatException/Overview/interceptor2.cs new file mode 100644 index 00000000000..010a3529f85 --- /dev/null +++ b/snippets/csharp/System/FormatException/Overview/interceptor2.cs @@ -0,0 +1,119 @@ +// +using System; +using System.Globalization; + +public class InterceptProvider : IFormatProvider, ICustomFormatter +{ + public object GetFormat(Type formatType) + { + if (formatType == typeof(ICustomFormatter)) + return this; + else + return null; + } + + public string Format(String format, Object obj, IFormatProvider provider) + { + // Display information about method call. + string formatString = format ?? ""; + Console.WriteLine("Provider: {0}, Object: {1}, Format String: {2}", + provider.GetType().Name, obj ?? "", formatString); + + if (obj == null) return String.Empty; + + // If this is a byte and the "R" format string, format it with Roman numerals. + if (obj is Byte && formatString.ToUpper().Equals("R")) { + Byte value = (Byte) obj; + int remainder; + int result; + String returnString = String.Empty; + + // Get the hundreds digit(s) + result = Math.DivRem(value, 100, out remainder); + if (result > 0) + returnString = new String('C', result); + value = (Byte) remainder; + // Get the 50s digit + result = Math.DivRem(value, 50, out remainder); + if (result == 1) + returnString += "L"; + value = (Byte) remainder; + // Get the tens digit. + result = Math.DivRem(value, 10, out remainder); + if (result > 0) + returnString += new String('X', result); + value = (Byte) remainder; + // Get the fives digit. + result = Math.DivRem(value, 5, out remainder); + if (result > 0) + returnString += "V"; + value = (Byte) remainder; + // Add the ones digit. + if (remainder > 0) + returnString += new String('I', remainder); + + // Check whether we have too many X characters. + int pos = returnString.IndexOf("XXXX"); + if (pos >= 0) { + int xPos = returnString.IndexOf("L"); + if (xPos >= 0 & xPos == pos - 1) + returnString = returnString.Replace("LXXXX", "XC"); + else + returnString = returnString.Replace("XXXX", "XL"); + } + // Check whether we have too many I characters + pos = returnString.IndexOf("IIII"); + if (pos >= 0) + if (returnString.IndexOf("V") >= 0) + returnString = returnString.Replace("VIIII", "IX"); + else + returnString = returnString.Replace("IIII", "IV"); + + return returnString; + } + + // Use default for all other formatting. + if (obj is IFormattable) + return ((IFormattable) obj).ToString(format, CultureInfo.CurrentCulture); + else + return obj.ToString(); + } +} + +public class FormatExample12 +{ + public static void Main() + { + int n = 10; + double value = 16.935; + DateTime day = DateTime.Now; + InterceptProvider provider = new InterceptProvider(); + Console.WriteLine(String.Format(provider, "{0:N0}: {1:C2} on {2:d}\n", n, value, day)); + Console.WriteLine(String.Format(provider, "{0}: {1:F}\n", "Today: ", + (DayOfWeek) DateTime.Now.DayOfWeek)); + Console.WriteLine(String.Format(provider, "{0:X}, {1}, {2}\n", + (Byte) 2, (Byte) 12, (Byte) 199)); + Console.WriteLine(String.Format(provider, "{0:R}, {1:R}, {2:R}\n", + (Byte) 2, (Byte) 12, (Byte) 199)); + } +} +// The example displays the following output: +// Provider: InterceptProvider, Object: 10, Format String: N0 +// Provider: InterceptProvider, Object: 16.935, Format String: C2 +// Provider: InterceptProvider, Object: 1/31/2013 6:10:28 PM, Format String: d +// 10: $16.94 on 1/31/2013 +// +// Provider: InterceptProvider, Object: Today: , Format String: +// Provider: InterceptProvider, Object: Thursday, Format String: F +// Today: : Thursday +// +// Provider: InterceptProvider, Object: 2, Format String: X +// Provider: InterceptProvider, Object: 12, Format String: +// Provider: InterceptProvider, Object: 199, Format String: +// 2, 12, 199 +// +// Provider: InterceptProvider, Object: 2, Format String: R +// Provider: InterceptProvider, Object: 12, Format String: R +// Provider: InterceptProvider, Object: 199, Format String: R +// II, XII, CXCIX +// diff --git a/snippets/csharp/System/FormatException/Overview/qa-interpolated1.cs b/snippets/csharp/System/FormatException/Overview/qa-interpolated1.cs new file mode 100644 index 00000000000..faf264947e3 --- /dev/null +++ b/snippets/csharp/System/FormatException/Overview/qa-interpolated1.cs @@ -0,0 +1,23 @@ +using System; + +public class Example12 +{ + public static void Main() + { + // + string[] names = { "Balto", "Vanya", "Dakota", "Samuel", "Koani", "Yiska", "Yuma" }; + string output = names[0] + ", " + names[1] + ", " + names[2] + ", " + + names[3] + ", " + names[4] + ", " + names[5] + ", " + + names[6]; + + output += "\n"; + var date = DateTime.Now; + output += String.Format("It is {0:t} on {0:d}. The day of the week is {1}.", + date, date.DayOfWeek); + Console.WriteLine(output); + // The example displays the following output: + // Balto, Vanya, Dakota, Samuel, Koani, Yiska, Yuma + // It is 10:29 AM on 1/8/2018. The day of the week is Monday. + // + } +} diff --git a/snippets/csharp/System/FormatException/Overview/qa-interpolated2.cs b/snippets/csharp/System/FormatException/Overview/qa-interpolated2.cs new file mode 100644 index 00000000000..d69dc65af5a --- /dev/null +++ b/snippets/csharp/System/FormatException/Overview/qa-interpolated2.cs @@ -0,0 +1,20 @@ +using System; + +public class Example13 +{ + public static void Main() + { + // + string[] names = { "Balto", "Vanya", "Dakota", "Samuel", "Koani", "Yiska", "Yuma" }; + string output = $"{names[0]}, {names[1]}, {names[2]}, {names[3]}, {names[4]}, " + + $"{names[5]}, {names[6]}"; + + var date = DateTime.Now; + output += $"\nIt is {date:t} on {date:d}. The day of the week is {date.DayOfWeek}."; + Console.WriteLine(output); + // The example displays the following output: + // Balto, Vanya, Dakota, Samuel, Koani, Yiska, Yuma + // It is 10:29 AM on 1/8/2018. The day of the week is Monday. + // + } +} diff --git a/snippets/csharp/System/FormatException/Overview/qa1.cs b/snippets/csharp/System/FormatException/Overview/qa1.cs index a4c2827110d..ff8496d8bef 100644 --- a/snippets/csharp/System/FormatException/Overview/qa1.cs +++ b/snippets/csharp/System/FormatException/Overview/qa1.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; -public class Example +public class QAExample1 { public static void Main() { diff --git a/snippets/csharp/System/FormatException/Overview/qa11.cs b/snippets/csharp/System/FormatException/Overview/qa11.cs new file mode 100644 index 00000000000..00e98be5982 --- /dev/null +++ b/snippets/csharp/System/FormatException/Overview/qa11.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; + +public class Example5 +{ + public static void Main() + { + // + Random rnd = new Random(); + int[] numbers = new int[4]; + int total = 0; + for (int ctr = 0; ctr <= 2; ctr++) + { + int number = rnd.Next(1001); + numbers[ctr] = number; + total += number; + } + numbers[3] = total; + Console.WriteLine($"{numbers} + {1} + {2} = {3}"); + // + } +} diff --git a/snippets/csharp/System/FormatException/Overview/qa2.cs b/snippets/csharp/System/FormatException/Overview/qa2.cs index 2c7da859059..9794045a467 100644 --- a/snippets/csharp/System/FormatException/Overview/qa2.cs +++ b/snippets/csharp/System/FormatException/Overview/qa2.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; -public class Example +public class QAExample2 { public static void Main() { diff --git a/snippets/csharp/System/FormatException/Overview/qa21.cs b/snippets/csharp/System/FormatException/Overview/qa21.cs new file mode 100644 index 00000000000..067bd5fdd03 --- /dev/null +++ b/snippets/csharp/System/FormatException/Overview/qa21.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; + +public class Example6 +{ + public static void Main() + { + // + Random rnd = new Random(); + int[] numbers = new int[4]; + int total = 0; + for (int ctr = 0; ctr <= 2; ctr++) + { + int number = rnd.Next(1001); + numbers[ctr] = number; + total += number; + } + numbers[3] = total; + object[] values = new object[numbers.Length]; + numbers.CopyTo(values, 0); + Console.WriteLine($"{values} + {1} + {2} = {3}"); + // + } +} diff --git a/snippets/csharp/System/FormatException/Overview/qa26.cs b/snippets/csharp/System/FormatException/Overview/qa26.cs new file mode 100644 index 00000000000..372f1370470 --- /dev/null +++ b/snippets/csharp/System/FormatException/Overview/qa26.cs @@ -0,0 +1,24 @@ +using System; + +public class Example7 +{ + public static void Main() + { + // + object[] values = { 1603, 1794.68235, 15436.14 }; + string result; + foreach (var value in values) + { + result = String.Format("{0,12:C2} {0,12:E3} {0,12:F4} {0,12:N3} {1,12:P2}\n", + Convert.ToDouble(value), Convert.ToDouble(value) / 10000); + Console.WriteLine(result); + } + // The example displays output like the following: + // $1,603.00 1.603E+003 1603.0000 1,603.000 16.03 % + // + // $1,794.68 1.795E+003 1794.6824 1,794.682 17.95 % + // + // $15,436.14 1.544E+004 15436.1400 15,436.140 154.36 % + // + } +} diff --git a/snippets/csharp/System/FormatException/Overview/qa27.cs b/snippets/csharp/System/FormatException/Overview/qa27.cs new file mode 100644 index 00000000000..403a9da46af --- /dev/null +++ b/snippets/csharp/System/FormatException/Overview/qa27.cs @@ -0,0 +1,16 @@ +using System; + +public class Example8 +{ + public static void Main() + { + // + decimal value = 16309.5436m; + string result = String.Format("{0,12:#.00000} {0,12:0,000.00} {0,12:000.00#}", + value); + Console.WriteLine(result); + // The example displays the following output: + // 16309.54360 16,309.54 16309.544 + // + } +} diff --git a/snippets/csharp/System/FormatException/Overview/qa28.cs b/snippets/csharp/System/FormatException/Overview/qa28.cs new file mode 100644 index 00000000000..acd3e998104 --- /dev/null +++ b/snippets/csharp/System/FormatException/Overview/qa28.cs @@ -0,0 +1,16 @@ +using System; + +public class Example9 +{ + public static void Main() + { + // + int value = 16342; + string result = String.Format("{0,18:00000000} {0,18:00000000.000} {0,18:000,0000,000.0}", + value); + Console.WriteLine(result); + // The example displays the following output: + // 00016342 00016342.000 0,000,016,342.0 + // + } +} diff --git a/snippets/csharp/System/FormatException/Overview/qa29.cs b/snippets/csharp/System/FormatException/Overview/qa29.cs new file mode 100644 index 00000000000..33faef50db8 --- /dev/null +++ b/snippets/csharp/System/FormatException/Overview/qa29.cs @@ -0,0 +1,15 @@ +using System; + +public class Example10 +{ + public static void Main() + { + // + int value = 1326; + string result = String.Format("{0,10:D6} {0,10:X8}", value); + Console.WriteLine(result); + // The example displays the following output: + // 001326 0000052E + // + } +} diff --git a/snippets/csharp/System/FormatException/Overview/qa3.cs b/snippets/csharp/System/FormatException/Overview/qa3.cs index 4a82da781dc..a599a1e270f 100644 --- a/snippets/csharp/System/FormatException/Overview/qa3.cs +++ b/snippets/csharp/System/FormatException/Overview/qa3.cs @@ -1,6 +1,6 @@ using System; -public class Example +public class FormatExample13 { public static void Main() { diff --git a/snippets/csharp/System/FormatException/Overview/starting1.cs b/snippets/csharp/System/FormatException/Overview/starting1.cs new file mode 100644 index 00000000000..3e444869dc2 --- /dev/null +++ b/snippets/csharp/System/FormatException/Overview/starting1.cs @@ -0,0 +1,57 @@ +using System; +using System.Text; + +public class Example14 +{ + public static void Main() + { + // + decimal temp = 20.4m; + string s = String.Format("The temperature is {0}°C.", temp); + Console.WriteLine(s); + // Displays 'The temperature is 20.4°C.' + // + + Snippet31(); + Snippet32(); + Snippet34(); + } + + private static void Snippet31() + { + // + string s = String.Format("At {0}, the temperature is {1}°C.", + DateTime.Now, 20.4); + Console.WriteLine(s); + // Output similar to: 'At 4/10/2015 9:29:41 AM, the temperature is 20.4°C.' + // + } + + private static void Snippet32() + { + // + string s = String.Format("It is now {0:d} at {0:t}", DateTime.Now); + Console.WriteLine(s); + // Output similar to: 'It is now 4/10/2015 at 10:04 AM' + // + } + + private static void Snippet34() + { + // + int[] years = { 2013, 2014, 2015 }; + int[] population = { 1025632, 1105967, 1148203 }; + String s = String.Format("{0,-10} {1,-10}\n\n", "Year", "Population"); + for (int index = 0; index < years.Length; index++) + s += String.Format("{0,-10} {1,-10:N0}\n", + years[index], population[index]); + Console.WriteLine($"\n{s}"); + // Result: + // Year Population + // + // 2013 1,025,632 + // 2014 1,105,967 + // 2015 1,148,203 + // + } +} diff --git a/snippets/csharp/System/FormatException/Overview/starting2.cs b/snippets/csharp/System/FormatException/Overview/starting2.cs new file mode 100644 index 00000000000..1bfa720b14d --- /dev/null +++ b/snippets/csharp/System/FormatException/Overview/starting2.cs @@ -0,0 +1,28 @@ +using System; + +public class Example15 +{ + public static void Main() + { + // + Decimal pricePerOunce = 17.36m; + String s = String.Format("The current price is {0} per ounce.", + pricePerOunce); + Console.WriteLine(s); + // Result: The current price is 17.36 per ounce. + // + ShowFormatted(); + } + + private static void ShowFormatted() + { + // + Decimal pricePerOunce = 17.36m; + String s = String.Format("The current price is {0:C2} per ounce.", + pricePerOunce); + Console.WriteLine(s); + // Result if current culture is en-US: + // The current price is $17.36 per ounce. + // + } +} diff --git a/snippets/csharp/System/FormatException/Overview/starting3.cs b/snippets/csharp/System/FormatException/Overview/starting3.cs new file mode 100644 index 00000000000..48ef9b7f0b0 --- /dev/null +++ b/snippets/csharp/System/FormatException/Overview/starting3.cs @@ -0,0 +1,26 @@ +using System; +using System.Text; + +class Example16 +{ + public static void Main() + { + // + int[] years = { 2013, 2014, 2015 }; + int[] population = { 1025632, 1105967, 1148203 }; + var sb = new System.Text.StringBuilder(); + sb.Append(String.Format("{0,6} {1,15}\n\n", "Year", "Population")); + for (int index = 0; index < years.Length; index++) + sb.Append(String.Format("{0,6} {1,15:N0}\n", years[index], population[index])); + + Console.WriteLine(sb); + + // Result: + // Year Population + // + // 2013 1,025,632 + // 2014 1,105,967 + // 2015 1,148,203 + // + } +} diff --git a/snippets/csharp/System/Single/CompareTo/Project.csproj b/snippets/csharp/System/Single/CompareTo/Project.csproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/csharp/System/Single/CompareTo/Project.csproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/csharp/System/Single/CompareTo/compareto2.cs b/snippets/csharp/System/Single/CompareTo/compareto2.cs new file mode 100644 index 00000000000..cdd6191ed77 --- /dev/null +++ b/snippets/csharp/System/Single/CompareTo/compareto2.cs @@ -0,0 +1,20 @@ +// +using System; + +public class Example2 +{ + public static void Main() + { + float value1 = 16.5457f; + float operand = 3.8899982f; + float value2 = value1 * operand / operand; + Console.WriteLine($"Comparing {value1} and {value2}: {value1.CompareTo(value2)}"); + Console.WriteLine(); + Console.WriteLine($"Comparing {value1:R} and {value2:R}: {value1.CompareTo(value2)}"); + } +} +// The example displays the following output: +// Comparing 16.5457 and 16.5457: -1 +// +// Comparing 16.5457 and 16.545702: -1 +// diff --git a/snippets/csharp/System/Single/CompareTo/compareto3.cs b/snippets/csharp/System/Single/CompareTo/compareto3.cs new file mode 100644 index 00000000000..4d5b9b389fc --- /dev/null +++ b/snippets/csharp/System/Single/CompareTo/compareto3.cs @@ -0,0 +1,20 @@ +// +using System; + +public class Example +{ + public static void Main() + { + float value1 = 16.5457f; + float operand = 3.8899982f; + object value2 = value1 * operand / operand; + Console.WriteLine($"Comparing {value1} and {value2}: {value1.CompareTo(value2)}"); + Console.WriteLine(); + Console.WriteLine($"Comparing {value1:R} and {value2:R}: {value1.CompareTo(value2)}"); + } +} +// The example displays the following output: +// Comparing 16.5457 and 16.5457: -1 +// +// Comparing 16.5457 and 16.545702: -1 +// diff --git a/snippets/csharp/System/Single/Epsilon/Project.csproj b/snippets/csharp/System/Single/Epsilon/Project.csproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/csharp/System/Single/Epsilon/Project.csproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/csharp/System/Single/Epsilon/epsilon.cs b/snippets/csharp/System/Single/Epsilon/epsilon.cs new file mode 100644 index 00000000000..2bf16f5c802 --- /dev/null +++ b/snippets/csharp/System/Single/Epsilon/epsilon.cs @@ -0,0 +1,25 @@ +// +using System; + +public class Example1 +{ + public static void Main() + { + float[] values = { 0f, Single.Epsilon, Single.Epsilon * .5f }; + + for (int ctr = 0; ctr <= values.Length - 2; ctr++) + { + for (int ctr2 = ctr + 1; ctr2 <= values.Length - 1; ctr2++) + { + Console.WriteLine($"{values[ctr]:r} = {values[ctr2]:r}: {values[ctr].Equals(values[ctr2])}"); + } + Console.WriteLine(); + } + } +} +// The example displays the following output: +// 0 = 1.401298E-45: False +// 0 = 0: True +// +// 1.401298E-45 = 0: False +// diff --git a/snippets/csharp/System/Single/Epsilon/epsilon1.cs b/snippets/csharp/System/Single/Epsilon/epsilon1.cs new file mode 100644 index 00000000000..87664989eac --- /dev/null +++ b/snippets/csharp/System/Single/Epsilon/epsilon1.cs @@ -0,0 +1,50 @@ +// +using System; + +public class Example2 +{ + public static void Main() + { + float[] values = { 0.0f, Single.Epsilon }; + foreach (var value in values) { + Console.WriteLine(GetComponentParts(value)); + Console.WriteLine(); + } + } + + private static string GetComponentParts(float value) + { + string result = String.Format("{0:R}: ", value); + int indent = result.Length; + + // Convert the single to a 4-byte array. + byte[] bytes = BitConverter.GetBytes(value); + int formattedSingle = BitConverter.ToInt32(bytes, 0); + + // Get the sign bit (byte 3, bit 7). + result += String.Format("Sign: {0}\n", + (formattedSingle >> 31) != 0 ? "1 (-)" : "0 (+)"); + + // Get the exponent (byte 2 bit 7 to byte 3, bits 6) + int exponent = (formattedSingle >> 23) & 0x000000FF; + int adjustment = (exponent != 0) ? 127 : 126; + result += String.Format("{0}Exponent: 0x{1:X4} ({1})\n", new String(' ', indent), exponent - adjustment); + + // Get the significand (bits 0-22) + long significand = exponent != 0 ? + ((formattedSingle & 0x007FFFFF) | 0x800000) : + (formattedSingle & 0x007FFFFF); + result += String.Format("{0}Mantissa: 0x{1:X13}\n", new String(' ', indent), significand); + return result; + } +} +// // The example displays the following output: +// 0: Sign: 0 (+) +// Exponent: 0xFFFFFF82 (-126) +// Mantissa: 0x0000000000000 +// +// +// 1.401298E-45: Sign: 0 (+) +// Exponent: 0xFFFFFF82 (-126) +// Mantissa: 0x0000000000001 +// diff --git a/snippets/csharp/System/Single/Equals/Project.csproj b/snippets/csharp/System/Single/Equals/Project.csproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/csharp/System/Single/Equals/Project.csproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/csharp/System/Single/Equals/equalsabs1.cs b/snippets/csharp/System/Single/Equals/equalsabs1.cs new file mode 100644 index 00000000000..6aa1d68c28e --- /dev/null +++ b/snippets/csharp/System/Single/Equals/equalsabs1.cs @@ -0,0 +1,43 @@ +// +using System; + +public class Example +{ + public static void Main() + { + float value1 = .1f * 10f; + float value2 = 0f; + for (int ctr = 0; ctr < 10; ctr++) + value2 += .1f; + + Console.WriteLine($"{value1:R} = {value2:R}: {HasMinimalDifference(value1, value2, 1)}"); + } + + public static bool HasMinimalDifference(float value1, float value2, int units) + { + byte[] bytes = BitConverter.GetBytes(value1); + int iValue1 = BitConverter.ToInt32(bytes, 0); + + bytes = BitConverter.GetBytes(value2); + int iValue2 = BitConverter.ToInt32(bytes, 0); + + // If the signs are different, return false except for +0 and -0. + if ((iValue1 >> 31) != (iValue2 >> 31)) + { + if (value1 == value2) + return true; + + return false; + } + + int diff = Math.Abs(iValue1 - iValue2); + + if (diff <= units) + return true; + + return false; + } +} +// The example displays the following output: +// 1 = 1.00000012: True +// \ No newline at end of file diff --git a/snippets/csharp/System/Single/Equals/equalsoverl.cs b/snippets/csharp/System/Single/Equals/equalsoverl.cs index 6b466ab062e..33dd94b5851 100644 --- a/snippets/csharp/System/Single/Equals/equalsoverl.cs +++ b/snippets/csharp/System/Single/Equals/equalsoverl.cs @@ -1,10 +1,10 @@ // using System; -public class Example +public class Example2 { static float value = 112; - + public static void Main() { byte byte1= 112; @@ -22,7 +22,7 @@ public static void Main() long long1 = 112; Console.WriteLine("value = long1: {0,17}", value.Equals(long1)); TestObjectForEquality(long1); - + sbyte sbyte1 = 112; Console.WriteLine("value = sbyte1: {0,16}", value.Equals(sbyte1)); TestObjectForEquality(sbyte1); @@ -38,7 +38,7 @@ public static void Main() ulong ulong1 = 112; Console.WriteLine("value = ulong1: {0,17}", value.Equals(ulong1)); TestObjectForEquality(ulong1); - + decimal dec1 = 112m; Console.WriteLine("value = dec1: {0,21}", value.Equals(dec1)); TestObjectForEquality(dec1); diff --git a/snippets/csharp/System/Single/Overview/Project.csproj b/snippets/csharp/System/Single/Overview/Project.csproj new file mode 100644 index 00000000000..258b56c95b9 --- /dev/null +++ b/snippets/csharp/System/Single/Overview/Project.csproj @@ -0,0 +1,9 @@ + + + + Exe + net10.0 + Example1 + + + diff --git a/snippets/csharp/System/Single/Overview/comparison1.cs b/snippets/csharp/System/Single/Overview/comparison1.cs new file mode 100644 index 00000000000..965c922e4f9 --- /dev/null +++ b/snippets/csharp/System/Single/Overview/comparison1.cs @@ -0,0 +1,15 @@ +// +using System; + +public class Example +{ + public static void Main() + { + float value1 = .3333333f; + float value2 = 1.0f/3; + Console.WriteLine($"{value1:R} = {value2:R}: {value1.Equals(value2)}"); + } +} +// The example displays the following output: +// 0.3333333 = 0.333333343: False +// diff --git a/snippets/csharp/System/Single/Overview/comparison2.cs b/snippets/csharp/System/Single/Overview/comparison2.cs new file mode 100644 index 00000000000..3282246945f --- /dev/null +++ b/snippets/csharp/System/Single/Overview/comparison2.cs @@ -0,0 +1,20 @@ +using System; + +public class Example1 +{ + public static void Main() + { + // + float value1 = 10.201438f; + value1 = (float)Math.Sqrt((float)Math.Pow(value1, 2)); + float value2 = (float)Math.Pow((float)value1 * 3.51f, 2); + value2 = ((float)Math.Sqrt(value2)) / 3.51f; + Console.WriteLine($"{value1} = {value2}: {value1.Equals(value2)}"); + + // The example displays the following output on .NET: + // 10.201438 = 10.201439: False + // The example displays the following output on .NET Framework: + // 10.20144 = 10.20144: False + // + } +} diff --git a/snippets/csharp/System/Single/Overview/comparison3.cs b/snippets/csharp/System/Single/Overview/comparison3.cs new file mode 100644 index 00000000000..4f82ff0c2ea --- /dev/null +++ b/snippets/csharp/System/Single/Overview/comparison3.cs @@ -0,0 +1,19 @@ +using System; + +public class Example2 +{ + public static void Main() + { + // + float value1 = .3333333f; + float value2 = 1.0f / 3; + int precision = 7; + value1 = (float)Math.Round(value1, precision); + value2 = (float)Math.Round(value2, precision); + Console.WriteLine($"{value1:R} = {value2:R}: {value1.Equals(value2)}"); + + // The example displays the following output: + // 0.3333333 = 0.3333333: True + // + } +} diff --git a/snippets/csharp/System/Single/Overview/comparison4.cs b/snippets/csharp/System/Single/Overview/comparison4.cs new file mode 100644 index 00000000000..ded666dc514 --- /dev/null +++ b/snippets/csharp/System/Single/Overview/comparison4.cs @@ -0,0 +1,51 @@ +using System; + +public class Example3 +{ + // + public static void Main() + { + float one1 = .1f * 10; + float one2 = 0f; + for (int ctr = 1; ctr <= 10; ctr++) + one2 += .1f; + + Console.WriteLine($"{one1:R} = {one2:R}: {one1.Equals(one2)}"); + Console.WriteLine($"{one1:R} is approximately equal to {one2:R}: " + + $"{IsApproximatelyEqual(one1, one2, .000001f)}"); + + float negativeOne1 = -1 * one1; + float negativeOne2 = -1 * one2; + + Console.WriteLine($"{negativeOne1:R} = {negativeOne2:R}: {negativeOne1.Equals(negativeOne2)}"); + Console.WriteLine($"{negativeOne1:R} is approximately equal to {negativeOne2:R}: " + + $"{IsApproximatelyEqual(negativeOne1, negativeOne2, .000001f)}"); + } + + static bool IsApproximatelyEqual(float value1, float value2, float epsilon) + { + // If they are equal anyway, just return True. + if (value1.Equals(value2)) + return true; + + // Handle NaN, Infinity. + if (Double.IsInfinity(value1) | Double.IsNaN(value1)) + return value1.Equals(value2); + else if (Double.IsInfinity(value2) | Double.IsNaN(value2)) + return value1.Equals(value2); + + // Handle zero to avoid division by zero. + double divisor = Math.Max(value1, value2); + if (divisor.Equals(0)) + divisor = Math.Min(value1, value2); + + return Math.Abs((value1 - value2) / divisor) <= epsilon; + } + + // The example displays the following output on .NET: + // 1 = 1.0000001: False + // 1 is approximately equal to 1.0000001: True + // -1 = -1.0000001: False + // -1 is approximately equal to -1.0000001: True + // +} diff --git a/snippets/csharp/System/Single/Overview/convert1.cs b/snippets/csharp/System/Single/Overview/convert1.cs new file mode 100644 index 00000000000..8a5e0e75a97 --- /dev/null +++ b/snippets/csharp/System/Single/Overview/convert1.cs @@ -0,0 +1,48 @@ +// +using System; + +public class Example4 +{ + public static void Main() + { + dynamic[] values = { Byte.MinValue, Byte.MaxValue, Decimal.MinValue, + Decimal.MaxValue, Double.MinValue, Double.MaxValue, + Int16.MinValue, Int16.MaxValue, Int32.MinValue, + Int32.MaxValue, Int64.MinValue, Int64.MaxValue, + SByte.MinValue, SByte.MaxValue, UInt16.MinValue, + UInt16.MaxValue, UInt32.MinValue, UInt32.MaxValue, + UInt64.MinValue, UInt64.MaxValue }; + float sngValue; + foreach (var value in values) + { + if (value.GetType() == typeof(Decimal) || + value.GetType() == typeof(Double)) + sngValue = (float)value; + else + sngValue = value; + Console.WriteLine($"{value} ({value.GetType().Name}) --> {sngValue:R} ({sngValue.GetType().Name})"); + } + } +} +// The example displays the following output: +// 0 (Byte) --> 0 (Single) +// 255 (Byte) --> 255 (Single) +// -79228162514264337593543950335 (Decimal) --> -7.92281625E+28 (Single) +// 79228162514264337593543950335 (Decimal) --> 7.92281625E+28 (Single) +// -1.79769313486232E+308 (Double) --> -Infinity (Single) +// 1.79769313486232E+308 (Double) --> Infinity (Single) +// -32768 (Int16) --> -32768 (Single) +// 32767 (Int16) --> 32767 (Single) +// -2147483648 (Int32) --> -2.14748365E+09 (Single) +// 2147483647 (Int32) --> 2.14748365E+09 (Single) +// -9223372036854775808 (Int64) --> -9.223372E+18 (Single) +// 9223372036854775807 (Int64) --> 9.223372E+18 (Single) +// -128 (SByte) --> -128 (Single) +// 127 (SByte) --> 127 (Single) +// 0 (UInt16) --> 0 (Single) +// 65535 (UInt16) --> 65535 (Single) +// 0 (UInt32) --> 0 (Single) +// 4294967295 (UInt32) --> 4.2949673E+09 (Single) +// 0 (UInt64) --> 0 (Single) +// 18446744073709551615 (UInt64) --> 1.84467441E+19 (Single) +// diff --git a/snippets/csharp/System/Single/Overview/convert2.cs b/snippets/csharp/System/Single/Overview/convert2.cs new file mode 100644 index 00000000000..d9a17fb336c --- /dev/null +++ b/snippets/csharp/System/Single/Overview/convert2.cs @@ -0,0 +1,98 @@ +using System; + +public class Example5 +{ + public static void Main() + { + // + float[] values = { Single.MinValue, -67890.1234f, -12345.6789f, + 12345.6789f, 67890.1234f, Single.MaxValue, + Single.NaN, Single.PositiveInfinity, + Single.NegativeInfinity }; + checked + { + foreach (var value in values) + { + try + { + Int64 lValue = (long)value; + Console.WriteLine($"{value} ({value.GetType().Name}) --> {lValue} (0x{lValue:X16}) ({lValue.GetType().Name})"); + } + catch (OverflowException) + { + Console.WriteLine($"Unable to convert {value} to Int64."); + } + try + { + UInt64 ulValue = (ulong)value; + Console.WriteLine($"{value} ({value.GetType().Name}) --> {ulValue} (0x{ulValue:X16}) ({ulValue.GetType().Name})"); + } + catch (OverflowException) + { + Console.WriteLine($"Unable to convert {value} to UInt64."); + } + try + { + Decimal dValue = (decimal)value; + Console.WriteLine($"{value} ({value.GetType().Name}) --> {dValue} ({dValue.GetType().Name})"); + } + catch (OverflowException) + { + Console.WriteLine($"Unable to convert {value} to Decimal."); + } + + Double dblValue = value; + Console.WriteLine($"{value} ({value.GetType().Name}) --> {dblValue} ({dblValue.GetType().Name})"); + Console.WriteLine(); + } + } + + // The example displays the following output for conversions performed + // in a checked context: + // Unable to convert -3.402823E+38 to Int64. + // Unable to convert -3.402823E+38 to UInt64. + // Unable to convert -3.402823E+38 to Decimal. + // -3.402823E+38 (Single) --> -3.40282346638529E+38 (Double) + // + // -67890.13 (Single) --> -67890 (0xFFFFFFFFFFFEF6CE) (Int64) + // Unable to convert -67890.13 to UInt64. + // -67890.13 (Single) --> -67890.12 (Decimal) + // -67890.13 (Single) --> -67890.125 (Double) + // + // -12345.68 (Single) --> -12345 (0xFFFFFFFFFFFFCFC7) (Int64) + // Unable to convert -12345.68 to UInt64. + // -12345.68 (Single) --> -12345.68 (Decimal) + // -12345.68 (Single) --> -12345.6787109375 (Double) + // + // 12345.68 (Single) --> 12345 (0x0000000000003039) (Int64) + // 12345.68 (Single) --> 12345 (0x0000000000003039) (UInt64) + // 12345.68 (Single) --> 12345.68 (Decimal) + // 12345.68 (Single) --> 12345.6787109375 (Double) + // + // 67890.13 (Single) --> 67890 (0x0000000000010932) (Int64) + // 67890.13 (Single) --> 67890 (0x0000000000010932) (UInt64) + // 67890.13 (Single) --> 67890.12 (Decimal) + // 67890.13 (Single) --> 67890.125 (Double) + // + // Unable to convert 3.402823E+38 to Int64. + // Unable to convert 3.402823E+38 to UInt64. + // Unable to convert 3.402823E+38 to Decimal. + // 3.402823E+38 (Single) --> 3.40282346638529E+38 (Double) + // + // Unable to convert NaN to Int64. + // Unable to convert NaN to UInt64. + // Unable to convert NaN to Decimal. + // NaN (Single) --> NaN (Double) + // + // Unable to convert ∞ to Int64. + // Unable to convert ∞ to UInt64. + // Unable to convert ∞ to Decimal. + // ∞ (Single) --> ∞ (Double) + // + // Unable to convert -∞ to Int64. + // Unable to convert -∞ to UInt64. + // Unable to convert -∞ to Decimal. + // -∞ (Single) --> -∞ (Double) + // + } +} diff --git a/snippets/csharp/System/Single/Overview/exceptional1.cs b/snippets/csharp/System/Single/Overview/exceptional1.cs new file mode 100644 index 00000000000..5f914834675 --- /dev/null +++ b/snippets/csharp/System/Single/Overview/exceptional1.cs @@ -0,0 +1,19 @@ +using System; + +public class Example6 +{ + public static void Main() + { + // + float value1 = 1.163287e-36f; + float value2 = 9.164234e-25f; + float result = value1 * value2; + Console.WriteLine($"{value1} * {value2} = {result}"); + Console.WriteLine($"{result} = 0: {result.Equals(0.0f)}"); + + // The example displays the following output: + // 1.163287E-36 * 9.164234E-25 = 0 + // 0 = 0: True + // + } +} diff --git a/snippets/csharp/System/Single/Overview/exceptional2.cs b/snippets/csharp/System/Single/Overview/exceptional2.cs new file mode 100644 index 00000000000..6c0cf45b151 --- /dev/null +++ b/snippets/csharp/System/Single/Overview/exceptional2.cs @@ -0,0 +1,28 @@ +using System; + +public class Example7 +{ + public static void Main() + { + // + float value1 = 3.065e35f; + float value2 = 6.9375e32f; + float result = value1 * value2; + Console.WriteLine($"PositiveInfinity: {Single.IsPositiveInfinity(result)}"); + Console.WriteLine($"NegativeInfinity: {Single.IsNegativeInfinity(result)}"); + Console.WriteLine(); + + value1 = -value1; + result = value1 * value2; + Console.WriteLine($"PositiveInfinity: {Single.IsPositiveInfinity(result)}"); + Console.WriteLine($"NegativeInfinity: {Single.IsNegativeInfinity(result)}"); + + // The example displays the following output: + // PositiveInfinity: True + // NegativeInfinity: False + // + // PositiveInfinity: False + // NegativeInfinity: True + // + } +} diff --git a/snippets/csharp/System/Single/Overview/precisionlist1.cs b/snippets/csharp/System/Single/Overview/precisionlist1.cs new file mode 100644 index 00000000000..c42b4fc898f --- /dev/null +++ b/snippets/csharp/System/Single/Overview/precisionlist1.cs @@ -0,0 +1,17 @@ +using System; + +public class Example9 +{ + public static void Main() + { + // + Double value1 = 1 / 3.0; + Single sValue2 = 1 / 3.0f; + Double value2 = (Double)sValue2; + Console.WriteLine($"{value1:R} = {value2:R}: {value1.Equals(value2)}"); + + // The example displays the following output on .NET: + // 0.3333333333333333 = 0.3333333432674408: False + // + } +} diff --git a/snippets/csharp/System/Single/Overview/precisionlist3.cs b/snippets/csharp/System/Single/Overview/precisionlist3.cs new file mode 100644 index 00000000000..d05493e8b93 --- /dev/null +++ b/snippets/csharp/System/Single/Overview/precisionlist3.cs @@ -0,0 +1,25 @@ +// +using System; + +public class PrecisionList3Example +{ + public static void Main() + { + Single[] values = { 10.01f, 2.88f, 2.88f, 2.88f, 9.0f }; + Single result = 27.65f; + Single total = 0f; + foreach (var value in values) + total += value; + + if (total.Equals(result)) + Console.WriteLine("The sum of the values equals the total."); + else + Console.WriteLine($"The sum of the values ({total}) does not equal the total ({result})."); + } +} + +// The example displays the following output on .NET: +// The sum of the values (27.650002) does not equal the total (27.65). +// The example displays the following output on .NET Framework: +// The sum of the values (27.65) does not equal the total (27.65). +// diff --git a/snippets/csharp/System/Single/Overview/precisionlist4a.cs b/snippets/csharp/System/Single/Overview/precisionlist4a.cs new file mode 100644 index 00000000000..299b38273f9 --- /dev/null +++ b/snippets/csharp/System/Single/Overview/precisionlist4a.cs @@ -0,0 +1,35 @@ +using System; +using System.IO; + +public class Example10 +{ + public static void Main() + { + // + StreamWriter sw = new(@"./Singles.dat"); + float[] values = { 3.2f / 1.11f, 1.0f / 3f, (float)Math.PI }; + for (int ctr = 0; ctr < values.Length; ctr++) + { + sw.Write(values[ctr].ToString()); + if (ctr != values.Length - 1) + sw.Write("|"); + } + sw.Close(); + + float[] restoredValues = new float[values.Length]; + StreamReader sr = new(@"./Singles.dat"); + string temp = sr.ReadToEnd(); + string[] tempStrings = temp.Split('|'); + for (int ctr = 0; ctr < tempStrings.Length; ctr++) + restoredValues[ctr] = float.Parse(tempStrings[ctr]); + + for (int ctr = 0; ctr < values.Length; ctr++) + Console.WriteLine($"{values[ctr]} {(values[ctr].Equals(restoredValues[ctr]) ? "=" : "<>")} {restoredValues[ctr]}"); + + // The example displays the following output on .NET Framework: + // 2.882883 <> 2.882883 + // 0.3333333 <> 0.3333333 + // 3.141593 <> 3.141593 + // + } +} diff --git a/snippets/csharp/System/Single/Overview/representation1.cs b/snippets/csharp/System/Single/Overview/representation1.cs new file mode 100644 index 00000000000..6ea38e68a79 --- /dev/null +++ b/snippets/csharp/System/Single/Overview/representation1.cs @@ -0,0 +1,21 @@ +// +using System; + +public class Example12 +{ + public static void Main() + { + Single value = .2f; + Single result1 = value * 10f; + Single result2 = 0f; + for (int ctr = 1; ctr <= 10; ctr++) + result2 += value; + + Console.WriteLine($".2 * 10: {result1:R}"); + Console.WriteLine($".2 Added 10 times: {result2:R}"); + } +} +// The example displays the following output: +// .2 * 10: 2 +// .2 Added 10 times: 2.0000002 +// diff --git a/snippets/csharp/System/Single/Overview/representation2.cs b/snippets/csharp/System/Single/Overview/representation2.cs new file mode 100644 index 00000000000..a3a072bdb3b --- /dev/null +++ b/snippets/csharp/System/Single/Overview/representation2.cs @@ -0,0 +1,16 @@ +// +using System; + +public class Example13 +{ + public static void Main() + { + Single value = 123.456f; + Single additional = Single.Epsilon * 1e15f; + Console.WriteLine($"{value} + {additional} = {value + additional}"); + } +} + +// The example displays the following output: +// 123.456 + 1.401298E-30 = 123.456 +// diff --git a/snippets/csharp/System/String/.ctor/Project.csproj b/snippets/csharp/System/String/.ctor/Project.csproj new file mode 100644 index 00000000000..22dd9034898 --- /dev/null +++ b/snippets/csharp/System/String/.ctor/Project.csproj @@ -0,0 +1,9 @@ + + + + Library + net10.0 + true + + + diff --git a/snippets/csharp/System/String/.ctor/char2_ctor.cs b/snippets/csharp/System/String/.ctor/char2_ctor.cs new file mode 100644 index 00000000000..ea152e7404d --- /dev/null +++ b/snippets/csharp/System/String/.ctor/char2_ctor.cs @@ -0,0 +1,30 @@ +// +using System; + +public class Example1 +{ + public static unsafe void Main() + { + char[] characters = { 'H', 'e', 'l', 'l', 'o', ' ', + 'w', 'o', 'r', 'l', 'd', '!', '\u0000' }; + String value; + + fixed (char* charPtr = characters) { + int length = 0; + Char* iterator = charPtr; + + while (*iterator != '\x0000') + { + if (*iterator == '!' || *iterator == '.') + break; + iterator++; + length++; + } + value = new String(charPtr, 0, length); + } + Console.WriteLine(value); + } +} +// The example displays the following output: +// Hello World +// diff --git a/snippets/csharp/System/String/.ctor/chptrctor_null.cs b/snippets/csharp/System/String/.ctor/chptrctor_null.cs new file mode 100644 index 00000000000..41eb2e7fa08 --- /dev/null +++ b/snippets/csharp/System/String/.ctor/chptrctor_null.cs @@ -0,0 +1,31 @@ +// +using System; + +public class Example2 +{ + public unsafe static void Main() + { + char[] chars = { 'a', 'b', 'c', 'd', '\0', 'A', 'B', 'C', 'D', '\0' }; + string s = null; + + fixed(char* chPtr = chars) { + s = new string(chPtr, 0, chars.Length); + } + + foreach (var ch in s) + Console.Write($"{(ushort)ch:X4} "); + Console.WriteLine(); + + fixed(char* chPtr = chars) { + s = new string(chPtr); + } + + foreach (var ch in s) + Console.Write($"{(ushort)ch:X4} "); + Console.WriteLine(); + } +} +// The example displays the following output: +// 0061 0062 0063 0064 0000 0041 0042 0043 0044 0000 +// 0061 0062 0063 0064 +// diff --git a/snippets/csharp/System/String/.ctor/chptrctor_null.csproj b/snippets/csharp/System/String/.ctor/chptrctor_null.csproj deleted file mode 100644 index d417f512b40..00000000000 --- a/snippets/csharp/System/String/.ctor/chptrctor_null.csproj +++ /dev/null @@ -1,59 +0,0 @@ - - - - - Debug - AnyCPU - {A494B950-CDBA-4812-A4D9-0A5682B6F169} - Exe - Properties - ChPtrCtor_Null - ChPtrCtor_Null - v4.8 - 512 - - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - true - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/snippets/csharp/System/String/.ctor/ctor1.cs b/snippets/csharp/System/String/.ctor/ctor1.cs new file mode 100644 index 00000000000..c3ff8a27bd1 --- /dev/null +++ b/snippets/csharp/System/String/.ctor/ctor1.cs @@ -0,0 +1,17 @@ +// +using System; + +public class Example3 +{ + public static void Main() + { + String value1 = "This is a string."; + String value2 = value1; + Console.WriteLine(value1); + Console.WriteLine(value2); + } +} +// The example displays the following output: +// This is a string. +// This is a string. +// diff --git a/snippets/csharp/System/String/.ctor/ctor2.cs b/snippets/csharp/System/String/.ctor/ctor2.cs new file mode 100644 index 00000000000..b6e0d7f7885 --- /dev/null +++ b/snippets/csharp/System/String/.ctor/ctor2.cs @@ -0,0 +1,20 @@ +// +using System; + +public class Example4 +{ + public static unsafe void Main() + { + char[] characters = { 'H', 'e', 'l', 'l', 'o', ' ', + 'w', 'o', 'r', 'l', 'd', '!', '\u0000' }; + string value; + + fixed (char* charPtr = characters) { + value = new String(charPtr); + } + Console.WriteLine(value); + } +} +// The example displays the following output: +// Hello world! +// diff --git a/snippets/csharp/System/String/.ctor/ptrctor_null.cs b/snippets/csharp/System/String/.ctor/ptrctor_null.cs new file mode 100644 index 00000000000..7209113786f --- /dev/null +++ b/snippets/csharp/System/String/.ctor/ptrctor_null.cs @@ -0,0 +1,32 @@ +// +using System; + +public class Example5 +{ + public unsafe static void Main() + { + sbyte[] bytes = { 0x61, 0x62, 0x063, 0x064, 0x00, 0x41, 0x42, 0x43, 0x44, 0x00 }; + + string s = null; + fixed (sbyte* bytePtr = bytes) { + s = new string(bytePtr, 0, bytes.Length); + } + + foreach (var ch in s) + Console.Write($"{(ushort)ch:X4} "); + + Console.WriteLine(); + + fixed(sbyte* bytePtr = bytes) { + s = new string(bytePtr); + } + + foreach (var ch in s) + Console.Write($"{(ushort)ch:X4} "); + Console.WriteLine(); + } +} +// The example displays the following output: +// 0061 0062 0063 0064 0000 0041 0042 0043 0044 0000 +// 0061 0062 0063 0064 +// diff --git a/snippets/csharp/System/String/.ctor/source.cs b/snippets/csharp/System/String/.ctor/source.cs new file mode 100644 index 00000000000..7eebd4e46d9 --- /dev/null +++ b/snippets/csharp/System/String/.ctor/source.cs @@ -0,0 +1,91 @@ +using System; +using System.Text; + +namespace Microsoft.Demo +{ + class ConsoleApp + { + [STAThread] + static void Main(string[] args) + { +// + // Unicode Mathematical operators + char [] charArr1 = {'\u2200','\u2202','\u200F','\u2205'}; + String szMathSymbols = new String(charArr1); + + // Unicode Letterlike Symbols + char [] charArr2 = {'\u2111','\u2118','\u2122','\u2126'}; + String szLetterLike = new String (charArr2); + + // Compare Strings - the result is false + Console.WriteLine("The Strings are equal? " + + (String.Compare(szMathSymbols, szLetterLike)==0?"true":"false") ); +// +// + unsafe + { + // Null terminated ASCII characters in an sbyte array + String szAsciiUpper = null; + sbyte[] sbArr1 = new sbyte[] { 0x41, 0x42, 0x43, 0x00 }; + // Instruct the Garbage Collector not to move the memory + fixed(sbyte* pAsciiUpper = sbArr1) + { + szAsciiUpper = new String(pAsciiUpper); + } + String szAsciiLower = null; + sbyte[] sbArr2 = { 0x61, 0x62, 0x63, 0x00 }; + // Instruct the Garbage Collector not to move the memory + fixed(sbyte* pAsciiLower = sbArr2) + { + szAsciiLower = new String(pAsciiLower, 0, sbArr2.Length); + } + // Prints "ABC abc" + Console.WriteLine(szAsciiUpper + " " + szAsciiLower); + + // Compare Strings - the result is true + Console.WriteLine("The Strings are equal when capitalized ? " + + (String.Compare(szAsciiUpper.ToUpper(), szAsciiLower.ToUpper())==0?"true":"false") ); + + // This is the effective equivalent of another Compare method, which ignores case + Console.WriteLine("The Strings are equal when capitalized ? " + + (String.Compare(szAsciiUpper, szAsciiLower, true)==0?"true":"false") ); + } +// +// + // Create a Unicode String with 5 Greek Alpha characters + String szGreekAlpha = new String('\u0391',5); + // Create a Unicode String with a Greek Omega character + String szGreekOmega = new String(new char [] {'\u03A9','\u03A9','\u03A9'},2,1); + + String szGreekLetters = String.Concat(szGreekOmega, szGreekAlpha, szGreekOmega.Clone()); + + // Examine the result + Console.WriteLine(szGreekLetters); + + // The first index of Alpha + int ialpha = szGreekLetters.IndexOf('\u0391'); + // The last index of Omega + int iomega = szGreekLetters.LastIndexOf('\u03A9'); + + Console.WriteLine("The Greek letter Alpha first appears at index " + ialpha + + " and Omega last appears at index " + iomega + " in this String."); +// + +// + unsafe + { + String utfeightstring = null; + sbyte [] asciiChars = new sbyte[] { 0x51,0x52,0x53,0x54,0x54,0x56 }; + UTF8Encoding encoding = new UTF8Encoding(true, true); + + // Instruct the Garbage Collector not to move the memory + fixed(sbyte* pAsciiChars = asciiChars) + { + utfeightstring = new String(pAsciiChars,0,asciiChars.Length,encoding); + } + Console.WriteLine("The UTF8 String is " + utfeightstring ); // prints "QRSTTV" + } +// + } + } +} \ No newline at end of file diff --git a/snippets/csharp/System/String/Format/Example1.cs b/snippets/csharp/System/String/Format/Example1.cs new file mode 100644 index 00000000000..1040735cbf8 --- /dev/null +++ b/snippets/csharp/System/String/Format/Example1.cs @@ -0,0 +1,25 @@ +using System; + +public class Example1 +{ + public static void Main() + { + // + short[] values= { Int16.MinValue, -27, 0, 1042, Int16.MaxValue }; + Console.WriteLine("{0,10} {1,10}\n", "Decimal", "Hex"); + foreach (short value in values) + { + string formatString = String.Format("{0,10:G}: {0,10:X}", value); + Console.WriteLine(formatString); + } + // The example displays the following output: + // Decimal Hex + // + // -32768: 8000 + // -27: FFE5 + // 0: 0 + // 1042: 412 + // 32767: 7FFF + // + } +} diff --git a/snippets/csharp/System/String/Format/Example2.cs b/snippets/csharp/System/String/Format/Example2.cs index af0fbbb8d57..b33a5f30d9e 100644 --- a/snippets/csharp/System/String/Format/Example2.cs +++ b/snippets/csharp/System/String/Format/Example2.cs @@ -1,13 +1,13 @@ using System; using System.Globalization; -public class Example +public class Example2 { public static void Main() { // string[] cultureNames = { "en-US", "fr-FR", "de-DE", "es-ES" }; - + DateTime dateToDisplay = new DateTime(2009, 9, 1, 18, 32, 0); double value = 9164.32; @@ -15,13 +15,13 @@ public static void Main() foreach (string cultureName in cultureNames) { System.Globalization.CultureInfo culture = new System.Globalization.CultureInfo(cultureName); - string output = String.Format(culture, "{0,-11} {1,-35:D} {2:N}", + string output = String.Format(culture, "{0,-11} {1,-35:D} {2:N}", culture.Name, dateToDisplay, value); Console.WriteLine(output); - } + } // The example displays the following output: // Culture Date Value - // + // // en-US Tuesday, September 01, 2009 9,164.32 // fr-FR mardi 1 septembre 2009 9 164,32 // de-DE Dienstag, 1. September 2009 9.164,32 diff --git a/snippets/csharp/System/String/Format/Project.csproj b/snippets/csharp/System/String/Format/Project.csproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/csharp/System/String/Format/Project.csproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/csharp/System/String/Intern/Intern1.cs b/snippets/csharp/System/String/Intern/Intern1.cs new file mode 100644 index 00000000000..fa3a57ae33a --- /dev/null +++ b/snippets/csharp/System/String/Intern/Intern1.cs @@ -0,0 +1,17 @@ +using System; +using System.Text; + +[assembly: CLSCompliant(true)] +public class Class1 +{ + public static void Main() + { + // + string s1 = "MyTest"; + string s2 = new StringBuilder().Append("My").Append("Test").ToString(); + string s3 = String.Intern(s2); + Console.WriteLine((Object)s2==(Object)s1); // Different references. + Console.WriteLine((Object)s3==(Object)s1); // The same reference. + // + } +} diff --git a/snippets/csharp/System/String/Intern/Project.csproj b/snippets/csharp/System/String/Intern/Project.csproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/csharp/System/String/Intern/Project.csproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/csharp/System/String/IsNullOrEmpty/NullString1.cs b/snippets/csharp/System/String/IsNullOrEmpty/NullString1.cs new file mode 100644 index 00000000000..c9da93895ba --- /dev/null +++ b/snippets/csharp/System/String/IsNullOrEmpty/NullString1.cs @@ -0,0 +1,40 @@ +using System; + +public class Example +{ + public static void Main() + { + // + String s = null; + + Console.WriteLine($"The value of the string is '{s}'"); + + try + { + Console.WriteLine($"String length is {s.Length}"); + } + catch (NullReferenceException e) + { + Console.WriteLine(e.Message); + } + + // The example displays the following output: + // The value of the string is '' + // Object reference not set to an instance of an object. + // + } +} + +public class Empty +{ + public void Test() + { + // + String s = ""; + Console.WriteLine($"The length of '{s}' is {s.Length}."); + + // The example displays the following output: + // The length of '' is 0. + // + } +} diff --git a/snippets/csharp/System/String/IsNullOrEmpty/Project.csproj b/snippets/csharp/System/String/IsNullOrEmpty/Project.csproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/csharp/System/String/IsNullOrEmpty/Project.csproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/csharp/System/String/IsNullOrEmpty/isnullorempty1.cs b/snippets/csharp/System/String/IsNullOrEmpty/isnullorempty1.cs new file mode 100644 index 00000000000..d023d3a5236 --- /dev/null +++ b/snippets/csharp/System/String/IsNullOrEmpty/isnullorempty1.cs @@ -0,0 +1,25 @@ +using System; + +public class Example1 +{ + public static void Main() + { + // + bool TestForNullOrEmpty(string s) + { + bool result; + result = s == null || s == string.Empty; + return result; + } + + string s1 = null; + string s2 = ""; + Console.WriteLine(TestForNullOrEmpty(s1)); + Console.WriteLine(TestForNullOrEmpty(s2)); + + // The example displays the following output: + // True + // True + // + } +} diff --git a/snippets/csharp/System/TimeSpan/Overview/Program.cs b/snippets/csharp/System/TimeSpan/Overview/Program.cs new file mode 100644 index 00000000000..1047b684bc1 --- /dev/null +++ b/snippets/csharp/System/TimeSpan/Overview/Program.cs @@ -0,0 +1 @@ +Example4.Run(); diff --git a/snippets/csharp/System/TimeSpan/Overview/Project.csproj b/snippets/csharp/System/TimeSpan/Overview/Project.csproj new file mode 100644 index 00000000000..274b5ecb6d6 --- /dev/null +++ b/snippets/csharp/System/TimeSpan/Overview/Project.csproj @@ -0,0 +1,8 @@ + + + + Exe + net10.0 + + + diff --git a/snippets/csharp/System/TimeSpan/Overview/instantiate1.cs b/snippets/csharp/System/TimeSpan/Overview/instantiate1.cs new file mode 100644 index 00000000000..c93d7f01285 --- /dev/null +++ b/snippets/csharp/System/TimeSpan/Overview/instantiate1.cs @@ -0,0 +1,74 @@ +using System; + +public class Example +{ + public static void Main() + { + Implicit(); + Console.WriteLine(); + Explicit(); + Console.WriteLine(); + TimeSpanOperation(); + Console.WriteLine(); + Parse(); + Console.WriteLine(); + } + + private static void Implicit() + { + // + TimeSpan interval = new TimeSpan(); + Console.WriteLine(interval.Equals(TimeSpan.Zero)); // Displays "True". + // + } + + private static void Explicit() + { + // + TimeSpan interval = new TimeSpan(2, 14, 18); + Console.WriteLine(interval.ToString()); + + // Displays "02:14:18". + // + } + + private static void TimeSpanOperation() + { + // + DateTime departure = new DateTime(2010, 6, 12, 18, 32, 0); + DateTime arrival = new DateTime(2010, 6, 13, 22, 47, 0); + TimeSpan travelTime = arrival - departure; + Console.WriteLine($"{arrival} - {departure} = {travelTime}"); + + // The example displays the following output: + // 6/13/2010 10:47:00 PM - 6/12/2010 6:32:00 PM = 1.04:15:00 + // + } + + private static void Parse() + { + // + string[] values = { "12", "31.", "5.8:32:16", "12:12:15.95", ".12"}; + foreach (string value in values) + { + try { + TimeSpan ts = TimeSpan.Parse(value); + Console.WriteLine($"'{value}' --> {ts}"); + } + catch (FormatException) { + Console.WriteLine($"Unable to parse '{value}'"); + } + catch (OverflowException) { + Console.WriteLine($"'{value}' is outside the range of a TimeSpan."); + } + } + + // The example displays the following output: + // '12' --> 12.00:00:00 + // Unable to parse '31.' + // '5.8:32:16' --> 5.08:32:16 + // '12:12:15.95' --> 12:12:15.9500000 + // Unable to parse '.12' + // + } +} diff --git a/snippets/csharp/System/TimeSpan/Overview/structure1.cs b/snippets/csharp/System/TimeSpan/Overview/structure1.cs index c6ad2557bd6..f034ea01cd4 100644 --- a/snippets/csharp/System/TimeSpan/Overview/structure1.cs +++ b/snippets/csharp/System/TimeSpan/Overview/structure1.cs @@ -1,6 +1,6 @@ using System; -public class Example +public class StructureExample1 { public static void Main() { diff --git a/snippets/csharp/System/TimeSpan/Overview/zero1.cs b/snippets/csharp/System/TimeSpan/Overview/zero1.cs new file mode 100644 index 00000000000..3ac36200ed2 --- /dev/null +++ b/snippets/csharp/System/TimeSpan/Overview/zero1.cs @@ -0,0 +1,31 @@ +using System; + +public class Example4 +{ + public static void Run() + { + // + Random rnd = new Random(); + + TimeSpan timeSpent = TimeSpan.Zero; + + timeSpent += GetTimeBeforeLunch(); + timeSpent += GetTimeAfterLunch(); + + Console.WriteLine($"Total time: {timeSpent}"); + + TimeSpan GetTimeBeforeLunch() + { + return new TimeSpan(rnd.Next(3, 6), 0, 0); + } + + TimeSpan GetTimeAfterLunch() + { + return new TimeSpan(rnd.Next(3, 6), 0, 0); + } + + // The example displays output like the following: + // Total time: 08:00:00 + // + } +} diff --git a/snippets/csharp/System/TimeSpan/Parse/Project.csproj b/snippets/csharp/System/TimeSpan/Parse/Project.csproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/csharp/System/TimeSpan/Parse/Project.csproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/csharp/System/TimeSpan/Parse/parse1.cs b/snippets/csharp/System/TimeSpan/Parse/parse1.cs index 164e268a774..0604062b069 100644 --- a/snippets/csharp/System/TimeSpan/Parse/parse1.cs +++ b/snippets/csharp/System/TimeSpan/Parse/parse1.cs @@ -3,20 +3,20 @@ using System.Globalization; using System.Threading; -public class Example +public class Example1 { public static void Main() { - string[] values = { "6", "6:12", "6:12:14", "6:12:14:45", - "6.12:14:45", "6:12:14:45.3448", + string[] values = { "6", "6:12", "6:12:14", "6:12:14:45", + "6.12:14:45", "6:12:14:45.3448", "6:12:14:45,3448", "6:34:14:45" }; string[] cultureNames = { "hr-HR", "en-US"}; - + // Change the current culture. foreach (string cultureName in cultureNames) { Thread.CurrentThread.CurrentCulture = new CultureInfo(cultureName); - Console.WriteLine("Current Culture: {0}", + Console.WriteLine("Current Culture: {0}", Thread.CurrentThread.CurrentCulture.Name); foreach (string value in values) { @@ -26,12 +26,12 @@ public static void Main() } catch (FormatException) { Console.WriteLine("{0}: Bad Format", value); - } + } catch (OverflowException) { Console.WriteLine("{0}: Overflow", value); } - } - Console.WriteLine(); + } + Console.WriteLine(); } } } @@ -45,7 +45,7 @@ public static void Main() // 6:12:14:45.3448: Bad Format // 6:12:14:45,3448 --> 6.12:14:45.3448000 // 6:34:14:45: Overflow -// +// // Current Culture: en-US // 6 --> 6.00:00:00 // 6:12 --> 06:12:00 @@ -55,4 +55,4 @@ public static void Main() // 6:12:14:45.3448 --> 6.12:14:45.3448000 // 6:12:14:45,3448: Bad Format // 6:34:14:45: Overflow -// \ No newline at end of file +// diff --git a/snippets/csharp/System/TimeSpan/Parse/parse2.cs b/snippets/csharp/System/TimeSpan/Parse/parse2.cs index 4a29c755743..fe7eb0fef9a 100644 --- a/snippets/csharp/System/TimeSpan/Parse/parse2.cs +++ b/snippets/csharp/System/TimeSpan/Parse/parse2.cs @@ -3,25 +3,25 @@ using System.Globalization; using System.Text.RegularExpressions; -public class Example +public class Example2 { public static void Main() { - string[] values = { "6", "6:12", "6:12:14", "6:12:14:45", - "6.12:14:45", "6:12:14:45.3448", + string[] values = { "6", "6:12", "6:12:14", "6:12:14:45", + "6.12:14:45", "6:12:14:45.3448", "6:12:14:45,3448", "6:34:14:45" }; - CultureInfo[] cultures = { new CultureInfo("en-US"), + CultureInfo[] cultures = { new CultureInfo("en-US"), new CultureInfo("ru-RU"), CultureInfo.InvariantCulture }; - + string header = String.Format("{0,-17}", "String"); foreach (CultureInfo culture in cultures) - header += culture.Equals(CultureInfo.InvariantCulture) ? + header += culture.Equals(CultureInfo.InvariantCulture) ? String.Format("{0,20}", "Invariant") : String.Format("{0,20}", culture.Name); Console.WriteLine(header); Console.WriteLine(); - + foreach (string value in values) { Console.Write("{0,-17}", value); @@ -33,18 +33,18 @@ public static void Main() } catch (FormatException) { Console.Write("{0,20}", "Bad Format"); - } + } catch (OverflowException) { Console.Write("{0,20}", "Overflow"); - } + } } - Console.WriteLine(); + Console.WriteLine(); } } } // The example displays the following output: // String en-US ru-RU Invariant -// +// // 6 6.00:00:00 6.00:00:00 6.00:00:00 // 6:12 06:12:00 06:12:00 06:12:00 // 6:12:14 06:12:14 06:12:14 06:12:14 @@ -53,4 +53,4 @@ public static void Main() // 6:12:14:45.3448 6.12:14:45.3448000 Bad Format 6.12:14:45.3448000 // 6:12:14:45,3448 Bad Format 6.12:14:45.3448000 Bad Format // 6:34:14:45 Overflow Overflow Overflow -// \ No newline at end of file +// diff --git a/snippets/csharp/System/TimeSpan/Parse/parsefailure1.cs b/snippets/csharp/System/TimeSpan/Parse/parsefailure1.cs new file mode 100644 index 00000000000..8ddbd82d5f0 --- /dev/null +++ b/snippets/csharp/System/TimeSpan/Parse/parsefailure1.cs @@ -0,0 +1,31 @@ +using System; + +public class Example3 +{ + public static void Main() + { + // + string[] values = { "000000006", "12.12:12:12.12345678" }; + foreach (string value in values) + { + try { + TimeSpan interval = TimeSpan.Parse(value); + Console.WriteLine($"{value} --> {interval}"); + } + catch (FormatException) { + Console.WriteLine($"{value}: Bad Format"); + } + catch (OverflowException) { + Console.WriteLine($"{value}: Overflow"); + } + } + + // Output from .NET Framework 3.5 and earlier versions: + // 000000006 --> 6.00:00:00 + // 12.12:12:12.12345678: Bad Format + // Output from .NET Framework 4 and later versions or .NET Core: + // 000000006: Overflow + // 12.12:12:12.12345678: Overflow + // + } +} diff --git a/snippets/csharp/System/TimeSpan/TryParse/Program.cs b/snippets/csharp/System/TimeSpan/TryParse/Program.cs new file mode 100644 index 00000000000..7855a5dcc15 --- /dev/null +++ b/snippets/csharp/System/TimeSpan/TryParse/Program.cs @@ -0,0 +1 @@ +TryParse.Main(); diff --git a/snippets/csharp/System/TimeSpan/TryParse/Project.csproj b/snippets/csharp/System/TimeSpan/TryParse/Project.csproj new file mode 100644 index 00000000000..f99395b4b2b --- /dev/null +++ b/snippets/csharp/System/TimeSpan/TryParse/Project.csproj @@ -0,0 +1,8 @@ + + + + Exe + net10.0 + + + diff --git a/snippets/csharp/System/Type/GetType/Project.csproj b/snippets/csharp/System/Type/GetType/Project.csproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/csharp/System/Type/GetType/Project.csproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/csharp/System/Type/GetType/source.cs b/snippets/csharp/System/Type/GetType/source.cs new file mode 100644 index 00000000000..cdf553928e0 --- /dev/null +++ b/snippets/csharp/System/Type/GetType/source.cs @@ -0,0 +1,33 @@ +using System; +using System.Reflection; + +class Example +{ + static void Main() + { + string test = "System.Collections.Generic.Dictionary`2[System.String,[MyNamespace.MyType, MyAssembly]]"; + // + Type t = Type.GetType(test, + (aName) => aName.Name == "MyAssembly" ? + Assembly.LoadFrom(@".\MyPath\v5.0\MyAssembly.dll") : null, + (assem, name, ignore) => assem == null ? + Type.GetType(name, false, ignore) : + assem.GetType(name, false, ignore) + ); + // + Console.WriteLine(t); + + test = "System.Collections.Generic.Dictionary`2[[YourNamespace.YourType, YourAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null], [MyNamespace.MyType, MyAssembly]]"; + // + Type t2 = Type.GetType(test, + (aName) => aName.Name == "MyAssembly" ? + Assembly.LoadFrom(@".\MyPath\v5.0\MyAssembly.dll") : + Assembly.Load(aName), + (assem, name, ignore) => assem == null ? + Type.GetType(name, false, ignore) : + assem.GetType(name, false, ignore), true + ); + // + Console.WriteLine(t2); + } +} diff --git a/snippets/csharp/System/Type/GetType/type_gettype.cs b/snippets/csharp/System/Type/GetType/type_gettype.cs index f429942b207..c0345bf6a7a 100644 --- a/snippets/csharp/System/Type/GetType/type_gettype.cs +++ b/snippets/csharp/System/Type/GetType/type_gettype.cs @@ -1,7 +1,7 @@ // using System; -class Example +class GetTypeExample { public static void Main() { diff --git a/snippets/csharp/System/Type/MakeGenericType/remarks.cs b/snippets/csharp/System/Type/MakeGenericType/remarks.cs new file mode 100644 index 00000000000..a9f8c04adb2 --- /dev/null +++ b/snippets/csharp/System/Type/MakeGenericType/remarks.cs @@ -0,0 +1,22 @@ +using System; + +// +public class Base { } +public class Derived : Base { } +// + +// +public class Outermost +{ + public class Inner + { + public class Innermost1 {} + public class Innermost2 {} + } +} +// + +class ProgStubClass +{ + public static void Main() {} +} \ No newline at end of file diff --git a/snippets/csharp/System/Type/Overview/Equals1.cs b/snippets/csharp/System/Type/Overview/Equals1.cs new file mode 100644 index 00000000000..e3a44d20d3f --- /dev/null +++ b/snippets/csharp/System/Type/Overview/Equals1.cs @@ -0,0 +1,27 @@ +using System; + +public class Example1 +{ + public static void Main() + { + // + long number1 = 1635429; + int number2 = 16203; + double number3 = 1639.41; + long number4 = 193685412; + + // Get the type of number1. + Type t = number1.GetType(); + + // Compare types of all objects with number1. + Console.WriteLine($"Type of number1 and number2 are equal: {Object.ReferenceEquals(t, number2.GetType())}"); + Console.WriteLine($"Type of number1 and number3 are equal: {Object.ReferenceEquals(t, number3.GetType())}"); + Console.WriteLine($"Type of number1 and number4 are equal: {Object.ReferenceEquals(t, number4.GetType())}"); + + // The example displays the following output: + // Type of number1 and number2 are equal: False + // Type of number1 and number3 are equal: False + // Type of number1 and number4 are equal: True + // + } +} diff --git a/snippets/csharp/System/Type/Overview/GetType1.cs b/snippets/csharp/System/Type/Overview/GetType1.cs new file mode 100644 index 00000000000..ecf2365b6d1 --- /dev/null +++ b/snippets/csharp/System/Type/Overview/GetType1.cs @@ -0,0 +1,20 @@ +using System; + +public class Example2 +{ + public static void Main() + { + // + object[] values = { "word", true, 120, 136.34, 'a' }; + foreach (var value in values) + Console.WriteLine($"{value} - type {value.GetType().Name}"); + + // The example displays the following output: + // word - type String + // True - type Boolean + // 120 - type Int32 + // 136.34 - type Double + // a - type Char + // + } +} diff --git a/snippets/csharp/System/Type/Overview/Project.csproj b/snippets/csharp/System/Type/Overview/Project.csproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/csharp/System/Type/Overview/Project.csproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/csharp/System/Type/Overview/source.cs b/snippets/csharp/System/Type/Overview/source.cs index e74fdd1f265..2e479978b80 100644 --- a/snippets/csharp/System/Type/Overview/source.cs +++ b/snippets/csharp/System/Type/Overview/source.cs @@ -5,16 +5,16 @@ using System; using System.Reflection; -class Example +class Example3 { static void Main() { Type t = typeof(String); - MethodInfo substr = t.GetMethod("Substring", + MethodInfo substr = t.GetMethod("Substring", new Type[] { typeof(int), typeof(int) }); - Object result = + Object result = substr.Invoke("Hello, World!", new Object[] { 7, 5 }); Console.WriteLine("{0} returned \"{1}\".", substr, result); } diff --git a/snippets/csharp/System/TypeInitializationException/Overview/Missing1.cs b/snippets/csharp/System/TypeInitializationException/Overview/Missing1.cs new file mode 100644 index 00000000000..b6d72e3e237 --- /dev/null +++ b/snippets/csharp/System/TypeInitializationException/Overview/Missing1.cs @@ -0,0 +1,47 @@ +// +using System; + +public class MissingEx1 +{ + public static void Main() + { + Person p = new Person("John", "Doe"); + Console.WriteLine(p); + } +} + +public class Person +{ + static readonly InfoModule s_infoModule; + + readonly string _fName; + readonly string _lName; + + static Person() + { + s_infoModule = new InfoModule(DateTime.UtcNow); + } + + public Person(string fName, string lName) + { + _fName = fName; + _lName = lName; + s_infoModule.Increment(); + } + + public override string ToString() + { + return string.Format("{0} {1}", _fName, _lName); + } +} +// The example displays the following output if missing1a.dll is renamed or removed: +// Unhandled Exception: System.TypeInitializationException: +// The type initializer for 'Person' threw an exception. ---> +// System.IO.FileNotFoundException: Could not load file or assembly +// 'Missing1a, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' +// or one of its dependencies. The system cannot find the file specified. +// at Person..cctor() +// --- End of inner exception stack trace --- +// at Person..ctor(String fName, String lName) +// at Example.Main() +// diff --git a/snippets/csharp/System/TypeInitializationException/Overview/Missing1a.cs b/snippets/csharp/System/TypeInitializationException/Overview/Missing1a.cs new file mode 100644 index 00000000000..56903779fba --- /dev/null +++ b/snippets/csharp/System/TypeInitializationException/Overview/Missing1a.cs @@ -0,0 +1,24 @@ +// +using System; + +public class InfoModule +{ + private DateTime firstUse; + private int ctr = 0; + + public InfoModule(DateTime dat) + { + firstUse = dat; + } + + public int Increment() + { + return ++ctr; + } + + public DateTime GetInitializationTime() + { + return firstUse; + } +} +// diff --git a/snippets/csharp/System/TypeInitializationException/Overview/Program.cs b/snippets/csharp/System/TypeInitializationException/Overview/Program.cs new file mode 100644 index 00000000000..b397c42b9a8 --- /dev/null +++ b/snippets/csharp/System/TypeInitializationException/Overview/Program.cs @@ -0,0 +1 @@ +RegexEx1.Run(); diff --git a/snippets/csharp/System/TypeInitializationException/Overview/Regex1.cs b/snippets/csharp/System/TypeInitializationException/Overview/Regex1.cs new file mode 100644 index 00000000000..dfeda845b44 --- /dev/null +++ b/snippets/csharp/System/TypeInitializationException/Overview/Regex1.cs @@ -0,0 +1,33 @@ +// +using System; +using System.Text.RegularExpressions; +using static System.Net.Mime.MediaTypeNames; + +public class RegexEx1 +{ + public static void Run() + { + AppDomain domain = AppDomain.CurrentDomain; + // Set a timeout interval of -2 seconds. + domain.SetData("REGEX_DEFAULT_MATCH_TIMEOUT", TimeSpan.FromSeconds(-2)); + + Regex rgx = new Regex("[aeiouy]"); + Console.WriteLine($"Regular expression pattern: {rgx.ToString()}"); + Console.WriteLine($"Timeout interval for this regex: {rgx.MatchTimeout.TotalSeconds} seconds"); + } +} + +// The example displays the following output: + +// Unhandled exception. System.TypeInitializationException: +// The type initializer for 'System.Text.RegularExpressions.Regex' threw an exception. ---> +// System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values. +// (Parameter 'AppDomain data 'REGEX_DEFAULT_MATCH_TIMEOUT' contains the invalid value or object +// '-00:00:02' for specifying a default matching timeout for System.Text.RegularExpressions.Regex.') +// at System.Text.RegularExpressions.Regex.InitDefaultMatchTimeout() +// at System.Text.RegularExpressions.Regex..cctor() +// --- End of inner exception stack trace --- +// at System.Text.RegularExpressions.Regex..ctor(String pattern, CultureInfo culture) +// at RegexEx1.Run() + +// diff --git a/snippets/csharp/System/TypeInitializationException/Overview/ctorException1.cs b/snippets/csharp/System/TypeInitializationException/Overview/ctorException1.cs new file mode 100644 index 00000000000..ac866e10443 --- /dev/null +++ b/snippets/csharp/System/TypeInitializationException/Overview/ctorException1.cs @@ -0,0 +1,33 @@ +// +using System; + +public class Example +{ + private static TestClass test = new TestClass(3); + + public static void Main() + { + Example ex = new Example(); + Console.WriteLine(test.Value); + } +} + +public class TestClass +{ + public readonly int Value; + + public TestClass(int value) + { + if (value < 0 || value > 1) throw new ArgumentOutOfRangeException(nameof(value)); + Value = value; + } +} +// The example displays the following output: +// Unhandled Exception: System.TypeInitializationException: +// The type initializer for 'Example' threw an exception. ---> +// System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values. +// at TestClass..ctor(Int32 value) +// at Example..cctor() +// --- End of inner exception stack trace --- +// at Example.Main() +// diff --git a/snippets/csharp/System/TypeInitializationException/Overview/project.csproj b/snippets/csharp/System/TypeInitializationException/Overview/project.csproj new file mode 100644 index 00000000000..a15a29bf12c --- /dev/null +++ b/snippets/csharp/System/TypeInitializationException/Overview/project.csproj @@ -0,0 +1,8 @@ + + + + Exe + net10.0 + + + diff --git a/snippets/csharp/System/Version/Overview/GettingVersions1.cs b/snippets/csharp/System/Version/Overview/GettingVersions1.cs new file mode 100644 index 00000000000..7d914d90746 --- /dev/null +++ b/snippets/csharp/System/Version/Overview/GettingVersions1.cs @@ -0,0 +1,33 @@ +using System; +using System.Reflection; + +[assembly: CLSCompliant(true)] +public class Class1 +{ + public static void Run() + { + GetOsVersion(); + Console.WriteLine(); + GetClrVersion(); + Console.WriteLine(); + } + + private static void GetOsVersion() + { + // + // Get the operating system version. + OperatingSystem os = Environment.OSVersion; + Version ver = os.Version; + Console.WriteLine($"Operating System: {os.VersionString} ({ver})"); + // + } + + private static void GetClrVersion() + { + // + // Get the common language runtime version. + Version ver = Environment.Version; + Console.WriteLine($"CLR Version {ver}"); + // + } +} diff --git a/snippets/csharp/System/Version/Overview/Program.cs b/snippets/csharp/System/Version/Overview/Program.cs new file mode 100644 index 00000000000..22abad5dddf --- /dev/null +++ b/snippets/csharp/System/Version/Overview/Program.cs @@ -0,0 +1 @@ +Class1.Run(); diff --git a/snippets/csharp/System/Version/Overview/Project.csproj b/snippets/csharp/System/Version/Overview/Project.csproj new file mode 100644 index 00000000000..8810b14fdbd --- /dev/null +++ b/snippets/csharp/System/Version/Overview/Project.csproj @@ -0,0 +1,9 @@ + + + + Exe + net10.0 + false + + + diff --git a/snippets/csharp/System/Version/Overview/comparisons1.cs b/snippets/csharp/System/Version/Overview/comparisons1.cs new file mode 100644 index 00000000000..67c94f8978e --- /dev/null +++ b/snippets/csharp/System/Version/Overview/comparisons1.cs @@ -0,0 +1,34 @@ +using System; + +public class Example7 +{ + public static void Main() + { + CompareSimple(); + } + + private static void CompareSimple() + { + // + Version v1 = new(2, 0); + Version v2 = new("2.1"); + Console.Write("Version {0} is ", v1); + switch(v1.CompareTo(v2)) + { + case 0: + Console.Write("the same as"); + break; + case 1: + Console.Write("later than"); + break; + case -1: + Console.Write("earlier than"); + break; + } + Console.WriteLine($" Version {v2}."); + + // The example displays the following output: + // Version 2.0 is earlier than Version 2.1. + // + } +} diff --git a/snippets/csharp/System/Version/Overview/comparisons2.cs b/snippets/csharp/System/Version/Overview/comparisons2.cs new file mode 100644 index 00000000000..e4f6dc58c92 --- /dev/null +++ b/snippets/csharp/System/Version/Overview/comparisons2.cs @@ -0,0 +1,27 @@ +// +using System; + +enum VersionTime {Earlier = -1, Same = 0, Later = 1 }; + +public class Example2 +{ + public static void Main() + { + Version v1 = new(1, 1); + Version v1a = new("1.1.0"); + ShowRelationship(v1, v1a); + + Version v1b = new(1, 1, 0, 0); + ShowRelationship(v1b, v1a); + } + + private static void ShowRelationship(Version v1, Version v2) + { + Console.WriteLine($"Relationship of {v1} to {v2}: {(VersionTime) v1.CompareTo(v2)}"); + } +} + +// The example displays the following output: +// Relationship of 1.1 to 1.1.0: Earlier +// Relationship of 1.1.0.0 to 1.1.0: Later +// diff --git a/snippets/csharp/System/Version/Overview/currentapp.cs b/snippets/csharp/System/Version/Overview/currentapp.cs new file mode 100644 index 00000000000..0a932351d50 --- /dev/null +++ b/snippets/csharp/System/Version/Overview/currentapp.cs @@ -0,0 +1,16 @@ +// +using System; +using System.Reflection; + +public class Example4 +{ + public static void Main() + { + // Get the version of the executing assembly (that is, this assembly). + Assembly assem = Assembly.GetEntryAssembly(); + AssemblyName assemName = assem.GetName(); + Version ver = assemName.Version; + Console.WriteLine("Application {0}, Version {1}", assemName.Name, ver.ToString()); + } +} +// diff --git a/snippets/csharp/System/Version/Overview/currentassem.cs b/snippets/csharp/System/Version/Overview/currentassem.cs new file mode 100644 index 00000000000..e83f32b25e7 --- /dev/null +++ b/snippets/csharp/System/Version/Overview/currentassem.cs @@ -0,0 +1,16 @@ +// +using System; +using System.Reflection; + +public class Example3 +{ + public static void Main() + { + // Get the version of the current assembly. + Assembly assem = typeof(Example3).Assembly; + AssemblyName assemName = assem.GetName(); + Version ver = assemName.Version; + Console.WriteLine("{0}, Version {1}", assemName.Name, ver.ToString()); + } +} +// diff --git a/snippets/csharp/System/Version/Overview/example1.cs b/snippets/csharp/System/Version/Overview/example1.cs index c210f946275..e595209c12f 100644 --- a/snippets/csharp/System/Version/Overview/example1.cs +++ b/snippets/csharp/System/Version/Overview/example1.cs @@ -16,6 +16,7 @@ public static void Main() Console.WriteLine("This is version {0} of {1}.", ver, thisAssemName.Name); } } + // The example displays the following output: // This is version 2.0.1.0 of Example1. // diff --git a/snippets/fsharp/System/FormatException/Overview/FormatExample2.fs b/snippets/fsharp/System/FormatException/Overview/FormatExample2.fs new file mode 100644 index 00000000000..0cf9b0f18d8 --- /dev/null +++ b/snippets/fsharp/System/FormatException/Overview/FormatExample2.fs @@ -0,0 +1,66 @@ +module FormatExample2 + +// +open System + +type CustomerFormatter() = + interface IFormatProvider with + member this.GetFormat(formatType) = + if formatType = typeof then + this + else + null + + interface ICustomFormatter with + member this.Format(format, arg, formatProvider: IFormatProvider) = + if this.Equals formatProvider |> not then + null + else + let format = + if String.IsNullOrEmpty format then "G" + else format.ToUpper() + + let customerString = + let s = string arg + if s.Length < 8 then + s.PadLeft(8, '0') + else s + + match format with + | "G" -> + customerString.Substring(0, 1) + "-" + + customerString.Substring(1, 5) + "-" + + customerString.Substring 6 + | "S" -> + customerString.Substring(0, 1) + "/" + + customerString.Substring(1, 5) + "/" + + customerString.Substring 6 + | "P" -> + customerString.Substring(0, 1) + "." + + customerString.Substring(1, 5) + "." + + customerString.Substring 6 + | _ -> + raise (FormatException $"The '{format}' format specifier is not supported.") + +let acctNumber = 79203159 +String.Format(CustomerFormatter(), "{0}", acctNumber) +|> printfn "%s" +String.Format(CustomerFormatter(), "{0:G}", acctNumber) +|> printfn "%s" +String.Format(CustomerFormatter(), "{0:S}", acctNumber) +|> printfn "%s" +String.Format(CustomerFormatter(), "{0:P}", acctNumber) +|> printfn "%s" +try + String.Format(CustomerFormatter(), "{0:X}", acctNumber) + |> printfn "%s" +with :? FormatException as e -> + printfn $"{e.Message}" + +// The example displays the following output: +// 7-92031-59 +// 7-92031-59 +// 7/92031/59 +// 7.92031.59 +// The 'X' format specifier is not supported. +// \ No newline at end of file diff --git a/snippets/fsharp/System/FormatException/Overview/formatoverload1.fs b/snippets/fsharp/System/FormatException/Overview/formatoverload1.fs new file mode 100644 index 00000000000..7365178fd89 --- /dev/null +++ b/snippets/fsharp/System/FormatException/Overview/formatoverload1.fs @@ -0,0 +1,13 @@ +module formatoverload1 + +// +open System + +let dat = DateTime(2012, 1, 17, 9, 30, 0) +let city = "Chicago" +let temp = -16 +String.Format("At {0} in {1}, the temperature was {2} degrees.", dat, city, temp) +|> printfn "%s" +// The example displays output like the following: +// At 1/17/2012 9:30:00 AM in Chicago, the temperature was -16 degrees. +// \ No newline at end of file diff --git a/snippets/fsharp/System/FormatException/Overview/formatoverload2.fs b/snippets/fsharp/System/FormatException/Overview/formatoverload2.fs new file mode 100644 index 00000000000..76ebd80b44e --- /dev/null +++ b/snippets/fsharp/System/FormatException/Overview/formatoverload2.fs @@ -0,0 +1,29 @@ +module formatoverload2 + +open System + +// +// Create a list of 5-tuples with population data for three U.S. cities, 1940-1950. +let cities = + [ "Los Angeles", DateTime(1940, 1, 1), 1504277, DateTime(1950, 1, 1), 1970358 + "New York", DateTime(1940, 1, 1), 7454995, DateTime(1950, 1, 1), 7891957 + "Chicago", DateTime(1940, 1, 1), 3396808, DateTime(1950, 1, 1), 3620962 + "Detroit", DateTime(1940, 1, 1), 1623452, DateTime(1950, 1, 1), 1849568 ] + +// Display header +String.Format("{0,-12}{1,8}{2,12}{1,8}{2,12}{3,14}\n", "City", "Year", "Population", "Change (%)") +|> printfn "%s" + +for name, year1, pop1, year2, pop2 in cities do + String.Format("{0,-12}{1,8:yyyy}{2,12:N0}{3,8:yyyy}{4,12:N0}{5,14:P1}", + name, year1, pop1, year2, pop2, + double (pop2 - pop1) / double pop1) + |> printfn "%s" +// The example displays the following output: +// City Year Population Year Population Change (%) +// +// Los Angeles 1940 1,504,277 1950 1,970,358 31.0 % +// New York 1940 7,454,995 1950 7,891,957 5.9 % +// Chicago 1940 3,396,808 1950 3,620,962 6.6 % +// Detroit 1940 1,623,452 1950 1,849,568 13.9 % +// \ No newline at end of file diff --git a/snippets/fsharp/System/FormatException/Overview/formatsyntax1.fs b/snippets/fsharp/System/FormatException/Overview/formatsyntax1.fs new file mode 100644 index 00000000000..a743dbc0b0d --- /dev/null +++ b/snippets/fsharp/System/FormatException/Overview/formatsyntax1.fs @@ -0,0 +1,8 @@ +module formatsyntax1 + +// +open System + +String.Format("{0,-10:C}", 126347.89m) +|> printfn "%s" +// \ No newline at end of file diff --git a/snippets/fsharp/System/FormatException/Overview/interceptor2.fs b/snippets/fsharp/System/FormatException/Overview/interceptor2.fs new file mode 100644 index 00000000000..f45c4c0ea79 --- /dev/null +++ b/snippets/fsharp/System/FormatException/Overview/interceptor2.fs @@ -0,0 +1,109 @@ +module interceptor2 + +// +open System +open System.Globalization + +type InterceptProvider() = + interface IFormatProvider with + member this.GetFormat(formatType) = + if formatType = typeof then + this + else + null + interface ICustomFormatter with + member _.Format(format, obj, provider: IFormatProvider) = + // Display information about method call. + let formatString = + if format = null then "" else format + printfn $"Provider: {provider.GetType().Name}, Object: %A{obj}, Format String: %s{formatString}" + + if obj = null then + String.Empty + else + // If this is a byte and the "R" format string, format it with Roman numerals. + match obj with + | :? byte as value when formatString.ToUpper().Equals "R" -> + let mutable returnString = String.Empty + + // Get the hundreds digit(s) + let struct (result, remainder) = Math.DivRem(value, 100uy) + if result > 0uy then + returnString <- String('C', int result) + let value = byte remainder + // Get the 50s digit + let struct (result, remainder) = Math.DivRem(value, 50uy) + if result = 1uy then + returnString <- returnString + "L" + let value = byte remainder + // Get the tens digit. + let struct (result, remainder) = Math.DivRem(value, 10uy) + if result > 0uy then + returnString <- returnString + String('X', int result) + let value = byte remainder + // Get the fives digit. + let struct (result, remainder) = Math.DivRem(value, 5uy) + if result > 0uy then + returnString <- returnString + "V" + let value = byte remainder + // Add the ones digit. + if remainder > 0uy then + returnString <- returnString + String('I', int remainder) + + // Check whether we have too many X characters. + let pos = returnString.IndexOf "XXXX" + if pos >= 0 then + let xPos = returnString.IndexOf "L" + returnString <- + if xPos >= 0 && xPos = pos - 1 then + returnString.Replace("LXXXX", "XC") + else + returnString.Replace("XXXX", "XL") + // Check whether we have too many I characters + let pos = returnString.IndexOf "IIII" + if pos >= 0 then + returnString <- + if returnString.IndexOf "V" >= 0 then + returnString.Replace("VIIII", "IX") + else + returnString.Replace("IIII", "IV") + returnString + + // Use default for all other formatting. + | :? IFormattable as x -> + x.ToString(format, CultureInfo.CurrentCulture) + | _ -> + string obj + +let n = 10 +let value = 16.935 +let day = DateTime.Now +let provider = InterceptProvider() +String.Format(provider, "{0:N0}: {1:C2} on {2:d}\n", n, value, day) +|> printfn "%s" +String.Format(provider, "{0}: {1:F}\n", "Today: ", DateTime.Now.DayOfWeek) +|> printfn "%s" +String.Format(provider, "{0:X}, {1}, {2}\n", 2uy, 12uy, 199uy) +|> printfn "%s" +String.Format(provider, "{0:R}, {1:R}, {2:R}\n", 2uy, 12uy, 199uy) +|> printfn "%s" +// The example displays the following output: +// Provider: InterceptProvider, Object: 10, Format String: N0 +// Provider: InterceptProvider, Object: 16.935, Format String: C2 +// Provider: InterceptProvider, Object: 1/31/2013 6:10:28 PM, Format String: d +// 10: $16.94 on 1/31/2013 +// +// Provider: InterceptProvider, Object: Today: , Format String: +// Provider: InterceptProvider, Object: Thursday, Format String: F +// Today: : Thursday +// +// Provider: InterceptProvider, Object: 2, Format String: X +// Provider: InterceptProvider, Object: 12, Format String: +// Provider: InterceptProvider, Object: 199, Format String: +// 2, 12, 199 +// +// Provider: InterceptProvider, Object: 2, Format String: R +// Provider: InterceptProvider, Object: 12, Format String: R +// Provider: InterceptProvider, Object: 199, Format String: R +// II, XII, CXCIX +// \ No newline at end of file diff --git a/snippets/fsharp/System/FormatException/Overview/qa-interpolated1.fs b/snippets/fsharp/System/FormatException/Overview/qa-interpolated1.fs new file mode 100644 index 00000000000..f29e8e4b141 --- /dev/null +++ b/snippets/fsharp/System/FormatException/Overview/qa-interpolated1.fs @@ -0,0 +1,18 @@ +module qa_interpolated1 + +// +open System + +let names = [| "Balto"; "Vanya"; "Dakota"; "Samuel"; "Koani"; "Yiska"; "Yuma" |] +let output = + names[0] + ", " + names[1] + ", " + names[2] + ", " + + names[3] + ", " + names[4] + ", " + names[5] + ", " + + names[6] + "\n" + +let date = DateTime.Now +output + String.Format("It is {0:t} on {0:d}. The day of the week is {1}.", date, date.DayOfWeek) +|> printfn "%s" +// The example displays the following output: +// Balto, Vanya, Dakota, Samuel, Koani, Yiska, Yuma +// It is 10:29 AM on 1/8/2018. The day of the week is Monday. +// \ No newline at end of file diff --git a/snippets/fsharp/System/FormatException/Overview/qa-interpolated2.fs b/snippets/fsharp/System/FormatException/Overview/qa-interpolated2.fs new file mode 100644 index 00000000000..a70413c32d7 --- /dev/null +++ b/snippets/fsharp/System/FormatException/Overview/qa-interpolated2.fs @@ -0,0 +1,15 @@ +module qa_interpolated2 + +// +open System + +let names = [| "Balto"; "Vanya"; "Dakota"; "Samuel"; "Koani"; "Yiska"; "Yuma" |] +let output = $"{names[0]}, {names[1]}, {names[2]}, {names[3]}, {names[4]}, {names[5]}, {names[6]}" + +let date = DateTime.Now +output + $"\nIt is {date:t} on {date:d}. The day of the week is {date.DayOfWeek}." +|> printfn "%s" +// The example displays the following output: +// Balto, Vanya, Dakota, Samuel, Koani, Yiska, Yuma +// It is 10:29 AM on 1/8/2018. The day of the week is Monday. +// \ No newline at end of file diff --git a/snippets/fsharp/System/FormatException/Overview/qa11.fs b/snippets/fsharp/System/FormatException/Overview/qa11.fs new file mode 100644 index 00000000000..3d152075bed --- /dev/null +++ b/snippets/fsharp/System/FormatException/Overview/qa11.fs @@ -0,0 +1,15 @@ +module qa11 + +// +open System + +let rnd = Random() +let mutable total = 0 +let numbers = Array.zeroCreate 4 +for i = 0 to 2 do + let number = rnd.Next 1001 + numbers[i] <- number + total <- total + number +numbers[3] <- total +Console.WriteLine("{0} + {1} + {2} = {3}", numbers) +// \ No newline at end of file diff --git a/snippets/fsharp/System/FormatException/Overview/qa21.fs b/snippets/fsharp/System/FormatException/Overview/qa21.fs new file mode 100644 index 00000000000..56dc9afe390 --- /dev/null +++ b/snippets/fsharp/System/FormatException/Overview/qa21.fs @@ -0,0 +1,17 @@ +module qa21 + +// +open System + +let rnd = Random() +let numbers = Array.zeroCreate 4 +let mutable total = 0 +for i = 0 to 2 do + let number = rnd.Next 1001 + numbers[i] <- number + total <- total + number +numbers[3] <- total +let values = Array.zeroCreate numbers.Length +numbers.CopyTo(values, 0) +Console.WriteLine("{0} + {1} + {2} = {3}", values) +// \ No newline at end of file diff --git a/snippets/fsharp/System/FormatException/Overview/qa26.fs b/snippets/fsharp/System/FormatException/Overview/qa26.fs new file mode 100644 index 00000000000..308535944f9 --- /dev/null +++ b/snippets/fsharp/System/FormatException/Overview/qa26.fs @@ -0,0 +1,16 @@ +module qa26 + +// +open System + +let values: obj list = [ 1603, 1794.68235, 15436.14 ] +for value in values do + String.Format("{0,12:C2} {0,12:E3} {0,12:F4} {0,12:N3} {1,12:P2}\n", Convert.ToDouble(value), Convert.ToDouble(value) / 10000.) + |> printfn "%s" +// The example displays output like the following: +// $1,603.00 1.603E+003 1603.0000 1,603.000 16.03 % +// +// $1,794.68 1.795E+003 1794.6824 1,794.682 17.95 % +// +// $15,436.14 1.544E+004 15436.1400 15,436.140 154.36 % +// \ No newline at end of file diff --git a/snippets/fsharp/System/FormatException/Overview/qa27.fs b/snippets/fsharp/System/FormatException/Overview/qa27.fs new file mode 100644 index 00000000000..dde74671a0e --- /dev/null +++ b/snippets/fsharp/System/FormatException/Overview/qa27.fs @@ -0,0 +1,11 @@ +module qa27 + +open System + +// +let value = 16309.5436m +String.Format("{0,12:#.00000} {0,12:0,000.00} {0,12:000.00#}", value) +|> printfn "%s" +// The example displays the following output: +// 16309.54360 16,309.54 16309.544 +// \ No newline at end of file diff --git a/snippets/fsharp/System/FormatException/Overview/qa28.fs b/snippets/fsharp/System/FormatException/Overview/qa28.fs new file mode 100644 index 00000000000..dbb92793763 --- /dev/null +++ b/snippets/fsharp/System/FormatException/Overview/qa28.fs @@ -0,0 +1,11 @@ +module qa28 + +// +open System + +let value = 16342 +String.Format("{0,18:00000000} {0,18:00000000.000} {0,18:000,0000,000.0}", value) +|> printfn "%s" +// The example displays the following output: +// 00016342 00016342.000 0,000,016,342.0 +// \ No newline at end of file diff --git a/snippets/fsharp/System/FormatException/Overview/qa29.fs b/snippets/fsharp/System/FormatException/Overview/qa29.fs new file mode 100644 index 00000000000..74ab5f7281b --- /dev/null +++ b/snippets/fsharp/System/FormatException/Overview/qa29.fs @@ -0,0 +1,11 @@ +module qa29 + +// +open System + +let value = 1326 +String.Format("{0,10:D6} {0,10:X8}", value) +|> printfn "%s" +// The example displays the following output: +// 001326 0000052E +// \ No newline at end of file diff --git a/snippets/fsharp/System/FormatException/Overview/starting1.fs b/snippets/fsharp/System/FormatException/Overview/starting1.fs new file mode 100644 index 00000000000..3ea79b6661f --- /dev/null +++ b/snippets/fsharp/System/FormatException/Overview/starting1.fs @@ -0,0 +1,44 @@ +module starting1 + +open System + +let snippet31 () = + // + String.Format("At {0}, the temperature is {1}°C.", DateTime.Now, 20.4) + |> printfn "%s" + // Output similar to: 'At 4/10/2015 9:29:41 AM, the temperature is 20.4°C.' + // + +let snippet32 () = + // + String.Format("It is now {0:d} at {0:t}", DateTime.Now) + |> printfn "%s" + // Output similar to: 'It is now 4/10/2015 at 10:04 AM' + // + +let snippet34 () = + // + let years = [| 2013; 2014; 2015 |] + let population = [| 1025632; 1105967; 1148203 |] + let mutable s = String.Format("{0,-10} {1,-10}\n\n", "Year", "Population") + for i = 0 to years.Length - 1 do + s <- s + String.Format("{0,-10} {1,-10:N0}\n", years[i], population[i]) + printfn $"\n{s}" + // Result: + // Year Population + // + // 2013 1,025,632 + // 2014 1,105,967 + // 2015 1,148,203 + // + +// +let temp = 20.4m +String.Format("The temperature is {0}°C.", temp) +|> printfn "%s" +// Displays 'The temperature is 20.4°C.' +// + +snippet31 () +snippet32 () +snippet34 () \ No newline at end of file diff --git a/snippets/fsharp/System/FormatException/Overview/starting2.fs b/snippets/fsharp/System/FormatException/Overview/starting2.fs new file mode 100644 index 00000000000..9680d1bbabb --- /dev/null +++ b/snippets/fsharp/System/FormatException/Overview/starting2.fs @@ -0,0 +1,20 @@ +module starting2 + +open System + +let showFormatted () = + // + let pricePerOunce = 17.36m + String.Format("The current price is {0:C2} per ounce.", pricePerOunce) + |> printfn "%s" + // Result if current culture is en-US: + // The current price is $17.36 per ounce. + // + +// +let pricePerOunce = 17.36m +String.Format("The current price is {0} per ounce.", pricePerOunce) +|> printfn "%s" +// Result: The current price is 17.36 per ounce. +// +showFormatted () diff --git a/snippets/fsharp/System/FormatException/Overview/starting3.fs b/snippets/fsharp/System/FormatException/Overview/starting3.fs new file mode 100644 index 00000000000..0d881960c3a --- /dev/null +++ b/snippets/fsharp/System/FormatException/Overview/starting3.fs @@ -0,0 +1,22 @@ +module starting3 + +// +open System +open System.Text + +let years = [| 2013; 2014; 2015 |] +let population = [| 1025632; 1105967; 1148203 |] +let sb = StringBuilder() +sb.Append(String.Format("{0,6} {1,15}\n\n", "Year", "Population")) |> ignore +for i = 0 to years.Length - 1 do + sb.Append(String.Format("{0,6} {1,15:N0}\n", years[i], population[i])) |> ignore + +printfn $"{sb}" + +// Result: +// Year Population +// +// 2013 1,025,632 +// 2014 1,105,967 +// 2015 1,148,203 +// \ No newline at end of file diff --git a/snippets/fsharp/System/Random/Overview/Random1.fs b/snippets/fsharp/System/Random/Overview/Random1.fs new file mode 100644 index 00000000000..0017b215d5b --- /dev/null +++ b/snippets/fsharp/System/Random/Overview/Random1.fs @@ -0,0 +1,50 @@ +module Random1 + +open System + +// +let bytes1 = Array.zeroCreate 100 +let bytes2 = Array.zeroCreate 100 +let rnd1 = Random() +let rnd2 = Random() + +rnd1.NextBytes bytes1 +rnd2.NextBytes bytes2 + +printfn "First Series" +for i = bytes1.GetLowerBound 0 to bytes1.GetUpperBound 0 do + printf "%5i" bytes1.[i] + if (i + 1) % 10 = 0 then printfn "" + +printfn "" + +printfn "Second Series" +for i = bytes2.GetLowerBound 0 to bytes2.GetUpperBound 0 do + printf "%5i" bytes2.[i] + if (i + 1) % 10 = 0 then printfn "" + +// The example displays output like the following: +// First Series: +// 97 129 149 54 22 208 120 105 68 177 +// 113 214 30 172 74 218 116 230 89 18 +// 12 112 130 105 116 180 190 200 187 120 +// 7 198 233 158 58 51 50 170 98 23 +// 21 1 113 74 146 245 34 255 96 24 +// 232 255 23 9 167 240 255 44 194 98 +// 18 175 173 204 169 171 236 127 114 23 +// 167 202 132 65 253 11 254 56 214 127 +// 145 191 104 163 143 7 174 224 247 73 +// 52 6 231 255 5 101 83 165 160 231 +// +// Second Series: +// 97 129 149 54 22 208 120 105 68 177 +// 113 214 30 172 74 218 116 230 89 18 +// 12 112 130 105 116 180 190 200 187 120 +// 7 198 233 158 58 51 50 170 98 23 +// 21 1 113 74 146 245 34 255 96 24 +// 232 255 23 9 167 240 255 44 194 98 +// 18 175 173 204 169 171 236 127 114 23 +// 167 202 132 65 253 11 254 56 214 127 +// 145 191 104 163 143 7 174 224 247 73 +// 52 6 231 255 5 101 83 165 160 231 +// diff --git a/snippets/fsharp/System/Random/Overview/array1.fs b/snippets/fsharp/System/Random/Overview/array1.fs new file mode 100644 index 00000000000..ca56497d573 --- /dev/null +++ b/snippets/fsharp/System/Random/Overview/array1.fs @@ -0,0 +1,21 @@ +module Array1 + +open System + +// +let cities = + [| "Atlanta"; "Boston"; "Chicago"; "Detroit"; + "Fort Wayne"; "Greensboro"; "Honolulu"; "Indianapolis"; + "Jersey City"; "Kansas City"; "Los Angeles"; + "Milwaukee"; "New York"; "Omaha"; "Philadelphia"; + "Raleigh"; "San Francisco"; "Tulsa"; "Washington" |] + +let rnd = Random() + +let index = rnd.Next(0,cities.Length) + +printfn "Today's city of the day: %s" cities.[index] + +// The example displays output like the following: +// Today's city of the day: Honolulu +// diff --git a/snippets/fsharp/System/Random/Overview/booleans1.fs b/snippets/fsharp/System/Random/Overview/booleans1.fs new file mode 100644 index 00000000000..44a9bba0f75 --- /dev/null +++ b/snippets/fsharp/System/Random/Overview/booleans1.fs @@ -0,0 +1,28 @@ +module Booleans1 + +// +open System + +type BooleanGenerator() = + let rnd = Random() + + member _.NextBoolean() = + rnd.Next(0, 2) = 1 + +let boolGen = BooleanGenerator() +let mutable totalTrue, totalFalse = 0, 0 + +for _ = 1 to 1000000 do + let value = boolGen.NextBoolean() + if value then + totalTrue <- totalTrue + 1 + else + totalFalse <- totalFalse + 1 + +printfn $"Number of true values: {totalTrue,7:N0} ({(double totalTrue) / double (totalTrue + totalFalse):P3})" +printfn $"Number of false values: {totalFalse,7:N0} ({(double totalFalse) / double (totalTrue + totalFalse):P3})" + +// The example displays output like the following: +// Number of true values: 500,004 (50.000 %) +// Number of false values: 499,996 (50.000 %) +// diff --git a/snippets/fsharp/System/Random/Overview/booleans2.fs b/snippets/fsharp/System/Random/Overview/booleans2.fs new file mode 100644 index 00000000000..e4e146c3a8d --- /dev/null +++ b/snippets/fsharp/System/Random/Overview/booleans2.fs @@ -0,0 +1,26 @@ +module Booleans2 + +open System + +// +let rnd = Random() + +let nextBool () = + rnd.Next(0, 2) = 1 + +let mutable totalTrue, totalFalse = 0, 0 + +for _ = 1 to 1000000 do + let value = nextBool () + if value then + totalTrue <- totalTrue + 1 + else + totalFalse <- totalFalse + 1 + +printfn $"Number of true values: {totalTrue,7:N0} ({(double totalTrue) / double (totalTrue + totalFalse):P3})" +printfn $"Number of false values: {totalFalse,7:N0} ({(double totalFalse) / double (totalTrue + totalFalse):P3})" + +// The example displays output like the following: +// Number of true values: 499,777 (49.978 %) +// Number of false values: 500,223 (50.022 %) +// diff --git a/snippets/fsharp/System/Random/Overview/bytes1.fs b/snippets/fsharp/System/Random/Overview/bytes1.fs new file mode 100644 index 00000000000..9b605bc10ea --- /dev/null +++ b/snippets/fsharp/System/Random/Overview/bytes1.fs @@ -0,0 +1,49 @@ +module Bytes1 + +// +open System + +type Random2() = + inherit Random() + + member this.NextBytes(bytes: byte[], minValue: byte, maxValue: byte) = + for i=bytes.GetLowerBound(0) to bytes.GetUpperBound(0) do + bytes.[i] <- this.Next(int minValue, int maxValue) |> byte + +let rnd = Random2() +let bytes = Array.zeroCreate 10000 +let total = Array.zeroCreate 101 +rnd.NextBytes(bytes, 0uy, 101uy) + +// Calculate how many of each value we have. +for v in bytes do + total.[int v] <- total.[int v] + 1 + +// Display the results. +for i = 0 to total.Length - 1 do + printf "%3i: %-3i " i total.[i] + if (i + 1) % 5 = 0 then printfn "" + +// The example displays output like the following: +// 0: 115 1: 119 2: 92 3: 98 4: 92 +// 5: 102 6: 103 7: 84 8: 93 9: 116 +// 10: 91 11: 98 12: 106 13: 91 14: 92 +// 15: 101 16: 100 17: 96 18: 97 19: 100 +// 20: 101 21: 106 22: 112 23: 82 24: 85 +// 25: 102 26: 107 27: 98 28: 106 29: 102 +// 30: 109 31: 108 32: 94 33: 101 34: 107 +// 35: 101 36: 86 37: 100 38: 101 39: 102 +// 40: 113 41: 95 42: 96 43: 89 44: 99 +// 45: 81 46: 89 47: 105 48: 100 49: 85 +// 50: 103 51: 103 52: 93 53: 89 54: 91 +// 55: 97 56: 105 57: 97 58: 110 59: 86 +// 60: 116 61: 94 62: 117 63: 98 64: 110 +// 65: 93 66: 102 67: 100 68: 105 69: 83 +// 70: 81 71: 97 72: 85 73: 70 74: 98 +// 75: 100 76: 110 77: 114 78: 83 79: 90 +// 80: 96 81: 112 82: 102 83: 102 84: 99 +// 85: 81 86: 100 87: 93 88: 99 89: 118 +// 90: 95 91: 124 92: 108 93: 96 94: 104 +// 95: 106 96: 99 97: 99 98: 92 99: 99 +// 100: 108 +// diff --git a/snippets/fsharp/System/Random/Overview/doublerange1.fs b/snippets/fsharp/System/Random/Overview/doublerange1.fs new file mode 100644 index 00000000000..d4c9fe115ef --- /dev/null +++ b/snippets/fsharp/System/Random/Overview/doublerange1.fs @@ -0,0 +1,37 @@ +module DoubleRange1 + +open System + +// +[] +let ONE_TENTH = 922337203685477581L + +let rnd = Random() + +// Generate 20 million random integers. +let count = + Array.init 20000000 (fun _ -> rnd.NextDouble() * (float Int64.MaxValue) ) + |> Array.countBy (fun x -> x / (float ONE_TENTH) |> int ) // Categorize into 10 groups and count them. + |> Array.map snd + +// Display breakdown by range. +printfn "%28s %32s %7s\n" "Range" "Count" "Pct." +for i = 0 to 9 do + let r1 = int64 i * ONE_TENTH + let r2 = if i < 9 then r1 + ONE_TENTH - 1L else Int64.MaxValue + printfn $"{r1,25:N0}-{r2,25:N0} {count.[i],8:N0} {float count.[i] / 20000000.0,7:P2}" + +// The example displays output like the following: +// Range Count Pct. +// +// 0- 922,337,203,685,477,580 1,996,148 9.98 % +// 922,337,203,685,477,581-1,844,674,407,370,955,161 2,000,293 10.00 % +// 1,844,674,407,370,955,162-2,767,011,611,056,432,742 2,000,094 10.00 % +// 2,767,011,611,056,432,743-3,689,348,814,741,910,323 2,000,159 10.00 % +// 3,689,348,814,741,910,324-4,611,686,018,427,387,904 1,999,552 10.00 % +// 4,611,686,018,427,387,905-5,534,023,222,112,865,485 1,998,248 9.99 % +// 5,534,023,222,112,865,486-6,456,360,425,798,343,066 2,000,696 10.00 % +// 6,456,360,425,798,343,067-7,378,697,629,483,820,647 2,001,637 10.01 % +// 7,378,697,629,483,820,648-8,301,034,833,169,298,228 2,002,870 10.01 % +// 8,301,034,833,169,298,229-9,223,372,036,854,775,807 2,000,303 10.00 % +// diff --git a/snippets/fsharp/System/Random/Overview/doublerange2.fs b/snippets/fsharp/System/Random/Overview/doublerange2.fs new file mode 100644 index 00000000000..04c48ba953f --- /dev/null +++ b/snippets/fsharp/System/Random/Overview/doublerange2.fs @@ -0,0 +1,22 @@ +module DoubleRange2 + +open System + +// +let rnd = Random() + +for _ = 1 to 10 do + printfn "%O" (rnd.NextDouble() - 1.0) + +// The example displays output like the following: +// -0.930412760437658 +// -0.164699016215605 +// -0.9851692803135 +// -0.43468508843085 +// -0.177202483255976 +// -0.776813320245972 +// -0.0713201854710096 +// -0.0912875561468711 +// -0.540621722368813 +// -0.232211863730201 +// diff --git a/snippets/fsharp/System/Random/Overview/doublerange3.fs b/snippets/fsharp/System/Random/Overview/doublerange3.fs new file mode 100644 index 00000000000..829f6d79b1e --- /dev/null +++ b/snippets/fsharp/System/Random/Overview/doublerange3.fs @@ -0,0 +1,31 @@ +module DoubleRange3 + +open System + +// +let rnd = Random() + +let lowerBound = 10.0 +let upperBound = 11.0 + +let range = + Array.init 1000000 (fun _ -> rnd.NextDouble() * (upperBound - lowerBound) + lowerBound) + |> Array.countBy (fun x -> Math.Truncate((x - lowerBound) * 10.0) |> int) + |> Array.map snd + +for i = 0 to 9 do + let lowerRange = 10.0 + float i * 0.1 + printfn $"{lowerRange:N1} to {lowerRange + 0.1:N1}: {range.[i],8:N0} ({float range.[i] / 1000000.0,6:P2})" + +// The example displays output like the following: +// 10.0 to 10.1: 99,929 ( 9.99 %) +// 10.1 to 10.2: 100,189 (10.02 %) +// 10.2 to 10.3: 99,384 ( 9.94 %) +// 10.3 to 10.4: 100,240 (10.02 %) +// 10.4 to 10.5: 99,397 ( 9.94 %) +// 10.5 to 10.6: 100,580 (10.06 %) +// 10.6 to 10.7: 100,293 (10.03 %) +// 10.7 to 10.8: 100,135 (10.01 %) +// 10.8 to 10.9: 99,905 ( 9.99 %) +// 10.9 to 11.0: 99,948 ( 9.99 %) +// diff --git a/snippets/fsharp/System/Random/Overview/long1.fs b/snippets/fsharp/System/Random/Overview/long1.fs new file mode 100644 index 00000000000..90b86226dce --- /dev/null +++ b/snippets/fsharp/System/Random/Overview/long1.fs @@ -0,0 +1,37 @@ +module Long1 + +open System + +// +[] +let ONE_TENTH = 922337203685477581L + +let rnd = Random() + +let count = + // Generate 20 million random long integers. + Array.init 20000000 (fun _ -> rnd.NextDouble() * (float Int64.MaxValue) |> int64 ) + |> Array.countBy (fun x -> x / ONE_TENTH) // Categorize and count random numbers. + |> Array.map snd + +// Display breakdown by range. +printfn "%28s %32s %7s\n" "Range" "Count" "Pct." +for i = 0 to 9 do + let r1 = int64 i * ONE_TENTH + let r2 = if i < 9 then r1 + ONE_TENTH - 1L else Int64.MaxValue + printfn $"{r1,25:N0}-{r2,25:N0} {count.[i],8:N0} {float count.[i] / 20000000.0,7:P2}" + +// The example displays output like the following: +// Range Count Pct. +// +// 0- 922,337,203,685,477,580 1,996,148 9.98 % +// 922,337,203,685,477,581-1,844,674,407,370,955,161 2,000,293 10.00 % +// 1,844,674,407,370,955,162-2,767,011,611,056,432,742 2,000,094 10.00 % +// 2,767,011,611,056,432,743-3,689,348,814,741,910,323 2,000,159 10.00 % +// 3,689,348,814,741,910,324-4,611,686,018,427,387,904 1,999,552 10.00 % +// 4,611,686,018,427,387,905-5,534,023,222,112,865,485 1,998,248 9.99 % +// 5,534,023,222,112,865,486-6,456,360,425,798,343,066 2,000,696 10.00 % +// 6,456,360,425,798,343,067-7,378,697,629,483,820,647 2,001,637 10.01 % +// 7,378,697,629,483,820,648-8,301,034,833,169,298,228 2,002,870 10.01 % +// 8,301,034,833,169,298,229-9,223,372,036,854,775,807 2,000,303 10.00 % +// diff --git a/snippets/fsharp/System/Random/Overview/nextbytes1.fs b/snippets/fsharp/System/Random/Overview/nextbytes1.fs new file mode 100644 index 00000000000..53520b2b3ce --- /dev/null +++ b/snippets/fsharp/System/Random/Overview/nextbytes1.fs @@ -0,0 +1,17 @@ +module NextBytes1 + +open System + +// +let rnd = Random() +let bytes = Array.zeroCreate 20 +rnd.NextBytes bytes + +for i = 1 to bytes.Length do + printf "%3i " bytes.[i - 1] + if (i % 10 = 0) then printfn "" + +// The example displays output like the following: +// 141 48 189 66 134 212 211 71 161 56 +// 181 166 220 133 9 252 222 57 62 62 +// diff --git a/snippets/fsharp/System/Random/Overview/nextdoubleex1.fs b/snippets/fsharp/System/Random/Overview/nextdoubleex1.fs new file mode 100644 index 00000000000..5e1fe90a370 --- /dev/null +++ b/snippets/fsharp/System/Random/Overview/nextdoubleex1.fs @@ -0,0 +1,16 @@ +module NextDoubleEx1 + +open System + +// +let rnd = Random() +for i = 0 to 9 do + printf $"{rnd.NextDouble(),-19:R} " + if (i + 1) % 3 = 0 then printfn "" + +// The example displays output like the following: +// 0.7911680553998649 0.0903414949264105 0.79776258291572455 +// 0.615568345233597 0.652644504165577 0.84023809378977776 +// 0.099662564741290441 0.91341467383942321 0.96018602045261581 +// 0.74772306473354022 +// diff --git a/snippets/fsharp/System/Random/Overview/nextex1.fs b/snippets/fsharp/System/Random/Overview/nextex1.fs new file mode 100644 index 00000000000..9b650155718 --- /dev/null +++ b/snippets/fsharp/System/Random/Overview/nextex1.fs @@ -0,0 +1,12 @@ +module NextEx1 + +open System + +// +let rnd = Random() +for i = 0 to 9 do + printf "%3i " (rnd.Next(-10, 11)) + +// The example displays output like the following: +// 2 9 -3 2 4 -7 -3 -8 -8 5 +// diff --git a/snippets/fsharp/System/Random/Overview/range1.fs b/snippets/fsharp/System/Random/Overview/range1.fs new file mode 100644 index 00000000000..13943083adb --- /dev/null +++ b/snippets/fsharp/System/Random/Overview/range1.fs @@ -0,0 +1,14 @@ +module Range1 + +open System + +// +let rnd = Random() +for i = 1 to 15 do + printf "%3i " (rnd.Next(-10, 11)) + if i % 5 = 0 then printfn "" +// The example displays output like the following: +// -2 -5 -1 -2 10 +// -3 6 -4 -8 3 +// -7 10 5 -2 4 +// diff --git a/snippets/fsharp/System/Random/Overview/range2.fs b/snippets/fsharp/System/Random/Overview/range2.fs new file mode 100644 index 00000000000..3f8a084972c --- /dev/null +++ b/snippets/fsharp/System/Random/Overview/range2.fs @@ -0,0 +1,17 @@ +module Range2 + +open System + +// +let rnd = Random() +for i = 1 to 50 do + printf "%3i " (rnd.Next(1000, 10000)) + if i % 10 = 0 then printfn "" + +// The example displays output like the following: +// 9570 8979 5770 1606 3818 4735 8495 7196 7070 2313 +// 5279 6577 5104 5734 4227 3373 7376 6007 8193 5540 +// 7558 3934 3819 7392 1113 7191 6947 4963 9179 7907 +// 3391 6667 7269 1838 7317 1981 5154 7377 3297 5320 +// 9869 8694 2684 4949 2999 3019 2357 5211 9604 2593 +// diff --git a/snippets/fsharp/System/Random/Overview/same1.fs b/snippets/fsharp/System/Random/Overview/same1.fs new file mode 100644 index 00000000000..0d8e9045a16 --- /dev/null +++ b/snippets/fsharp/System/Random/Overview/same1.fs @@ -0,0 +1,76 @@ +module Same1 + +// +open System +open System.IO + +let showRandomNumbers seed = + let rnd = Random seed + for _ = 0 to 20 do + printfn $"{rnd.NextDouble()}" + +let persistSeed (seed: int) = + use bin = new BinaryWriter(new FileStream(@".\seed.dat", FileMode.Create)) + bin.Write seed + +let displayNewRandomNumbers () = + use bin = new BinaryReader(new FileStream(@".\seed.dat", FileMode.Open)) + let seed = bin.ReadInt32() + + let rnd = Random seed + for _ = 0 to 20 do + printfn $"{rnd.NextDouble()}" + +let seed = 100100 +showRandomNumbers seed +printfn "" + +persistSeed seed + +displayNewRandomNumbers () + +// The example displays output like the following: +// 0.500193602172748 +// 0.0209461245783354 +// 0.465869495396442 +// 0.195512794514891 +// 0.928583675496552 +// 0.729333720509584 +// 0.381455668891527 +// 0.0508996467343064 +// 0.019261200921266 +// 0.258578445417145 +// 0.0177532266908107 +// 0.983277184415272 +// 0.483650274334313 +// 0.0219647376900375 +// 0.165910115077118 +// 0.572085966622497 +// 0.805291457942357 +// 0.927985211335116 +// 0.4228545699375 +// 0.523320379910674 +// 0.157783938645285 +// +// 0.500193602172748 +// 0.0209461245783354 +// 0.465869495396442 +// 0.195512794514891 +// 0.928583675496552 +// 0.729333720509584 +// 0.381455668891527 +// 0.0508996467343064 +// 0.019261200921266 +// 0.258578445417145 +// 0.0177532266908107 +// 0.983277184415272 +// 0.483650274334313 +// 0.0219647376900375 +// 0.165910115077118 +// 0.572085966622497 +// 0.805291457942357 +// 0.927985211335116 +// 0.4228545699375 +// 0.523320379910674 +// 0.157783938645285 +// diff --git a/snippets/fsharp/System/Random/Overview/threadsafeex1.fs b/snippets/fsharp/System/Random/Overview/threadsafeex1.fs new file mode 100644 index 00000000000..df8058ffdd9 --- /dev/null +++ b/snippets/fsharp/System/Random/Overview/threadsafeex1.fs @@ -0,0 +1,146 @@ +module ThreadSafeEx1 + +// +open System +open System.Threading + +type Example() = + [] + static val mutable private previous : float + + [] + static val mutable private perThreadCtr : int + + [] + static val mutable private perThreadTotal : float + + static let source = new CancellationTokenSource() + static let countdown = new CountdownEvent(1) + static let randLock = obj () + static let numericLock = obj () + static let rand = Random() + + let mutable totalValue = 0.0 + let mutable totalCount = 0 + + member _.GetRandomNumbers(token: CancellationToken) = + let mutable result = 0.0 + countdown.AddCount 1 + try + try + for _ = 0 to 1999999 do + // Make sure there's no corruption of Random. + token.ThrowIfCancellationRequested() + + lock randLock (fun () -> + result <- rand.NextDouble() ) + + // Check for corruption of Random instance. + if result = Example.previous && result = 0.0 then + source.Cancel() + else + Example.previous <- result + + Example.perThreadCtr <- Example.perThreadCtr + 1 + Example.perThreadTotal <- Example.perThreadTotal + result + + // Update overall totals. + lock numericLock (fun () -> + // Show result. + printfn "Thread %s finished execution." Thread.CurrentThread.Name + printfn $"Random numbers generated: {Example.perThreadCtr:N0}" + printfn $"Sum of random numbers: {Example.perThreadTotal:N2}" + printfn $"Random number mean: {(Example.perThreadTotal / float Example.perThreadCtr):N4}\n" + + // Update overall totals. + totalCount <- totalCount + Example.perThreadCtr + totalValue <- totalValue + Example.perThreadTotal) + + with :? OperationCanceledException as e -> + printfn "Corruption in Thread %s %s" (e.GetType().Name) Thread.CurrentThread.Name + finally + countdown.Signal() |> ignore + + member this.Execute() = + let token = source.Token + for i = 1 to 10 do + let newThread = Thread(fun () -> this.GetRandomNumbers token) + newThread.Name <- string i + newThread.Start() + this.GetRandomNumbers token + + countdown.Signal() |> ignore + + countdown.Wait() + + source.Dispose() + + printfn $"\nTotal random numbers generated: {totalCount:N0}" + printfn $"Total sum of all random numbers: {totalValue:N2}" + printfn $"Random number mean: {(totalValue / float totalCount):N4}" + +let ex = Example() +Thread.CurrentThread.Name <- "Main" +ex.Execute() + +// The example displays output like the following: +// Thread 6 finished execution. +// Random numbers generated: 2,000,000 +// Sum of random numbers: 1,000,491.05 +// Random number mean: 0.5002 +// +// Thread 10 finished execution. +// Random numbers generated: 2,000,000 +// Sum of random numbers: 999,329.64 +// Random number mean: 0.4997 +// +// Thread 4 finished execution. +// Random numbers generated: 2,000,000 +// Sum of random numbers: 1,000,166.89 +// Random number mean: 0.5001 +// +// Thread 8 finished execution. +// Random numbers generated: 2,000,000 +// Sum of random numbers: 999,628.37 +// Random number mean: 0.4998 +// +// Thread Main finished execution. +// Random numbers generated: 2,000,000 +// Sum of random numbers: 999,920.89 +// Random number mean: 0.5000 +// +// Thread 3 finished execution. +// Random numbers generated: 2,000,000 +// Sum of random numbers: 999,370.45 +// Random number mean: 0.4997 +// +// Thread 7 finished execution. +// Random numbers generated: 2,000,000 +// Sum of random numbers: 999,330.92 +// Random number mean: 0.4997 +// +// Thread 9 finished execution. +// Random numbers generated: 2,000,000 +// Sum of random numbers: 1,000,172.79 +// Random number mean: 0.5001 +// +// Thread 5 finished execution. +// Random numbers generated: 2,000,000 +// Sum of random numbers: 1,000,079.43 +// Random number mean: 0.5000 +// +// Thread 1 finished execution. +// Random numbers generated: 2,000,000 +// Sum of random numbers: 999,817.91 +// Random number mean: 0.4999 +// +// Thread 2 finished execution. +// Random numbers generated: 2,000,000 +// Sum of random numbers: 999,930.63 +// Random number mean: 0.5000 +// +// +// Total random numbers generated: 22,000,000 +// Total sum of all random numbers: 10,998,238.98 +// Random number mean: 0.4999 +// diff --git a/snippets/fsharp/System/Random/Overview/threadsafeex2.fs b/snippets/fsharp/System/Random/Overview/threadsafeex2.fs new file mode 100644 index 00000000000..aa9cd5bdee2 --- /dev/null +++ b/snippets/fsharp/System/Random/Overview/threadsafeex2.fs @@ -0,0 +1,143 @@ +module ThreadSafeEx2 + +// +open System +open System.Threading +open System.Threading.Tasks + +type Example() = + static let source = new CancellationTokenSource() + static let rand = Random() + + static let randLock = obj () + static let numericLock = obj () + + let mutable totalValue = 0.0 + let mutable totalCount = 0 + + member _.Execute() = + use source = source // Dispose of the CancellationTokenSource when we're done with it. + let token = source.Token + + let tasks = + [| for i = 0 to 10 do + Task.Run( + (fun () -> + let mutable previous = 0.0 + let mutable taskCtr = 0 + let mutable taskTotal = 0.0 + let mutable result = 0.0 + + for _ = 1 to 2000000 do + // Make sure there's no corruption of Random. + token.ThrowIfCancellationRequested() + + lock randLock (fun () -> result <- rand.NextDouble()) + + // Check for corruption of Random instance. + if result = previous && result = 0.0 then + source.Cancel() + else + previous <- result + + taskCtr <- taskCtr + 1 + taskTotal <- taskTotal + result + + lock numericLock (fun () -> + // Show result. + printfn "Task %i finished execution." i + printfn $"Random numbers generated: {taskCtr:N0}" + printfn $"Sum of random numbers: {taskTotal:N2}" + printfn $"Random number mean: {(taskTotal / float taskCtr):N4}\n" + + // Update overall totals. + totalCount <- totalCount + taskCtr + totalValue <- totalValue + taskTotal)), + token + ) |] + + try + // Run tasks with F# Async. + Task.WhenAll tasks + |> Async.AwaitTask + |> Async.RunSynchronously + + printfn $"\nTotal random numbers generated: {totalCount:N0}" + printfn $"Total sum of all random numbers: {totalValue:N2}" + printfn $"Random number mean: {(totalValue / float totalCount):N4}" + with + | :? AggregateException as e -> + for inner in e.InnerExceptions do + match inner with + | :? TaskCanceledException as canc -> + if canc <> null then + printfn $"Task #{canc.Task.Id} cancelled" + else + printfn $"Exception: {inner.GetType().Name}" + | _ -> () + +let ex = Example() +Thread.CurrentThread.Name <- "Main" +ex.Execute() + +// The example displays output like the following: +// Task 1 finished execution. +// Random numbers generated: 2,000,000 +// Sum of random numbers: 1,000,502.47 +// Random number mean: 0.5003 +// +// Task 0 finished execution. +// Random numbers generated: 2,000,000 +// Sum of random numbers: 1,000,445.63 +// Random number mean: 0.5002 +// +// Task 2 finished execution. +// Random numbers generated: 2,000,000 +// Sum of random numbers: 1,000,556.04 +// Random number mean: 0.5003 +// +// Task 3 finished execution. +// Random numbers generated: 2,000,000 +// Sum of random numbers: 1,000,178.87 +// Random number mean: 0.5001 +// +// Task 4 finished execution. +// Random numbers generated: 2,000,000 +// Sum of random numbers: 999,819.17 +// Random number mean: 0.4999 +// +// Task 5 finished execution. +// Random numbers generated: 2,000,000 +// Sum of random numbers: 1,000,190.58 +// Random number mean: 0.5001 +// +// Task 6 finished execution. +// Random numbers generated: 2,000,000 +// Sum of random numbers: 999,720.21 +// Random number mean: 0.4999 +// +// Task 7 finished execution. +// Random numbers generated: 2,000,000 +// Sum of random numbers: 999,000.96 +// Random number mean: 0.4995 +// +// Task 8 finished execution. +// Random numbers generated: 2,000,000 +// Sum of random numbers: 999,499.33 +// Random number mean: 0.4997 +// +// Task 9 finished execution. +// Random numbers generated: 2,000,000 +// Sum of random numbers: 1,000,193.25 +// Random number mean: 0.5001 +// +// Task 10 finished execution. +// Random numbers generated: 2,000,000 +// Sum of random numbers: 999,960.82 +// Random number mean: 0.5000 +// +// +// Total random numbers generated: 22,000,000 +// Total sum of all random numbers: 11,000,067.33 +// Random number mean: 0.5000 +// diff --git a/snippets/fsharp/System/Random/Overview/unique.fs b/snippets/fsharp/System/Random/Overview/unique.fs new file mode 100644 index 00000000000..2a0d2c1466e --- /dev/null +++ b/snippets/fsharp/System/Random/Overview/unique.fs @@ -0,0 +1,46 @@ +module Unique + +// +open System +open System.Threading + +printfn "Instantiating two random number generators..." +let rnd1 = Random() +Thread.Sleep 2000 +let rnd2 = Random() + +printfn "\nThe first random number generator:" +for _ = 1 to 10 do + printfn $" {rnd1.Next()}" + +printfn "\nThe second random number generator:" +for _ = 1 to 10 do + printfn $" {rnd2.Next()}" + +// The example displays output like the following: +// Instantiating two random number generators... +// +// The first random number generator: +// 643164361 +// 1606571630 +// 1725607587 +// 2138048432 +// 496874898 +// 1969147632 +// 2034533749 +// 1840964542 +// 412380298 +// 47518930 +// +// The second random number generator: +// 1251659083 +// 1514185439 +// 1465798544 +// 517841554 +// 1821920222 +// 195154223 +// 1538948391 +// 1548375095 +// 546062716 +// 897797880 +// diff --git a/snippets/fsharp/System/Random/Overview/uniquearray1.fs b/snippets/fsharp/System/Random/Overview/uniquearray1.fs new file mode 100644 index 00000000000..5cae6445e6d --- /dev/null +++ b/snippets/fsharp/System/Random/Overview/uniquearray1.fs @@ -0,0 +1,78 @@ +module UniqueArray1 + +// +open System + +type Suit = + | Clubs + | Diamonds + | Hearts + | Spades + +type Face = + | Ace | Two | Three + | Four | Five | Six + | Seven | Eight | Nine + | Ten | Jack | Queen | King + +type Card = { Face: Face; Suit: Suit } + +let suits = [ Clubs; Diamonds; Hearts; Spades ] +let faces = [ Ace; Two; Three; Four; Five; Six; Seven; Eight; Nine; Ten; Jack; Queen; King ] + +type Dealer() = + let rnd = Random() + let mutable pos = 0 + // Parallel array for sorting cards. + let order = Array.init (suits.Length * faces.Length) (fun _ -> rnd.NextDouble() ) + // A deck of cards, without Jokers. + let deck = [| + for s in suits do + for f in faces do + { Face = f; Suit = s } |] + // Shuffle the deck. + do Array.Sort(order, deck) + + // Deal a number of cards from the deck, return None if failed + member _.Deal(numberToDeal) : Card [] option = + if numberToDeal = 0 || pos = deck.Length then + printfn "There are no cards left in the deck" + None + else + let cards = deck.[pos .. numberToDeal + pos - 1] + if numberToDeal > deck.Length - pos then + printfn "Can only deal the %i cards remaining on the deck." (deck.Length - pos) + pos <- min (pos + numberToDeal) deck.Length + Some cards + +let showCards cards = + for card in cards do + printfn $"{card.Face} of {card.Suit}" + +let dealer = Dealer() + +dealer.Deal 20 +|> Option.iter showCards + +// The example displays output like the following: +// Six of Diamonds +// King of Clubs +// Eight of Clubs +// Seven of Clubs +// Queen of Clubs +// King of Hearts +// Three of Spades +// Ace of Clubs +// Four of Hearts +// Three of Diamonds +// Nine of Diamonds +// Two of Hearts +// Ace of Hearts +// Three of Hearts +// Four of Spades +// Eight of Hearts +// Queen of Diamonds +// Two of Clubs +// Four of Diamonds +// Jack of Hearts +// diff --git a/snippets/fsharp/System/Single/CompareTo/compareto2.fs b/snippets/fsharp/System/Single/CompareTo/compareto2.fs new file mode 100644 index 00000000000..e097f734ffc --- /dev/null +++ b/snippets/fsharp/System/Single/CompareTo/compareto2.fs @@ -0,0 +1,13 @@ +module compareto2 + +// +let value1 = 16.5457f +let operand = 3.8899982f +let value2 = value1 * operand / operand +printfn $"Comparing {value1} and {value2}: {value1.CompareTo value2}\n" +printfn $"Comparing {value1:R} and {value2:R}: {value1.CompareTo value2}" +// The example displays the following output: +// Comparing 16.5457 and 16.5457: -1 +// +// Comparing 16.5457 and 16.545702: -1 +// \ No newline at end of file diff --git a/snippets/fsharp/System/Single/CompareTo/compareto3.fs b/snippets/fsharp/System/Single/CompareTo/compareto3.fs new file mode 100644 index 00000000000..d541c895f14 --- /dev/null +++ b/snippets/fsharp/System/Single/CompareTo/compareto3.fs @@ -0,0 +1,13 @@ +module compareto3 + +// +let value1 = 16.5457f +let operand = 3.8899982f +let value2 = box (value1 * operand / operand) +printfn $"Comparing {value1} and {value2}: {value1.CompareTo value2}\n" +printfn $"Comparing {value1:R} and {value2:R}: {value1.CompareTo value2}" +// The example displays the following output: +// Comparing 16.5457 and 16.5457: -1 +// +// Comparing 16.5457 and 16.545702: -1 +// \ No newline at end of file diff --git a/snippets/fsharp/System/Single/Epsilon/epsilon.fs b/snippets/fsharp/System/Single/Epsilon/epsilon.fs new file mode 100644 index 00000000000..ef10b674b18 --- /dev/null +++ b/snippets/fsharp/System/Single/Epsilon/epsilon.fs @@ -0,0 +1,17 @@ +module epsilon + +// +open System + +let values = [ 0f; Single.Epsilon; Single.Epsilon * 0.5f ] + +for i = 0 to values.Length - 2 do + for i2 = i + 1 to values.Length - 1 do + printfn $"{values[i]:r} = {values[i2]:r}: {values[i].Equals(values[i2])}" + printfn "" +// The example displays the following output: +// 0 = 1.401298E-45: False +// 0 = 0: True +// +// 1.401298E-45 = 0: False +// \ No newline at end of file diff --git a/snippets/fsharp/System/Single/Epsilon/epsilon1.fs b/snippets/fsharp/System/Single/Epsilon/epsilon1.fs new file mode 100644 index 00000000000..ae40c7d0c64 --- /dev/null +++ b/snippets/fsharp/System/Single/Epsilon/epsilon1.fs @@ -0,0 +1,44 @@ +module epsilon1 + +// +open System + +let getComponentParts (value: float32) = + let result = $"{value:R}: " + let indent = result.Length + + // Convert the single to a 4-byte array. + let bytes = BitConverter.GetBytes value + let formattedSingle = BitConverter.ToInt32(bytes, 0) + + // Get the sign bit (byte 3, bit 7). + let result = result + $"""Sign: {if formattedSingle >>> 31 <> 0 then "1 (-)" else "0 (+)"}\n""" + + // Get the exponent (byte 2 bit 7 to byte 3, bits 6) + let exponent = (formattedSingle >>> 23) &&& 0x000000FF + let adjustment = if exponent <> 0 then 127 else 126 + let result = result + $"{String(' ', indent)}Exponent: 0x{exponent - adjustment:X4} ({exponent - adjustment})\n" + + // Get the significand (bits 0-22) + let significand = + if exponent <> 0 then + (formattedSingle &&& 0x007FFFFF) ||| 0x800000 + else + formattedSingle &&& 0x007FFFFF + + result + $"{String(' ', indent)}Mantissa: 0x{significand:X13}\n" + + +let values = [ 0f; Single.Epsilon ] +for value in values do + printfn $"{getComponentParts value}\n" +// // The example displays the following output: +// 0: Sign: 0 (+) +// Exponent: 0xFFFFFF82 (-126) +// Mantissa: 0x0000000000000 +// +// +// 1.401298E-45: Sign: 0 (+) +// Exponent: 0xFFFFFF82 (-126) +// Mantissa: 0x0000000000001 +// diff --git a/snippets/fsharp/System/Single/Equals/equalsabs1.fs b/snippets/fsharp/System/Single/Equals/equalsabs1.fs new file mode 100644 index 00000000000..be7777d1a44 --- /dev/null +++ b/snippets/fsharp/System/Single/Equals/equalsabs1.fs @@ -0,0 +1,27 @@ +module equalsabs1 + +// +open System + +let hasMinimalDifference (value1: float32) (value2: float32) units = + let bytes = BitConverter.GetBytes value1 + let iValue1 = BitConverter.ToInt32(bytes, 0) + let bytes = BitConverter.GetBytes(value2) + let iValue2 = BitConverter.ToInt32(bytes, 0) + + // If the signs are different, return false except for +0 and -0. + if (iValue1 >>> 31) <> (iValue2 >>> 31) then + value1 = value2 + else + let diff = abs (iValue1 - iValue2) + diff <= units + +let value1 = 0.1f * 10f +let value2 = + List.replicate 10 0.1f + |> List.sum + +printfn $"{value1:R} = {value2:R}: {hasMinimalDifference value1 value2 1}" +// The example displays the following output: +// 1 = 1.0000001: True +// diff --git a/snippets/fsharp/System/String/.ctor/char2_ctor.fs b/snippets/fsharp/System/String/.ctor/char2_ctor.fs new file mode 100644 index 00000000000..159ab3913a0 --- /dev/null +++ b/snippets/fsharp/System/String/.ctor/char2_ctor.fs @@ -0,0 +1,29 @@ +module char2_ctor + +// +#nowarn "9" +open System +open FSharp.NativeInterop + +let characters = + [| 'H'; 'e'; 'l'; 'l'; 'o'; ' ' + 'w'; 'o'; 'r'; 'l'; 'd'; '!'; '\u0000' |] + +[] +let main _ = + use charPtr = fixed characters + let mutable length = 0 + let mutable iterator = charPtr + let mutable broken = false + while not broken && NativePtr.read iterator <> '\u0000' do + if NativePtr.read iterator = '!' || NativePtr.read iterator = '.' then + broken <- true + else + iterator <- NativePtr.add iterator 1 + length <- length + 1 + String(charPtr, 0, length) + |> printfn "%s" + 0 +// The example displays the following output: +// Hello World +// \ No newline at end of file diff --git a/snippets/fsharp/System/String/.ctor/chptrctor_null.fs b/snippets/fsharp/System/String/.ctor/chptrctor_null.fs new file mode 100644 index 00000000000..b973bca4ee7 --- /dev/null +++ b/snippets/fsharp/System/String/.ctor/chptrctor_null.fs @@ -0,0 +1,26 @@ +module chptrctor_null + +// +#nowarn "9" +open System + +let chars = [| 'a'; 'b'; 'c'; 'd'; '\000'; 'A'; 'B'; 'C'; 'D'; '\000' |] +let s = + use chPtr = fixed chars + String(chPtr, 0, chars.Length) + +for ch in s do + printf $"{uint16 ch:X4} " +printfn "" + +let s2 = + use chPtr = fixed chars + String chPtr + +for ch in s2 do + printf $"{uint16 ch:X4} " +printfn "" +// The example displays the following output: +// 0061 0062 0063 0064 0000 0041 0042 0043 0044 0000 +// 0061 0062 0063 0064 +// \ No newline at end of file diff --git a/snippets/fsharp/System/String/.ctor/ctor1.fs b/snippets/fsharp/System/String/.ctor/ctor1.fs new file mode 100644 index 00000000000..b44b9bb30d6 --- /dev/null +++ b/snippets/fsharp/System/String/.ctor/ctor1.fs @@ -0,0 +1,11 @@ +module ctor1 + +// +let value1 = "This is a string." +let value2 = value1 +printfn "%s" value1 +printfn "%s" value2 +// The example displays the following output: +// This is a string. +// This is a string. +// \ No newline at end of file diff --git a/snippets/fsharp/System/String/.ctor/ctor2.fs b/snippets/fsharp/System/String/.ctor/ctor2.fs new file mode 100644 index 00000000000..1042312649a --- /dev/null +++ b/snippets/fsharp/System/String/.ctor/ctor2.fs @@ -0,0 +1,18 @@ +module ctor2 + +// +#nowarn "9" +open System + +let characters = + [| 'H'; 'e'; 'l'; 'l'; 'o'; ' ' + 'w'; 'o'; 'r'; 'l'; 'd'; '!'; '\u0000' |] + +let value = + use charPtr = fixed characters + String charPtr + +printfn $"{value}" +// The example displays the following output: +// Hello world! +// \ No newline at end of file diff --git a/snippets/fsharp/System/String/.ctor/ptrctor_null.fs b/snippets/fsharp/System/String/.ctor/ptrctor_null.fs new file mode 100644 index 00000000000..e3753c593e0 --- /dev/null +++ b/snippets/fsharp/System/String/.ctor/ptrctor_null.fs @@ -0,0 +1,28 @@ +module ptrctor_null + +// +#nowarn "9" +open System + +let bytes = + [| 0x61y; 0x62y; 0x063y; 0x064y; 0x00y; 0x41y; 0x42y; 0x43y; 0x44y; 0x00y |] + +let s = + use bytePtr = fixed bytes + String(bytePtr, 0, bytes.Length) + +for ch in s do + printf $"{uint16 ch:X4} " +printfn "" + +let s2 = + use bytePtr = fixed bytes + String bytePtr + +for ch in s do + printf $"{uint16 ch:X4} " +printfn "" +// The example displays the following output: +// 0061 0062 0063 0064 0000 0041 0042 0043 0044 0000 +// 0061 0062 0063 0064 +// \ No newline at end of file diff --git a/snippets/fsharp/System/String/.ctor/source.fs b/snippets/fsharp/System/String/.ctor/source.fs new file mode 100644 index 00000000000..017dbeeaaba --- /dev/null +++ b/snippets/fsharp/System/String/.ctor/source.fs @@ -0,0 +1,70 @@ +module source + +open System +open System.Text + +do +// + // Unicode Mathematical operators + let charArr1 = [| '\u2200'; '\u2202'; '\u200F'; '\u2205' |] + let szMathSymbols = String charArr1 + + // Unicode Letterlike Symbols + let charArr2 = [| '\u2111'; '\u2118'; '\u2122'; '\u2126' |] + let szLetterLike = String charArr2 + + // Compare Strings - the result is false + printfn $"The Strings are equal? %b{String.Compare(szMathSymbols, szLetterLike) = 0}" +// +// + // Null terminated ASCII characters in an sbyte array + let szAsciiUpper = + let sbArr1 = [| 0x41y; 0x42y; 0x43y; 0x00y |] + // Instruct the Garbage Collector not to move the memory + use pAsciiUpper = fixed sbArr1 + String pAsciiUpper + + let szAsciiLower = + let sbArr2 = [| 0x61y; 0x62y; 0x63y; 0x00y |] + // Instruct the Garbage Collector not to move the memory + use pAsciiLower = fixed sbArr2 + String(pAsciiLower, 0, sbArr2.Length) + + // Prints "ABC abc" + printfn $"{szAsciiUpper} {szAsciiLower}" + + // Compare Strings - the result is true + printfn $"The Strings are equal when capitalized ? %b{String.Compare(szAsciiUpper.ToUpper(), szAsciiLower.ToUpper()) = 0}" + + // This is the effective equivalent of another Compare method, which ignores case + printfn $"The Strings are equal when capitalized ? %b{String.Compare(szAsciiUpper, szAsciiLower, true) = 0}" +// +// + // Create a Unicode String with 5 Greek Alpha characters + let szGreekAlpha = String('\u0391',5) + // Create a Unicode String with a Greek Omega character + let szGreekOmega = String([| '\u03A9'; '\u03A9'; '\u03A9' |],2,1) + + let szGreekLetters = String.Concat(szGreekOmega, szGreekAlpha, szGreekOmega.Clone()) + + // Examine the result + printfn $"{szGreekLetters}" + + // The first index of Alpha + let ialpha = szGreekLetters.IndexOf '\u0391' + // The last index of Omega + let iomega = szGreekLetters.LastIndexOf '\u03A9' + + printfn $"The Greek letter Alpha first appears at index {ialpha} and Omega last appears at index {iomega} in this String." +// + +// + let utfeightstring = + let asciiChars = [| 0x51y; 0x52y; 0x53y; 0x54y; 0x54y; 0x56y |] + let encoding = UTF8Encoding(true, true) + + // Instruct the Garbage Collector not to move the memory + use pAsciiChars = fixed asciiChars + String(pAsciiChars,0,asciiChars.Length,encoding) + printfn $"The UTF8 String is {utfeightstring}" // prints "QRSTTV" +// \ No newline at end of file diff --git a/snippets/fsharp/System/String/Format/Example1.fs b/snippets/fsharp/System/String/Format/Example1.fs new file mode 100644 index 00000000000..6f76849429c --- /dev/null +++ b/snippets/fsharp/System/String/Format/Example1.fs @@ -0,0 +1,19 @@ +module Example1 + +// +open System + +let values= [| Int16.MinValue; -27s; 0s; 1042s; Int16.MaxValue |] +printfn "%10s %10s\n" "Decimal" "Hex" +for value in values do + String.Format("{0,10:G}: {0,10:X}", value) + |> printfn "%s" +// The example displays the following output: +// Decimal Hex +// +// -32768: 8000 +// -27: FFE5 +// 0: 0 +// 1042: 412 +// 32767: 7FFF +// \ No newline at end of file diff --git a/snippets/fsharp/System/String/Intern/Intern1.fs b/snippets/fsharp/System/String/Intern/Intern1.fs new file mode 100644 index 00000000000..8443ea61d61 --- /dev/null +++ b/snippets/fsharp/System/String/Intern/Intern1.fs @@ -0,0 +1,11 @@ +module Intern1.fs +open System +open System.Text + +// +let s1 = "MyTest" +let s2 = StringBuilder().Append("My").Append("Test").ToString() +let s3 = String.Intern s2 +printfn $"{s2 :> obj = s1 :> obj}" // Different references. +printfn $"{s3 :> obj = s1 :> obj}" // The same reference. +// diff --git a/snippets/fsharp/System/String/Intern/fs.fsproj b/snippets/fsharp/System/String/Intern/fs.fsproj index 6d494f6fa40..b7ebb91ff77 100644 --- a/snippets/fsharp/System/String/Intern/fs.fsproj +++ b/snippets/fsharp/System/String/Intern/fs.fsproj @@ -6,5 +6,6 @@ + diff --git a/snippets/fsharp/System/String/IsNullOrEmpty/NullString1.fs b/snippets/fsharp/System/String/IsNullOrEmpty/NullString1.fs new file mode 100644 index 00000000000..21f1ee3462c --- /dev/null +++ b/snippets/fsharp/System/String/IsNullOrEmpty/NullString1.fs @@ -0,0 +1,19 @@ +namespace IsNullOrEmpty +open System + +module NullString1 = + + // + let (s: string) = null + + printfn "The value of the string is '%s'" s + + try + printfn "String length is %d" s.Length + with + | :? NullReferenceException as ex -> printfn "%s" ex.Message + + // The example displays the following output: + // The value of the string is '' + // Object reference not set to an instance of an object. + // diff --git a/snippets/fsharp/System/String/IsNullOrEmpty/NullString2.fs b/snippets/fsharp/System/String/IsNullOrEmpty/NullString2.fs new file mode 100644 index 00000000000..d8c8fad9c8c --- /dev/null +++ b/snippets/fsharp/System/String/IsNullOrEmpty/NullString2.fs @@ -0,0 +1,12 @@ +namespace IsNullOrEmpty +open System + +module NullString2 = + + // + let s = "" + printfn "The length of '%s' is %d." s s.Length + + // The example displays the following output: + // The length of '' is 0. + // diff --git a/snippets/fsharp/System/String/IsNullOrEmpty/isnullorempty1.fs b/snippets/fsharp/System/String/IsNullOrEmpty/isnullorempty1.fs new file mode 100644 index 00000000000..7f4e29126fe --- /dev/null +++ b/snippets/fsharp/System/String/IsNullOrEmpty/isnullorempty1.fs @@ -0,0 +1,19 @@ +namespace IsNullOrEmpty +open System + +module IsNullOrEmpty1 = + + // + let testForNullOrEmpty (s: string): bool = + s = null || s = String.Empty + + let s1 = null + let s2 = "" + + printfn "%b" (testForNullOrEmpty s1) + printfn "%b" (testForNullOrEmpty s2) + + // The example displays the following output: + // true + // true + // diff --git a/snippets/fsharp/System/TimeSpan/Overview/fs.fsproj b/snippets/fsharp/System/TimeSpan/Overview/fs.fsproj index 575e4fe0f4e..90dd1791048 100644 --- a/snippets/fsharp/System/TimeSpan/Overview/fs.fsproj +++ b/snippets/fsharp/System/TimeSpan/Overview/fs.fsproj @@ -7,9 +7,6 @@ - - - - \ No newline at end of file + diff --git a/snippets/fsharp/System/TimeSpan/Overview/legacycode1.fs b/snippets/fsharp/System/TimeSpan/Overview/legacycode1.fs deleted file mode 100644 index 69be56c0f5a..00000000000 --- a/snippets/fsharp/System/TimeSpan/Overview/legacycode1.fs +++ /dev/null @@ -1,37 +0,0 @@ -module legacycode1 - -open System - -// -let showFormattingCode () = - let interval = TimeSpan(12, 30, 45) - try - $"{interval:r}" - with :? FormatException -> - "Invalid Format" - |> printfn "%s" - -let showParsingCode () = - let value = "000000006" - try - let interval = TimeSpan.Parse value - printfn $"{value} --> {interval}" - with - | :? FormatException -> - printfn $"{value}: Bad Format" - | :? OverflowException -> - printfn $"{value}: Overflow" - -showFormattingCode () -// Output from .NET Framework 3.5 and earlier versions: -// 12:30:45 -// Output from .NET Framework 4: -// Invalid Format - -printfn "---" - -showParsingCode () -// Output: -// 000000006 --> 6.00:00:00 - -// \ No newline at end of file diff --git a/snippets/fsharp/System/TimeSpan/Overview/perappdomain1.fs b/snippets/fsharp/System/TimeSpan/Overview/perappdomain1.fs deleted file mode 100644 index a0c611ba3ce..00000000000 --- a/snippets/fsharp/System/TimeSpan/Overview/perappdomain1.fs +++ /dev/null @@ -1,10 +0,0 @@ -module perappdomain1 - -// -open System - -let appSetup = AppDomainSetup() -appSetup.SetCompatibilitySwitches [| "NetFx40_TimeSpanLegacyFormatMode" |] -let legacyDomain = AppDomain.CreateDomain("legacyDomain", null, appSetup) -legacyDomain.ExecuteAssembly "ShowTimeSpan.exe" |> ignore -// \ No newline at end of file diff --git a/snippets/fsharp/System/TimeSpan/Overview/showtimespan.fs b/snippets/fsharp/System/TimeSpan/Overview/showtimespan.fs deleted file mode 100644 index 7c0fa6da583..00000000000 --- a/snippets/fsharp/System/TimeSpan/Overview/showtimespan.fs +++ /dev/null @@ -1,10 +0,0 @@ -module showtimespan - -// -open System - -let interval = DateTime.Now - DateTime.Now.Date -printfn $"Elapsed Time Today: {interval:d} hours." -// The example displays the following output: -// Elapsed Time Today: 01:40:52.2524662 hours. -// \ No newline at end of file diff --git a/snippets/fsharp/System/TimeSpan/Parse/parsefailure1.fs b/snippets/fsharp/System/TimeSpan/Parse/parsefailure1.fs new file mode 100644 index 00000000000..54ff371765d --- /dev/null +++ b/snippets/fsharp/System/TimeSpan/Parse/parsefailure1.fs @@ -0,0 +1,23 @@ +module parsefailure1 + +// +open System + +let values = [| "000000006"; "12.12:12:12.12345678" |] +for value in values do + try + let interval = TimeSpan.Parse value + printfn $"{value} --> {interval}" + with + | :? FormatException -> + printfn $"{value}: Bad Format" + | :? OverflowException -> + printfn $"{value}: Overflow" + +// Output from .NET Framework 3.5 and earlier versions: +// 000000006 --> 6.00:00:00 +// 12.12:12:12.12345678: Bad Format +// Output from .NET Framework 4 and later versions or .NET Core: +// 000000006: Overflow +// 12.12:12:12.12345678: Overflow +// \ No newline at end of file diff --git a/snippets/fsharp/System/Type/GetType/source.fs b/snippets/fsharp/System/Type/GetType/source.fs new file mode 100644 index 00000000000..9ec4c202801 --- /dev/null +++ b/snippets/fsharp/System/Type/GetType/source.fs @@ -0,0 +1,37 @@ +module source + +open System +open System.Reflection + +do + let test = "System.Collections.Generic.Dictionary`2[System.String,[MyNamespace.MyType, MyAssembly]]" + // + let t = + Type.GetType(test, + (fun aName -> + if aName.Name = "MyAssembly" then + Assembly.LoadFrom @".\MyPath\v5.0\MyAssembly.dll" + else null), + fun assem name ignr -> + if assem = null then + Type.GetType(name, false, ignr) + else + assem.GetType(name, false, ignr)) + // + printfn $"{t}" + + let test = "System.Collections.Generic.Dictionary`2[[YourNamespace.YourType, YourAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null], [MyNamespace.MyType, MyAssembly]]" + // + let t2 = + Type.GetType(test, + (fun aName -> + if aName.Name = "MyAssembly" then + Assembly.LoadFrom @".\MyPath\v5.0\MyAssembly.dll" + else Assembly.Load aName), + (fun assem name ignr -> + if assem = null then + Type.GetType(name, false, ignr) + else + assem.GetType(name, false, ignr)), true) + // + printfn $"{t2}" diff --git a/snippets/fsharp/System/Type/MakeGenericType/remarks.fs b/snippets/fsharp/System/Type/MakeGenericType/remarks.fs new file mode 100644 index 00000000000..bece475149a --- /dev/null +++ b/snippets/fsharp/System/Type/MakeGenericType/remarks.fs @@ -0,0 +1,5 @@ +module remarks +// +type Base<'T, 'U>() = class end +type Derived<'V>() = inherit Base() +// diff --git a/snippets/fsharp/System/Version/Overview/fs.fsproj b/snippets/fsharp/System/Version/Overview/fs.fsproj index 301ed38758c..847eb1a60c8 100644 --- a/snippets/fsharp/System/Version/Overview/fs.fsproj +++ b/snippets/fsharp/System/Version/Overview/fs.fsproj @@ -8,9 +8,8 @@ - - \ No newline at end of file + diff --git a/snippets/fsharp/System/Version/Overview/specificassem.fs b/snippets/fsharp/System/Version/Overview/specificassem.fs deleted file mode 100644 index f930a4460da..00000000000 --- a/snippets/fsharp/System/Version/Overview/specificassem.fs +++ /dev/null @@ -1,12 +0,0 @@ -module specificassem - -// -open System.Reflection - -// Get the version of a specific assembly. -let filename = @".\StringLibrary.dll" -let assem = Assembly.ReflectionOnlyLoadFrom filename -let assemName = assem.GetName() -let ver = assemName.Version -printfn $"{assemName.Name}, Version {ver}" -// \ No newline at end of file diff --git a/snippets/visualbasic/System/Double/Overview/Project.vbproj b/snippets/visualbasic/System/Double/Overview/Project.vbproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/visualbasic/System/Double/Overview/Project.vbproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/visualbasic/System/Double/Overview/precisionlist1.vb b/snippets/visualbasic/System/Double/Overview/precisionlist1.vb new file mode 100644 index 00000000000..efbde3e8e96 --- /dev/null +++ b/snippets/visualbasic/System/Double/Overview/precisionlist1.vb @@ -0,0 +1,15 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example10 + Public Sub Main() + Dim value1 As Double = 1 / 3 + Dim sValue2 As Single = 1 / 3 + Dim value2 As Double = CDbl(sValue2) + Console.WriteLine("{0} = {1}: {2}", value1, value2, value1.Equals(value2)) + End Sub +End Module +' The example displays the following output: +' 0.33333333333333331 = 0.3333333432674408: False +' diff --git a/snippets/visualbasic/System/Random/Overview/Project.vbproj b/snippets/visualbasic/System/Random/Overview/Project.vbproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/visualbasic/System/Random/Overview/Project.vbproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/visualbasic/System/Random/Overview/Random1.vb b/snippets/visualbasic/System/Random/Overview/Random1.vb new file mode 100644 index 00000000000..997827ecf77 --- /dev/null +++ b/snippets/visualbasic/System/Random/Overview/Random1.vb @@ -0,0 +1,55 @@ +' Visual Basic .NET Document +Option Strict On + +'Imports System.Threading + +' +Module modMain + + Public Sub Main() + Dim bytes1(99), bytes2(99) As Byte + Dim rnd1 As New Random() + Dim rnd2 As New Random() + + rnd1.NextBytes(bytes1) + rnd2.NextBytes(bytes2) + + Console.WriteLine("First Series:") + For ctr As Integer = bytes1.GetLowerBound(0) to bytes1.GetUpperBound(0) + Console.Write("{0, 5}", bytes1(ctr)) + If (ctr + 1) Mod 10 = 0 Then Console.WriteLine() + Next + Console.WriteLine() + Console.WriteLine("Second Series:") + For ctr As Integer = bytes2.GetLowerBound(0) to bytes2.GetUpperBound(0) + Console.Write("{0, 5}", bytes2(ctr)) + If (ctr + 1) Mod 10 = 0 Then Console.WriteLine() + Next + End Sub +End Module +' The example displays output like the following: +' First Series: +' 97 129 149 54 22 208 120 105 68 177 +' 113 214 30 172 74 218 116 230 89 18 +' 12 112 130 105 116 180 190 200 187 120 +' 7 198 233 158 58 51 50 170 98 23 +' 21 1 113 74 146 245 34 255 96 24 +' 232 255 23 9 167 240 255 44 194 98 +' 18 175 173 204 169 171 236 127 114 23 +' 167 202 132 65 253 11 254 56 214 127 +' 145 191 104 163 143 7 174 224 247 73 +' 52 6 231 255 5 101 83 165 160 231 +' +' Second Series: +' 97 129 149 54 22 208 120 105 68 177 +' 113 214 30 172 74 218 116 230 89 18 +' 12 112 130 105 116 180 190 200 187 120 +' 7 198 233 158 58 51 50 170 98 23 +' 21 1 113 74 146 245 34 255 96 24 +' 232 255 23 9 167 240 255 44 194 98 +' 18 175 173 204 169 171 236 127 114 23 +' 167 202 132 65 253 11 254 56 214 127 +' 145 191 104 163 143 7 174 224 247 73 +' 52 6 231 255 5 101 83 165 160 231 +' + diff --git a/snippets/visualbasic/System/Random/Overview/Random2.vb b/snippets/visualbasic/System/Random/Overview/Random2.vb index 8d5de19cef6..a165a36d04e 100644 --- a/snippets/visualbasic/System/Random/Overview/Random2.vb +++ b/snippets/visualbasic/System/Random/Overview/Random2.vb @@ -2,48 +2,48 @@ Option Strict On ' -Module Example - Public Sub Main() - ' Instantiate random number generator using system-supplied value as seed. - Dim rand As New Random() - ' Generate and display 5 random byte (integer) values. - Dim bytes(4) As Byte - rand.NextBytes(bytes) - Console.WriteLine("Five random byte values:") - For Each byteValue As Byte In bytes - Console.Write("{0, 5}", byteValue) - Next - Console.WriteLine() - ' Generate and display 5 random integers. - Console.WriteLine("Five random integer values:") - For ctr As Integer = 0 To 4 - Console.Write("{0,15:N0}", rand.Next) - Next - Console.WriteLine() - ' Generate and display 5 random integers between 0 and 100.' - Console.WriteLine("Five random integers between 0 and 100:") - For ctr As Integer = 0 To 4 - Console.Write("{0,8:N0}", rand.Next(101)) - Next - Console.WriteLine() - ' Generate and display 5 random integers from 50 to 100. - Console.WriteLine("Five random integers between 50 and 100:") - For ctr As Integer = 0 To 4 - Console.Write("{0,8:N0}", rand.Next(50, 101)) - Next - Console.WriteLine() - ' Generate and display 5 random floating point values from 0 to 1. - Console.WriteLine("Five Doubles.") - For ctr As Integer = 0 To 4 - Console.Write("{0,8:N3}", rand.NextDouble()) - Next - Console.WriteLine() - ' Generate and display 5 random floating point values from 0 to 5. - Console.WriteLine("Five Doubles between 0 and 5.") - For ctr As Integer = 0 To 4 - Console.Write("{0,8:N3}", rand.NextDouble() * 5) - Next - End Sub +Module RandomExample2 + Public Sub Main() + ' Instantiate random number generator using system-supplied value as seed. + Dim rand As New Random() + ' Generate and display 5 random byte (integer) values. + Dim bytes(4) As Byte + rand.NextBytes(bytes) + Console.WriteLine("Five random byte values:") + For Each byteValue As Byte In bytes + Console.Write("{0, 5}", byteValue) + Next + Console.WriteLine() + ' Generate and display 5 random integers. + Console.WriteLine("Five random integer values:") + For ctr As Integer = 0 To 4 + Console.Write("{0,15:N0}", rand.Next) + Next + Console.WriteLine() + ' Generate and display 5 random integers between 0 and 100.' + Console.WriteLine("Five random integers between 0 and 100:") + For ctr As Integer = 0 To 4 + Console.Write("{0,8:N0}", rand.Next(101)) + Next + Console.WriteLine() + ' Generate and display 5 random integers from 50 to 100. + Console.WriteLine("Five random integers between 50 and 100:") + For ctr As Integer = 0 To 4 + Console.Write("{0,8:N0}", rand.Next(50, 101)) + Next + Console.WriteLine() + ' Generate and display 5 random floating point values from 0 to 1. + Console.WriteLine("Five Doubles.") + For ctr As Integer = 0 To 4 + Console.Write("{0,8:N3}", rand.NextDouble()) + Next + Console.WriteLine() + ' Generate and display 5 random floating point values from 0 to 5. + Console.WriteLine("Five Doubles between 0 and 5.") + For ctr As Integer = 0 To 4 + Console.Write("{0,8:N3}", rand.NextDouble() * 5) + Next + End Sub End Module ' The example displays output like the following: ' Five random byte values: diff --git a/snippets/visualbasic/System/Random/Overview/array1.vb b/snippets/visualbasic/System/Random/Overview/array1.vb new file mode 100644 index 00000000000..1e229ea93a4 --- /dev/null +++ b/snippets/visualbasic/System/Random/Overview/array1.vb @@ -0,0 +1,20 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example1 + Public Sub Main() + Dim cities() As String = {"Atlanta", "Boston", "Chicago", "Detroit", + "Fort Wayne", "Greensboro", "Honolulu", "Indianapolis", + "Jersey City", "Kansas City", "Los Angeles", + "Milwaukee", "New York", "Omaha", "Philadelphia", + "Raleigh", "San Francisco", "Tulsa", "Washington"} + Dim rnd As New Random() + Dim index As Integer = rnd.Next(0, cities.Length) + Console.WriteLine("Today's city of the day: {0}", + cities(index)) + End Sub +End Module +' The example displays output like the following: +' Today's city of the day: Honolulu +' diff --git a/snippets/visualbasic/System/Random/Overview/booleans1.vb b/snippets/visualbasic/System/Random/Overview/booleans1.vb new file mode 100644 index 00000000000..5f9c954af26 --- /dev/null +++ b/snippets/visualbasic/System/Random/Overview/booleans1.vb @@ -0,0 +1,43 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example2 + Public Sub Main() + ' Instantiate the Boolean generator. + Dim boolGen As New BooleanGenerator() + Dim totalTrue, totalFalse As Integer + + ' Generate 1,0000 random Booleans, and keep a running total. + For ctr As Integer = 0 To 9999999 + Dim value As Boolean = boolGen.NextBoolean() + If value Then + totalTrue += 1 + Else + totalFalse += 1 + End If + Next + Console.WriteLine("Number of true values: {0,7:N0} ({1:P3})", + totalTrue, + totalTrue / (totalTrue + totalFalse)) + Console.WriteLine("Number of false values: {0,7:N0} ({1:P3})", + totalFalse, + totalFalse / (totalTrue + totalFalse)) + End Sub +End Module + +Public Class BooleanGenerator + Dim rnd As Random + + Public Sub New() + rnd = New Random() + End Sub + + Public Function NextBoolean() As Boolean + Return Convert.ToBoolean(rnd.Next(0, 2)) + End Function +End Class +' The example displays the following output: +' Number of true values: 500,004 (50.000 %) +' Number of false values: 499,996 (50.000 %) +' diff --git a/snippets/visualbasic/System/Random/Overview/booleans2.vb b/snippets/visualbasic/System/Random/Overview/booleans2.vb new file mode 100644 index 00000000000..7d6de5554e5 --- /dev/null +++ b/snippets/visualbasic/System/Random/Overview/booleans2.vb @@ -0,0 +1,34 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example3 + Public Sub Main() + Dim totalTrue, totalFalse As Integer + + ' Generate 1,0000 random Booleans, and keep a running total. + For ctr As Integer = 0 To 9999999 + Dim value As Boolean = NextBoolean() + If value Then + totalTrue += 1 + Else + totalFalse += 1 + End If + Next + Console.WriteLine("Number of true values: {0,7:N0} ({1:P3})", + totalTrue, + totalTrue / (totalTrue + totalFalse)) + Console.WriteLine("Number of false values: {0,7:N0} ({1:P3})", + totalFalse, + totalFalse / (totalTrue + totalFalse)) + End Sub + + Public Function NextBoolean() As Boolean + Static rnd As New Random() + Return Convert.ToBoolean(rnd.Next(0, 2)) + End Function +End Module +' The example displays the following output: +' Number of true values: 499,777 (49.978 %) +' Number of false values: 500,223 (50.022 %) +' diff --git a/snippets/visualbasic/System/Random/Overview/bytes1.vb b/snippets/visualbasic/System/Random/Overview/bytes1.vb new file mode 100644 index 00000000000..0aac57c768a --- /dev/null +++ b/snippets/visualbasic/System/Random/Overview/bytes1.vb @@ -0,0 +1,64 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example4 + Public Sub Main() + Dim rnd As New Random2() + Dim bytes(9999) As Byte + Dim total(100) As Integer + rnd.NextBytes(bytes, 0, 101) + + ' Calculate how many of each value we have. + For Each value In bytes + total(value) += 1 + Next + + ' Display the results. + For ctr As Integer = 0 To total.Length - 1 + Console.Write("{0,3}: {1,-3} ", ctr, total(ctr)) + If (ctr + 1) Mod 5 = 0 Then Console.WriteLine() + Next + End Sub +End Module + +Public Class Random2 : Inherits Random + Public Sub New() + MyBase.New() + End Sub + + Public Sub New(seed As Integer) + MyBase.New(seed) + End Sub + + Public Overloads Sub NextBytes(bytes() As Byte, + minValue As Byte, maxValue As Byte) + For ctr As Integer = bytes.GetLowerbound(0) To bytes.GetUpperBound(0) + bytes(ctr) = CByte(MyBase.Next(minValue, maxValue)) + Next + End Sub +End Class +' The example displays output like the following: +' 0: 115 1: 119 2: 92 3: 98 4: 92 +' 5: 102 6: 103 7: 84 8: 93 9: 116 +' 10: 91 11: 98 12: 106 13: 91 14: 92 +' 15: 101 16: 100 17: 96 18: 97 19: 100 +' 20: 101 21: 106 22: 112 23: 82 24: 85 +' 25: 102 26: 107 27: 98 28: 106 29: 102 +' 30: 109 31: 108 32: 94 33: 101 34: 107 +' 35: 101 36: 86 37: 100 38: 101 39: 102 +' 40: 113 41: 95 42: 96 43: 89 44: 99 +' 45: 81 46: 89 47: 105 48: 100 49: 85 +' 50: 103 51: 103 52: 93 53: 89 54: 91 +' 55: 97 56: 105 57: 97 58: 110 59: 86 +' 60: 116 61: 94 62: 117 63: 98 64: 110 +' 65: 93 66: 102 67: 100 68: 105 69: 83 +' 70: 81 71: 97 72: 85 73: 70 74: 98 +' 75: 100 76: 110 77: 114 78: 83 79: 90 +' 80: 96 81: 112 82: 102 83: 102 84: 99 +' 85: 81 86: 100 87: 93 88: 99 89: 118 +' 90: 95 91: 124 92: 108 93: 96 94: 104 +' 95: 106 96: 99 97: 99 98: 92 99: 99 +' 100: 108 +' + diff --git a/snippets/visualbasic/System/Random/Overview/doublerange1.vb b/snippets/visualbasic/System/Random/Overview/doublerange1.vb new file mode 100644 index 00000000000..86f6298c6c3 --- /dev/null +++ b/snippets/visualbasic/System/Random/Overview/doublerange1.vb @@ -0,0 +1,42 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example5 + Public Sub Main() + Const ONE_TENTH As Long = 922337203685477581 + + Dim rnd As New Random() + Dim number As Long + Dim count(9) As Integer + + ' Generate 20 million integer values. + For ctr As Integer = 1 To 20000000 + number = CLng(rnd.NextDouble() * Int64.MaxValue) + ' Categorize random numbers. + count(CInt(number \ ONE_TENTH)) += 1 + Next + ' Display breakdown by range. + Console.WriteLine("{0,28} {1,32} {2,7}", "Range", "Count", "Pct.") + Console.WriteLine() + For ctr As Integer = 0 To 9 + Console.WriteLine("{0,25:N0}-{1,25:N0} {2,8:N0} {3,7:P2}", ctr * ONE_TENTH, + If(ctr < 9, ctr * ONE_TENTH + ONE_TENTH - 1, Int64.MaxValue), + count(ctr), count(ctr) / 20000000) + Next + End Sub +End Module +' The example displays output like the following: +' Range Count Pct. +' +' 0- 922,337,203,685,477,580 1,996,148 9.98 % +' 922,337,203,685,477,581-1,844,674,407,370,955,161 2,000,293 10.00 % +' 1,844,674,407,370,955,162-2,767,011,611,056,432,742 2,000,094 10.00 % +' 2,767,011,611,056,432,743-3,689,348,814,741,910,323 2,000,159 10.00 % +' 3,689,348,814,741,910,324-4,611,686,018,427,387,904 1,999,552 10.00 % +' 4,611,686,018,427,387,905-5,534,023,222,112,865,485 1,998,248 9.99 % +' 5,534,023,222,112,865,486-6,456,360,425,798,343,066 2,000,696 10.00 % +' 6,456,360,425,798,343,067-7,378,697,629,483,820,647 2,001,637 10.01 % +' 7,378,697,629,483,820,648-8,301,034,833,169,298,228 2,002,870 10.01 % +' 8,301,034,833,169,298,229-9,223,372,036,854,775,807 2,000,303 10.00 % +' diff --git a/snippets/visualbasic/System/Random/Overview/doublerange2.vb b/snippets/visualbasic/System/Random/Overview/doublerange2.vb new file mode 100644 index 00000000000..9ece828201a --- /dev/null +++ b/snippets/visualbasic/System/Random/Overview/doublerange2.vb @@ -0,0 +1,24 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example6 + Public Sub Main() + Dim rnd As New Random() + For ctr As Integer = 1 To 10 + Console.WriteLine(rnd.NextDouble() - 1) + Next + End Sub +End Module +' The example displays output like the following: +' -0.930412760437658 +' -0.164699016215605 +' -0.9851692803135 +' -0.43468508843085 +' -0.177202483255976 +' -0.776813320245972 +' -0.0713201854710096 +' -0.0912875561468711 +' -0.540621722368813 +' -0.232211863730201 +' diff --git a/snippets/visualbasic/System/Random/Overview/doublerange3.vb b/snippets/visualbasic/System/Random/Overview/doublerange3.vb new file mode 100644 index 00000000000..0a6c9701504 --- /dev/null +++ b/snippets/visualbasic/System/Random/Overview/doublerange3.vb @@ -0,0 +1,36 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example7 + Public Sub Main() + Dim rnd As New Random() + Dim lowerBound As Integer = 10 + Dim upperBound As Integer = 11 + Dim range(9) As Integer + For ctr As Integer = 1 To 1000000 + Dim value As Double = rnd.NextDouble() * (upperBound - lowerBound) + lowerBound + range(CInt(Math.Truncate((value - lowerBound) * 10))) += 1 + Next + + For ctr As Integer = 0 To 9 + Dim lowerRange As Double = 10 + ctr * 0.1 + Console.WriteLine("{0:N1} to {1:N1}: {2,8:N0} ({3,7:P2})", + lowerRange, lowerRange + 0.1, range(ctr), + range(ctr) / 1000000.0) + Next + End Sub +End Module +' The example displays output like the following: +' 10.0 to 10.1: 99,929 ( 9.99 %) +' 10.1 to 10.2: 100,189 (10.02 %) +' 10.2 to 10.3: 99,384 ( 9.94 %) +' 10.3 to 10.4: 100,240 (10.02 %) +' 10.4 to 10.5: 99,397 ( 9.94 %) +' 10.5 to 10.6: 100,580 (10.06 %) +' 10.6 to 10.7: 100,293 (10.03 %) +' 10.7 to 10.8: 100,135 (10.01 %) +' 10.8 to 10.9: 99,905 ( 9.99 %) +' 10.9 to 11.0: 99,948 ( 9.99 %) +' + diff --git a/snippets/visualbasic/System/Random/Overview/long1.vb b/snippets/visualbasic/System/Random/Overview/long1.vb new file mode 100644 index 00000000000..5123939faf9 --- /dev/null +++ b/snippets/visualbasic/System/Random/Overview/long1.vb @@ -0,0 +1,42 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example8 + Public Sub Main() + Const ONE_TENTH As Long = 922337203685477581 + + Dim rnd As New Random() + Dim number As Long + Dim count(9) As Integer + + ' Generate 20 million long integers. + For ctr As Integer = 1 To 20000000 + number = CLng(rnd.NextDouble() * Int64.MaxValue) + ' Categorize random numbers. + count(CInt(number \ ONE_TENTH)) += 1 + Next + ' Display breakdown by range. + Console.WriteLine("{0,28} {1,32} {2,7}", "Range", "Count", "Pct.") + Console.WriteLine() + For ctr As Integer = 0 To 9 + Console.WriteLine("{0,25:N0}-{1,25:N0} {2,8:N0} {3,7:P2}", ctr * ONE_TENTH, + If(ctr < 9, ctr * ONE_TENTH + ONE_TENTH - 1, Int64.MaxValue), + count(ctr), count(ctr) / 20000000) + Next + End Sub +End Module +' The example displays output like the following: +' Range Count Pct. +' +' 0- 922,337,203,685,477,580 1,996,148 9.98 % +' 922,337,203,685,477,581-1,844,674,407,370,955,161 2,000,293 10.00 % +' 1,844,674,407,370,955,162-2,767,011,611,056,432,742 2,000,094 10.00 % +' 2,767,011,611,056,432,743-3,689,348,814,741,910,323 2,000,159 10.00 % +' 3,689,348,814,741,910,324-4,611,686,018,427,387,904 1,999,552 10.00 % +' 4,611,686,018,427,387,905-5,534,023,222,112,865,485 1,998,248 9.99 % +' 5,534,023,222,112,865,486-6,456,360,425,798,343,066 2,000,696 10.00 % +' 6,456,360,425,798,343,067-7,378,697,629,483,820,647 2,001,637 10.01 % +' 7,378,697,629,483,820,648-8,301,034,833,169,298,228 2,002,870 10.01 % +' 8,301,034,833,169,298,229-9,223,372,036,854,775,807 2,000,303 10.00 % +' diff --git a/snippets/visualbasic/System/Random/Overview/next2.vb b/snippets/visualbasic/System/Random/Overview/next2.vb index fe358629f8c..74fce58aa35 100644 --- a/snippets/visualbasic/System/Random/Overview/next2.vb +++ b/snippets/visualbasic/System/Random/Overview/next2.vb @@ -2,30 +2,30 @@ Option Strict On ' -Module Example - Public Sub Main() - Dim rnd As New Random() +Module NextExample2 + Public Sub Main() + Dim rnd As New Random() - Console.WriteLine("20 random integers from -100 to 100:") - For ctr As Integer = 1 To 20 - Console.Write("{0,6}", rnd.Next(-100, 101)) - If ctr Mod 5 = 0 Then Console.WriteLine() - Next - Console.WriteLine() - - Console.WriteLine("20 random integers from 1000 to 10000:") - For ctr As Integer = 1 To 20 - Console.Write("{0,8}", rnd.Next(1000, 10001)) - If ctr Mod 5 = 0 Then Console.WriteLine() - Next - Console.WriteLine() - - Console.WriteLine("20 random integers from 1 to 10:") - For ctr As Integer = 1 To 20 - Console.Write("{0,6}", rnd.Next(1, 11)) - If ctr Mod 5 = 0 Then Console.WriteLine() - Next - End Sub + Console.WriteLine("20 random integers from -100 to 100:") + For ctr As Integer = 1 To 20 + Console.Write("{0,6}", rnd.Next(-100, 101)) + If ctr Mod 5 = 0 Then Console.WriteLine() + Next + Console.WriteLine() + + Console.WriteLine("20 random integers from 1000 to 10000:") + For ctr As Integer = 1 To 20 + Console.Write("{0,8}", rnd.Next(1000, 10001)) + If ctr Mod 5 = 0 Then Console.WriteLine() + Next + Console.WriteLine() + + Console.WriteLine("20 random integers from 1 to 10:") + For ctr As Integer = 1 To 20 + Console.Write("{0,6}", rnd.Next(1, 11)) + If ctr Mod 5 = 0 Then Console.WriteLine() + Next + End Sub End Module ' The example displays output similar to the following: ' 20 random integers from -100 to 100: diff --git a/snippets/visualbasic/System/Random/Overview/next3.vb b/snippets/visualbasic/System/Random/Overview/next3.vb index 08a59076fac..11fa60964d9 100644 --- a/snippets/visualbasic/System/Random/Overview/next3.vb +++ b/snippets/visualbasic/System/Random/Overview/next3.vb @@ -2,19 +2,19 @@ Option Strict On ' -Module Example - Public Sub Main() - Console.Write("Number of random numbers to generate: ") - Dim line As String = Console.ReadLine() - Dim numbers As UInteger = 0 - Dim rnd As New Random() - - If Not UInt32.TryParse(line, numbers) Then numbers = 10 - - For ctr As UInteger = 1 To numbers - Console.WriteLine("{0,15:N0}", rnd.Next()) - Next - End Sub +Module NextExample3 + Public Sub Main() + Console.Write("Number of random numbers to generate: ") + Dim line As String = Console.ReadLine() + Dim numbers As UInteger = 0 + Dim rnd As New Random() + + If Not UInt32.TryParse(line, numbers) Then numbers = 10 + + For ctr As UInteger = 1 To numbers + Console.WriteLine("{0,15:N0}", rnd.Next()) + Next + End Sub End Module ' The example displays output like the following when asked to generate ' 15 random numbers: diff --git a/snippets/visualbasic/System/Random/Overview/next4.vb b/snippets/visualbasic/System/Random/Overview/next4.vb index 01f103fa4d2..e972ae6caa5 100644 --- a/snippets/visualbasic/System/Random/Overview/next4.vb +++ b/snippets/visualbasic/System/Random/Overview/next4.vb @@ -2,25 +2,25 @@ Option Strict On ' -Module Example - Public Sub Main() - Dim rnd As New Random() - Dim malePetNames() As String = { "Rufus", "Bear", "Dakota", "Fido", - "Vanya", "Samuel", "Koani", "Volodya", - "Prince", "Yiska" } - Dim femalePetNames() As String = { "Maggie", "Penny", "Saya", "Princess", - "Abby", "Laila", "Sadie", "Olivia", - "Starlight", "Talla" } - - ' Generate random indexes for pet names. - Dim mIndex As Integer = rnd.Next(0, malePetNames.Length) - Dim fIndex As Integer = rnd.Next(0, femalePetNames.Length) - - ' Display the result. - Console.WriteLine("Suggested pet name of the day: ") - Console.WriteLine(" For a male: {0}", malePetNames(mIndex)) - Console.WriteLine(" For a female: {0}", femalePetNames(fIndex)) - End Sub +Module NextExample4 + Public Sub Main() + Dim rnd As New Random() + Dim malePetNames() As String = {"Rufus", "Bear", "Dakota", "Fido", + "Vanya", "Samuel", "Koani", "Volodya", + "Prince", "Yiska"} + Dim femalePetNames() As String = {"Maggie", "Penny", "Saya", "Princess", + "Abby", "Laila", "Sadie", "Olivia", + "Starlight", "Talla"} + + ' Generate random indexes for pet names. + Dim mIndex As Integer = rnd.Next(0, malePetNames.Length) + Dim fIndex As Integer = rnd.Next(0, femalePetNames.Length) + + ' Display the result. + Console.WriteLine("Suggested pet name of the day: ") + Console.WriteLine(" For a male: {0}", malePetNames(mIndex)) + Console.WriteLine(" For a female: {0}", femalePetNames(fIndex)) + End Sub End Module ' The example displays output like the following: ' Suggested pet name of the day: diff --git a/snippets/visualbasic/System/Random/Overview/nextbytes1.vb b/snippets/visualbasic/System/Random/Overview/nextbytes1.vb new file mode 100644 index 00000000000..0f900436114 --- /dev/null +++ b/snippets/visualbasic/System/Random/Overview/nextbytes1.vb @@ -0,0 +1,19 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example9 + Public Sub Main() + Dim rnd As New Random() + Dim bytes(19) As Byte + rnd.NextBytes(bytes) + For ctr As Integer = 1 To bytes.Length + Console.Write("{0,3} ", bytes(ctr - 1)) + If ctr Mod 10 = 0 Then Console.WriteLine() + Next + End Sub +End Module +' The example displays output like the following: +' 141 48 189 66 134 212 211 71 161 56 +' 181 166 220 133 9 252 222 57 62 62 +' diff --git a/snippets/visualbasic/System/Random/Overview/nextdoubleex1.vb b/snippets/visualbasic/System/Random/Overview/nextdoubleex1.vb new file mode 100644 index 00000000000..d8c63d68654 --- /dev/null +++ b/snippets/visualbasic/System/Random/Overview/nextdoubleex1.vb @@ -0,0 +1,19 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example10 + Public Sub Main() + Dim rnd As New Random() + For ctr As Integer = 0 To 9 + Console.Write("{0,-19:R} ", rnd.NextDouble()) + If (ctr + 1) Mod 3 = 0 Then Console.WriteLine() + Next + End Sub +End Module +' The example displays output like the following: +' 0.7911680553998649 0.0903414949264105 0.79776258291572455 +' 0.615568345233597 0.652644504165577 0.84023809378977776 +' 0.099662564741290441 0.91341467383942321 0.96018602045261581 +' 0.74772306473354022 +' diff --git a/snippets/visualbasic/System/Random/Overview/nextex1.vb b/snippets/visualbasic/System/Random/Overview/nextex1.vb new file mode 100644 index 00000000000..c7fec4d9a8a --- /dev/null +++ b/snippets/visualbasic/System/Random/Overview/nextex1.vb @@ -0,0 +1,15 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example11 + Public Sub Main() + Dim rnd As New Random() + For ctr As Integer = 0 To 9 + Console.Write("{0,3} ", rnd.Next(-10, 11)) + Next + End Sub +End Module +' The example displays output like the following: +' 2 9 -3 2 4 -7 -3 -8 -8 5 +' diff --git a/snippets/visualbasic/System/Random/Overview/range1.vb b/snippets/visualbasic/System/Random/Overview/range1.vb new file mode 100644 index 00000000000..d8a9beacb5d --- /dev/null +++ b/snippets/visualbasic/System/Random/Overview/range1.vb @@ -0,0 +1,18 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example12 + Public Sub Main() + Dim rnd As New Random() + For ctr As Integer = 1 To 15 + Console.Write("{0,3} ", rnd.Next(-10, 11)) + If ctr Mod 5 = 0 Then Console.WriteLine() + Next + End Sub +End Module +' The example displays output like the following: +' -2 -5 -1 -2 10 +' -3 6 -4 -8 3 +' -7 10 5 -2 4 +' diff --git a/snippets/visualbasic/System/Random/Overview/range2.vb b/snippets/visualbasic/System/Random/Overview/range2.vb new file mode 100644 index 00000000000..f2fa6e2d382 --- /dev/null +++ b/snippets/visualbasic/System/Random/Overview/range2.vb @@ -0,0 +1,20 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example13 + Public Sub Main() + Dim rnd As New Random() + For ctr As Integer = 1 To 50 + Console.Write("{0,3} ", rnd.Next(1000, 10000)) + If ctr Mod 10 = 0 Then Console.WriteLine() + Next + End Sub +End Module +' The example displays output like the following: +' 9570 8979 5770 1606 3818 4735 8495 7196 7070 2313 +' 5279 6577 5104 5734 4227 3373 7376 6007 8193 5540 +' 7558 3934 3819 7392 1113 7191 6947 4963 9179 7907 +' 3391 6667 7269 1838 7317 1981 5154 7377 3297 5320 +' 9869 8694 2684 4949 2999 3019 2357 5211 9604 2593 +' diff --git a/snippets/visualbasic/System/Random/Overview/same1.vb b/snippets/visualbasic/System/Random/Overview/same1.vb new file mode 100644 index 00000000000..b7afc104908 --- /dev/null +++ b/snippets/visualbasic/System/Random/Overview/same1.vb @@ -0,0 +1,88 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.IO + +Module Example14 + Public Sub Main() + Dim seed As Integer = 100100 + ShowRandomNumbers(seed) + Console.WriteLine() + + PersistSeed(seed) + + DisplayNewRandomNumbers() + End Sub + + Private Sub ShowRandomNumbers(seed As Integer) + Dim rnd As New Random(seed) + For ctr As Integer = 0 To 20 + Console.WriteLine(rnd.NextDouble()) + Next + End Sub + + Private Sub PersistSeed(seed As Integer) + Dim fs As New FileStream(".\seed.dat", FileMode.Create) + Dim bin As New BinaryWriter(fs) + bin.Write(seed) + bin.Close() + End Sub + + Private Sub DisplayNewRandomNumbers() + Dim fs As New FileStream(".\seed.dat", FileMode.Open) + Dim bin As New BinaryReader(fs) + Dim seed As Integer = bin.ReadInt32() + bin.Close() + + Dim rnd As New Random(seed) + For ctr As Integer = 0 To 20 + Console.WriteLine(rnd.NextDouble()) + Next + End Sub +End Module +' The example displays output like the following: +' 0.500193602172748 +' 0.0209461245783354 +' 0.465869495396442 +' 0.195512794514891 +' 0.928583675496552 +' 0.729333720509584 +' 0.381455668891527 +' 0.0508996467343064 +' 0.019261200921266 +' 0.258578445417145 +' 0.0177532266908107 +' 0.983277184415272 +' 0.483650274334313 +' 0.0219647376900375 +' 0.165910115077118 +' 0.572085966622497 +' 0.805291457942357 +' 0.927985211335116 +' 0.4228545699375 +' 0.523320379910674 +' 0.157783938645285 +' +' 0.500193602172748 +' 0.0209461245783354 +' 0.465869495396442 +' 0.195512794514891 +' 0.928583675496552 +' 0.729333720509584 +' 0.381455668891527 +' 0.0508996467343064 +' 0.019261200921266 +' 0.258578445417145 +' 0.0177532266908107 +' 0.983277184415272 +' 0.483650274334313 +' 0.0219647376900375 +' 0.165910115077118 +' 0.572085966622497 +' 0.805291457942357 +' 0.927985211335116 +' 0.4228545699375 +' 0.523320379910674 +' 0.157783938645285 +' diff --git a/snippets/visualbasic/System/Random/Overview/threadsafeex1.vb b/snippets/visualbasic/System/Random/Overview/threadsafeex1.vb new file mode 100644 index 00000000000..bf1411760da --- /dev/null +++ b/snippets/visualbasic/System/Random/Overview/threadsafeex1.vb @@ -0,0 +1,144 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Threading + +Module Example15 + Dim previous As Double = 0.0 + Dim perThreadCtr As Integer = 0 + Dim perThreadTotal As Double = 0.0 + Dim source As New CancellationTokenSource() + Dim countdown As New CountdownEvent(1) + Dim randLock As New Object() + Dim numericLock As New Object() + Dim rand As New Random() + Dim totalValue As Double = 0.0 + Dim totalCount As Integer = 0 + + Public Sub Main() + Thread.CurrentThread.Name = "Main" + + Dim token As CancellationToken = source.Token + For threads As Integer = 1 To 10 + Dim newThread As New Thread(AddressOf GetRandomNumbers) + newThread.Name = threads.ToString() + newThread.Start(token) + Next + GetRandomNumbers(token) + + countdown.Signal() + ' Make sure all threads have finished. + countdown.Wait() + + Console.WriteLine() + Console.WriteLine("Total random numbers generated: {0:N0}", totalCount) + Console.WriteLine("Total sum of all random numbers: {0:N2}", totalValue) + Console.WriteLine("Random number mean: {0:N4}", totalValue / totalCount) + End Sub + + Private Sub GetRandomNumbers(o As Object) + Dim token As CancellationToken = CType(o, CancellationToken) + Dim result As Double = 0.0 + countdown.AddCount(1) + + Try + For ctr As Integer = 1 To 2000000 + ' Make sure there's no corruption of Random. + token.ThrowIfCancellationRequested() + + SyncLock randLock + result = rand.NextDouble() + End SyncLock + ' Check for corruption of Random instance. + If result = previous AndAlso result = 0 Then + source.Cancel() + Else + previous = result + End If + perThreadCtr += 1 + perThreadTotal += result + Next + + Console.WriteLine("Thread {0} finished execution.", + Thread.CurrentThread.Name) + Console.WriteLine("Random numbers generated: {0:N0}", perThreadCtr) + Console.WriteLine("Sum of random numbers: {0:N2}", perThreadTotal) + Console.WriteLine("Random number mean: {0:N4}", perThreadTotal / perThreadCtr) + Console.WriteLine() + + ' Update overall totals. + SyncLock numericLock + totalCount += perThreadCtr + totalValue += perThreadTotal + End SyncLock + Catch e As OperationCanceledException + Console.WriteLine("Corruption in Thread {1}", e.GetType().Name, Thread.CurrentThread.Name) + Finally + countdown.Signal() + source.Dispose() + End Try + End Sub +End Module +' The example displays output like the following: +' Thread 6 finished execution. +' Random numbers generated: 2,000,000 +' Sum of random numbers: 1,000,491.05 +' Random number mean: 0.5002 +' +' Thread 10 finished execution. +' Random numbers generated: 2,000,000 +' Sum of random numbers: 999,329.64 +' Random number mean: 0.4997 +' +' Thread 4 finished execution. +' Random numbers generated: 2,000,000 +' Sum of random numbers: 1,000,166.89 +' Random number mean: 0.5001 +' +' Thread 8 finished execution. +' Random numbers generated: 2,000,000 +' Sum of random numbers: 999,628.37 +' Random number mean: 0.4998 +' +' Thread Main finished execution. +' Random numbers generated: 2,000,000 +' Sum of random numbers: 999,920.89 +' Random number mean: 0.5000 +' +' Thread 3 finished execution. +' Random numbers generated: 2,000,000 +' Sum of random numbers: 999,370.45 +' Random number mean: 0.4997 +' +' Thread 7 finished execution. +' Random numbers generated: 2,000,000 +' Sum of random numbers: 999,330.92 +' Random number mean: 0.4997 +' +' Thread 9 finished execution. +' Random numbers generated: 2,000,000 +' Sum of random numbers: 1,000,172.79 +' Random number mean: 0.5001 +' +' Thread 5 finished execution. +' Random numbers generated: 2,000,000 +' Sum of random numbers: 1,000,079.43 +' Random number mean: 0.5000 +' +' Thread 1 finished execution. +' Random numbers generated: 2,000,000 +' Sum of random numbers: 999,817.91 +' Random number mean: 0.4999 +' +' Thread 2 finished execution. +' Random numbers generated: 2,000,000 +' Sum of random numbers: 999,930.63 +' Random number mean: 0.5000 +' +' +' Total random numbers generated: 22,000,000 +' Total sum of all random numbers: 10,998,238.98 +' Random number mean: 0.4999 +' + diff --git a/snippets/visualbasic/System/Random/Overview/threadsafeex2.vb b/snippets/visualbasic/System/Random/Overview/threadsafeex2.vb new file mode 100644 index 00000000000..2e01f27849d --- /dev/null +++ b/snippets/visualbasic/System/Random/Overview/threadsafeex2.vb @@ -0,0 +1,143 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Collections.Generic +Imports System.Threading +Imports System.Threading.Tasks + +Module Example16 + Dim source As New CancellationTokenSource() + Dim randLock As New Object() + Dim numericLock As New Object() + Dim rand As New Random() + Dim totalValue As Double = 0.0 + Dim totalCount As Integer = 0 + + Public Sub Main() + Dim tasks As New List(Of Task)() + + For ctr As Integer = 1 To 10 + Dim token As CancellationToken = source.Token + Dim taskNo As Integer = ctr + tasks.Add(Task.Run( + Sub() + Dim previous As Double = 0.0 + Dim taskCtr As Integer = 0 + Dim taskTotal As Double = 0.0 + Dim result As Double = 0.0 + + For n As Integer = 1 To 2000000 + ' Make sure there's no corruption of Random. + token.ThrowIfCancellationRequested() + + SyncLock randLock + result = rand.NextDouble() + End SyncLock + ' Check for corruption of Random instance. + If result = previous AndAlso result = 0 Then + source.Cancel() + Else + previous = result + End If + taskCtr += 1 + taskTotal += result + Next + + ' Show result. + Console.WriteLine("Task {0} finished execution.", taskNo) + Console.WriteLine("Random numbers generated: {0:N0}", taskCtr) + Console.WriteLine("Sum of random numbers: {0:N2}", taskTotal) + Console.WriteLine("Random number mean: {0:N4}", taskTotal / taskCtr) + Console.WriteLine() + + ' Update overall totals. + SyncLock numericLock + totalCount += taskCtr + totalValue += taskTotal + End SyncLock + End Sub, token)) + Next + + Try + Task.WaitAll(tasks.ToArray()) + Console.WriteLine() + Console.WriteLine("Total random numbers generated: {0:N0}", totalCount) + Console.WriteLine("Total sum of all random numbers: {0:N2}", totalValue) + Console.WriteLine("Random number mean: {0:N4}", totalValue / totalCount) + Catch e As AggregateException + For Each inner As Exception In e.InnerExceptions + Dim canc As TaskCanceledException = TryCast(inner, TaskCanceledException) + If canc IsNot Nothing Then + Console.WriteLine("Task #{0} cancelled.", canc.Task.Id) + Else + Console.WriteLine("Exception: {0}", inner.GetType().Name) + End If + Next + Finally + source.Dispose() + End Try + End Sub +End Module +' The example displays output like the following: +' Task 1 finished execution. +' Random numbers generated: 2,000,000 +' Sum of random numbers: 1,000,502.47 +' Random number mean: 0.5003 +' +' Task 0 finished execution. +' Random numbers generated: 2,000,000 +' Sum of random numbers: 1,000,445.63 +' Random number mean: 0.5002 +' +' Task 2 finished execution. +' Random numbers generated: 2,000,000 +' Sum of random numbers: 1,000,556.04 +' Random number mean: 0.5003 +' +' Task 3 finished execution. +' Random numbers generated: 2,000,000 +' Sum of random numbers: 1,000,178.87 +' Random number mean: 0.5001 +' +' Task 4 finished execution. +' Random numbers generated: 2,000,000 +' Sum of random numbers: 999,819.17 +' Random number mean: 0.4999 +' +' Task 5 finished execution. +' Random numbers generated: 2,000,000 +' Sum of random numbers: 1,000,190.58 +' Random number mean: 0.5001 +' +' Task 6 finished execution. +' Random numbers generated: 2,000,000 +' Sum of random numbers: 999,720.21 +' Random number mean: 0.4999 +' +' Task 7 finished execution. +' Random numbers generated: 2,000,000 +' Sum of random numbers: 999,000.96 +' Random number mean: 0.4995 +' +' Task 8 finished execution. +' Random numbers generated: 2,000,000 +' Sum of random numbers: 999,499.33 +' Random number mean: 0.4997 +' +' Task 9 finished execution. +' Random numbers generated: 2,000,000 +' Sum of random numbers: 1,000,193.25 +' Random number mean: 0.5001 +' +' Task 10 finished execution. +' Random numbers generated: 2,000,000 +' Sum of random numbers: 999,960.82 +' Random number mean: 0.5000 +' +' +' Total random numbers generated: 22,000,000 +' Total sum of all random numbers: 11,000,067.33 +' Random number mean: 0.5000 +' + diff --git a/snippets/visualbasic/System/Random/Overview/unique.vb b/snippets/visualbasic/System/Random/Overview/unique.vb new file mode 100644 index 00000000000..102b020518c --- /dev/null +++ b/snippets/visualbasic/System/Random/Overview/unique.vb @@ -0,0 +1,54 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Threading + +Module Example17 + Public Sub Main() + Console.WriteLine("Instantiating two random number generators...") + Dim rnd1 As New Random() + Thread.Sleep(2000) + Dim rnd2 As New Random() + Console.WriteLine() + + Console.WriteLine("The first random number generator:") + For ctr As Integer = 1 To 10 + Console.WriteLine(" {0}", rnd1.Next()) + Next + Console.WriteLine() + + Console.WriteLine("The second random number generator:") + For ctr As Integer = 1 To 10 + Console.WriteLine(" {0}", rnd2.Next()) + Next + End Sub +End Module +' The example displays output like the following: +' Instantiating two random number generators... +' +' The first random number generator: +' 643164361 +' 1606571630 +' 1725607587 +' 2138048432 +' 496874898 +' 1969147632 +' 2034533749 +' 1840964542 +' 412380298 +' 47518930 +' +' The second random number generator: +' 1251659083 +' 1514185439 +' 1465798544 +' 517841554 +' 1821920222 +' 195154223 +' 1538948391 +' 1548375095 +' 546062716 +' 897797880 +' + diff --git a/snippets/visualbasic/System/Random/Overview/uniquearray1.vb b/snippets/visualbasic/System/Random/Overview/uniquearray1.vb new file mode 100644 index 00000000000..bc7c09df6df --- /dev/null +++ b/snippets/visualbasic/System/Random/Overview/uniquearray1.vb @@ -0,0 +1,125 @@ +' Visual Basic .NET Document +Option Strict On + +' +' A class that represents an individual card in a playing deck. +Public Class Card + Public Suit As Suit + Public FaceValue As FaceValue + + Public Overrides Function ToString() As String + Return String.Format("{0:F} of {1:F}", Me.FaceValue, Me.Suit) + End Function +End Class + +Public Enum Suit As Integer + Hearts = 0 + Diamonds = 1 + Spades = 2 + Clubs = 3 +End Enum + +Public Enum FaceValue As Integer + Ace = 1 + Two = 2 + Three = 3 + Four = 4 + Five = 5 + Six = 6 + Seven = 7 + Eight = 8 + Nine = 9 + Ten = 10 + Jack = 11 + Queen = 12 + King = 13 +End Enum + +Public Class Dealer + Dim rnd As Random + ' A deck of cards, without Jokers. + Dim deck(51) As Card + ' Parallel array for sorting cards. + Dim order(51) As Double + ' A pointer to the next card to deal. + Dim ptr As Integer = 0 + ' A flag to indicate the deck is used. + Dim mustReshuffle As Boolean + + Public Sub New() + rnd = New Random() + ' Initialize the deck. + Dim deckCtr As Integer = 0 + For Each Suit In [Enum].GetValues(GetType(Suit)) + For Each faceValue In [Enum].GetValues(GetType(FaceValue)) + Dim card As New Card() + card.Suit = CType(Suit, Suit) + card.FaceValue = CType(faceValue, FaceValue) + deck(deckCtr) = card + deckCtr += 1 + Next + Next + For ctr As Integer = 0 To order.Length - 1 + order(ctr) = rnd.NextDouble() + Next + Array.Sort(order, deck) + End Sub + + Public Function Deal(numberToDeal As Integer) As Card() + If mustReshuffle Then + Console.WriteLine("There are no cards left in the deck") + Return Nothing + End If + + Dim cardsDealt(numberToDeal - 1) As Card + For ctr As Integer = 0 To numberToDeal - 1 + cardsDealt(ctr) = deck(ptr) + ptr += 1 + If ptr = deck.Length Then + mustReshuffle = True + End If + If mustReshuffle And ctr < numberToDeal - 1 + Console.WriteLine("Can only deal the {0} cards remaining on the deck.", + ctr + 1) + Return cardsDealt + End If + Next + Return cardsDealt + End Function +End Class + +Public Module UniqueArrayExample + Public Sub Main() + Dim dealer As New Dealer() + ShowCards(dealer.Deal(20)) + End Sub + + Private Sub ShowCards(cards() As Card) + For Each card In cards + If card IsNot Nothing Then _ + Console.WriteLine("{0} of {1}", card.FaceValue, card.Suit) + Next + End Sub +End Module +' The example displays output like the following: +' Six of Diamonds +' King of Clubs +' Eight of Clubs +' Seven of Clubs +' Queen of Clubs +' King of Hearts +' Three of Spades +' Ace of Clubs +' Four of Hearts +' Three of Diamonds +' Nine of Diamonds +' Two of Hearts +' Ace of Hearts +' Three of Hearts +' Four of Spades +' Eight of Hearts +' Queen of Diamonds +' Two of Clubs +' Four of Diamonds +' Jack of Hearts +' diff --git a/snippets/visualbasic/System/Single/CompareTo/Project.vbproj b/snippets/visualbasic/System/Single/CompareTo/Project.vbproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/visualbasic/System/Single/CompareTo/Project.vbproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/visualbasic/System/Single/CompareTo/compareto2.vb b/snippets/visualbasic/System/Single/CompareTo/compareto2.vb new file mode 100644 index 00000000000..11204a93390 --- /dev/null +++ b/snippets/visualbasic/System/Single/CompareTo/compareto2.vb @@ -0,0 +1,21 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example + Public Sub Main() + Dim value1 As Single = 16.5457 + Dim value2 As Single = value1 * CSng(3.8899982) / CSng(3.8899982) + Console.WriteLine("Comparing {0} and {1}: {2}", + value1, value2, value1.CompareTo(value2)) + Console.WriteLine() + Console.WriteLine("Comparing {0:R} and {1:R}: {2}", + value1, value2, value1.CompareTo(value2)) + End Sub +End Module +' The example displays the following output: +' Comparing 16.5457 and 16.5457: -1 +' +' Comparing 16.5457 and 16.545702: -1 +' + diff --git a/snippets/visualbasic/System/Single/CompareTo/compareto3.vb b/snippets/visualbasic/System/Single/CompareTo/compareto3.vb new file mode 100644 index 00000000000..1822759f127 --- /dev/null +++ b/snippets/visualbasic/System/Single/CompareTo/compareto3.vb @@ -0,0 +1,21 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example2 + Public Sub Main() + Dim value1 As Single = 16.5457 + Dim value2 As Object = value1 * CSng(3.8899982) / CSng(3.8899982) + Console.WriteLine("Comparing {0} and {1}: {2}", + value1, value2, value1.CompareTo(value2)) + Console.WriteLine() + Console.WriteLine("Comparing {0:R} and {1:R}: {2}", + value1, value2, value1.CompareTo(value2)) + End Sub +End Module +' The example displays the following output: +' Comparing 16.5457 and 16.5457: -1 +' +' Comparing 16.5457 and 16.545702: -1 +' + diff --git a/snippets/visualbasic/System/Single/Epsilon/Project.vbproj b/snippets/visualbasic/System/Single/Epsilon/Project.vbproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/visualbasic/System/Single/Epsilon/Project.vbproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/visualbasic/System/Single/Epsilon/SingleEquals_25051.vb b/snippets/visualbasic/System/Single/Epsilon/SingleEquals_25051.vb new file mode 100644 index 00000000000..257091aabb5 --- /dev/null +++ b/snippets/visualbasic/System/Single/Epsilon/SingleEquals_25051.vb @@ -0,0 +1,71 @@ +' Visual Basic .NET Document +Option Strict On + +Module modMain + Public Sub Main() + CompareUsingEquals() + Console.WriteLine() + CompareApproximateValues() + Console.WriteLine() + CompareObjectsUsingEquals() + Console.WriteLine() + CompareApproximateObjectValues() + End Sub + + Private Sub CompareUsingEquals() + ' + ' Initialize two singles with apparently identical values + Dim single1 As Single = .33333 + Dim single2 As Single = 1/3 + ' Compare them for equality + Console.WriteLine(single1.Equals(single2)) ' displays False + ' + End Sub + + Private Sub CompareApproximateValues() + ' + ' Initialize two singles with apparently identical values + Dim single1 As Single = .33333 + Dim single2 As Single = 1/3 + ' Define the tolerance for variation in their values + Dim difference As Single = Math.Abs(single1 * .0001f) + + ' Compare the values + ' The output to the console indicates that the two values are equal + If Math.Abs(single1 - single2) <= difference Then + Console.WriteLine("single1 and single2 are equal.") + Else + Console.WriteLine("single1 and single2 are unequal.") + End If + ' + End Sub + + Private Sub CompareObjectsUsingEquals() + ' + ' Initialize two singles with apparently identical values + Dim single1 As Single = .33333 + Dim single2 As Object = 1/3 + ' Compare them for equality + Console.WriteLine(single1.Equals(single2)) ' displays False + ' + End Sub + + Private Sub CompareApproximateObjectValues() + ' + ' Initialize two singles with apparently identical values + Dim single1 As Single = .33333 + Dim single2 As Object = 1/3 + ' Define the tolerance for variation in their values + Dim difference As Single = Math.Abs(single1 * .0001f) + + ' Compare the values + ' The output to the console indicates that the two values are equal + If Math.Abs(single1 - CSng(single2)) <= difference Then + Console.WriteLine("single1 and single2 are equal.") + Else + Console.WriteLine("single1 and single2 are unequal.") + End If + ' + End Sub +End Module + diff --git a/snippets/visualbasic/System/Single/Epsilon/epsilon.vb b/snippets/visualbasic/System/Single/Epsilon/epsilon.vb new file mode 100644 index 00000000000..09b88e9a915 --- /dev/null +++ b/snippets/visualbasic/System/Single/Epsilon/epsilon.vb @@ -0,0 +1,24 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example1 + Public Sub Main() + Dim values() As Single = {0, Single.Epsilon, Single.Epsilon * 0.5} + + For ctr As Integer = 0 To values.Length - 2 + For ctr2 As Integer = ctr + 1 To values.Length - 1 + Console.WriteLine("{0:r} = {1:r}: {2}", + values(ctr), values(ctr2), + values(ctr).Equals(values(ctr2))) + Next + Console.WriteLine() + Next + End Sub +End Module +' The example displays the following output: +' 0 = 1.401298E-45: False +' 0 = 0: True +' +' 1.401298E-45 = 0: False +' diff --git a/snippets/visualbasic/System/Single/Epsilon/epsilon1.vb b/snippets/visualbasic/System/Single/Epsilon/epsilon1.vb new file mode 100644 index 00000000000..f002bf8ccef --- /dev/null +++ b/snippets/visualbasic/System/Single/Epsilon/epsilon1.vb @@ -0,0 +1,54 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example2 + Public Sub Main() + Dim values() As Single = {0.0, Single.Epsilon} + For Each value In values + Console.WriteLine(GetComponentParts(value)) + Console.WriteLine() + Next + End Sub + + Private Function GetComponentParts(value As Single) As String + Dim result As String = String.Format("{0:R}: ", value) + Dim indent As Integer = result.Length + + ' Convert the single to an 8-byte array. + Dim bytes() As Byte = BitConverter.GetBytes(value) + Dim formattedSingle As Integer = BitConverter.ToInt32(bytes, 0) + + ' Get the sign bit (byte 3, bit 7). + result += String.Format("Sign: {0}{1}", + If(formattedSingle >> 31 <> 0, "1 (-)", "0 (+)"), + vbCrLf) + + ' Get the exponent (byte 2 bit 7 to byte 3, bits 6) + Dim exponent As Integer = (formattedSingle >> 23) And &HFF + Dim adjustment As Integer = If(exponent <> 0, 127, 126) + result += String.Format("{0}Exponent: 0x{1:X4} ({1}){2}", + New String(" "c, indent), exponent - adjustment, + vbCrLf) + + ' Get the significand (bits 0-22) + Dim significand As Long = If(exponent <> 0, + (formattedSingle And &H7FFFFF) Or &H800000, + formattedSingle And &H7FFFFF) + result += String.Format("{0}Mantissa: 0x{1:X13}{2}", + New String(" "c, indent), significand, vbCrLf) + + Return result + End Function +End Module +' The example displays the following output: +' 0: Sign: 0 (+) +' Exponent: 0xFFFFFF82 (-126) +' Mantissa: 0x0000000000000 +' +' +' 1.401298E-45: Sign: 0 (+) +' Exponent: 0xFFFFFF82 (-126) +' Mantissa: 0x0000000000001 +' + diff --git a/snippets/visualbasic/System/Single/Equals/Project.vbproj b/snippets/visualbasic/System/Single/Equals/Project.vbproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/visualbasic/System/Single/Equals/Project.vbproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/visualbasic/System/Single/Equals/equalsabs1.vb b/snippets/visualbasic/System/Single/Equals/equalsabs1.vb new file mode 100644 index 00000000000..cbab954266a --- /dev/null +++ b/snippets/visualbasic/System/Single/Equals/equalsabs1.vb @@ -0,0 +1,44 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example1 + Public Sub Main() + Dim value1 As Single = .1 * 10 + Dim value2 As Single = 0 + For ctr As Integer = 0 To 9 + value2 += CSng(.1) + Next + + Console.WriteLine("{0:R} = {1:R}: {2}", value1, value2, + HasMinimalDifference(value1, value2, 1)) + End Sub + + Public Function HasMinimalDifference(value1 As Single, value2 As Single, units As Integer) As Boolean + Dim bytes() As Byte = BitConverter.GetBytes(value1) + Dim iValue1 As Integer = BitConverter.ToInt32(bytes, 0) + + bytes = BitConverter.GetBytes(value2) + Dim iValue2 As Integer = BitConverter.ToInt32(bytes, 0) + + ' If the signs are different, Return False except for +0 and -0. + If ((iValue1 >> 31) <> (iValue2 >> 31)) Then + If value1 = value2 Then + Return True + End If + Return False + End If + + Dim diff As Integer = Math.Abs(iValue1 - iValue2) + + If diff <= units Then + Return True + End If + + Return False + End Function +End Module +' The example displays the following output: +' 1 = 1.00000012: True +' + diff --git a/snippets/visualbasic/System/Single/Equals/equalsoverl.vb b/snippets/visualbasic/System/Single/Equals/equalsoverl.vb index aa588582fa9..da4a9f69d90 100644 --- a/snippets/visualbasic/System/Single/Equals/equalsoverl.vb +++ b/snippets/visualbasic/System/Single/Equals/equalsoverl.vb @@ -2,14 +2,14 @@ Option Strict On ' -Module Example +Module Example2 Dim value As Single = 112 - + Public Sub Main() Dim byte1 As Byte = 112 Console.WriteLine("value = byte1: {0,16}", value.Equals(byte1)) TestObjectForEquality(byte1) - + Dim short1 As Short = 112 Console.WriteLine("value = short1: {0,16}", value.Equals(short1)) TestObjectForEquality(short1) @@ -25,7 +25,7 @@ Module Example Dim sbyte1 As SByte = 112 Console.WriteLine("value = sbyte1: {0,16}", value.Equals(sbyte1)) TestObjectForEquality(sbyte1) - + Dim ushort1 As UShort = 112 Console.WriteLine("value = ushort1: {0,16}", value.Equals(ushort1)) TestObjectForEquality(ushort1) @@ -37,7 +37,7 @@ Module Example Dim ulong1 As ULong = 112 Console.WriteLine("value = ulong1: {0,17}", value.Equals(ulong1)) TestObjectForEquality(ulong1) - + Dim dec1 As Decimal = 112d Console.WriteLine("value = dec1: {0,20}", value.Equals(dec1)) TestObjectForEquality(dec1) @@ -46,7 +46,7 @@ Module Example Console.WriteLine("value = dbl1: {0,20}", value.Equals(dbl1)) TestObjectForEquality(dbl1) End Sub - + Private Sub TestObjectForEquality(obj As Object) Console.WriteLine("{0} ({1}) = {2} ({3}): {4}", value, value.GetType().Name, diff --git a/snippets/visualbasic/System/Single/Overview/PrecisionList4a.vb b/snippets/visualbasic/System/Single/Overview/PrecisionList4a.vb new file mode 100644 index 00000000000..7e9692ec3f7 --- /dev/null +++ b/snippets/visualbasic/System/Single/Overview/PrecisionList4a.vb @@ -0,0 +1,37 @@ +' Visual Basic .NET Document +Option Strict On + +Imports System.IO + +Module Example11 + Public Sub Main() + ' + Dim sw As New StreamWriter(".\Singles.dat") + Dim values() As Single = {3.2 / 1.11, 1.0 / 3, CSng(Math.PI)} + For ctr As Integer = 0 To values.Length - 1 + sw.Write(values(ctr).ToString()) + If ctr <> values.Length - 1 Then sw.Write("|") + Next + sw.Close() + + Dim restoredValues(values.Length - 1) As Single + Dim sr As New StreamReader(".\Singles.dat") + Dim temp As String = sr.ReadToEnd() + Dim tempStrings() As String = temp.Split("|"c) + For ctr As Integer = 0 To tempStrings.Length - 1 + restoredValues(ctr) = Single.Parse(tempStrings(ctr)) + Next + + For ctr As Integer = 0 To values.Length - 1 + Console.WriteLine("{0} {2} {1}", values(ctr), + restoredValues(ctr), + If(values(ctr).Equals(restoredValues(ctr)), "=", "<>")) + Next + + ' The example displays the following output on .NET Framework: + ' 2.882883 <> 2.882883 + ' 0.3333333 <> 0.3333333 + ' 3.141593 <> 3.141593 + ' + End Sub +End Module diff --git a/snippets/visualbasic/System/Single/Overview/Project.vbproj b/snippets/visualbasic/System/Single/Overview/Project.vbproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/visualbasic/System/Single/Overview/Project.vbproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/visualbasic/System/Single/Overview/comparison1.vb b/snippets/visualbasic/System/Single/Overview/comparison1.vb new file mode 100644 index 00000000000..dca470b4395 --- /dev/null +++ b/snippets/visualbasic/System/Single/Overview/comparison1.vb @@ -0,0 +1,15 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example1 + Public Sub Main() + Dim value1 As Single = 0.3333333 + Dim value2 As Single = 1 / 3 + Console.WriteLine("{0:R} = {1:R}: {2}", value1, value2, value1.Equals(value2)) + End Sub +End Module +' The example displays the following output: +' 0.3333333 = 0.333333343: False +' + diff --git a/snippets/visualbasic/System/Single/Overview/comparison2.vb b/snippets/visualbasic/System/Single/Overview/comparison2.vb new file mode 100644 index 00000000000..d56467bdaa7 --- /dev/null +++ b/snippets/visualbasic/System/Single/Overview/comparison2.vb @@ -0,0 +1,20 @@ +' Visual Basic .NET Document +Option Strict On + +Module Example2 + Public Sub Main() + ' + Dim value1 As Single = 10.201438 + value1 = CSng(Math.Sqrt(CSng(Math.Pow(value1, 2)))) + Dim value2 As Single = CSng(Math.Pow(value1 * CSng(3.51), 2)) + value2 = CSng(Math.Sqrt(value2) / CSng(3.51)) + Console.WriteLine("{0} = {1}: {2}", + value1, value2, value1.Equals(value2)) + + ' The example displays the following output on .NET: + ' 10.201438 = 10.201439: False + ' The example displays the following output on .NET Framework: + ' 10.20144 = 10.20144: False + ' + End Sub +End Module diff --git a/snippets/visualbasic/System/Single/Overview/comparison3.vb b/snippets/visualbasic/System/Single/Overview/comparison3.vb new file mode 100644 index 00000000000..db9d08a7e8b --- /dev/null +++ b/snippets/visualbasic/System/Single/Overview/comparison3.vb @@ -0,0 +1,18 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example3 + Public Sub Main() + Dim value1 As Single = 0.3333333 + Dim value2 As Single = 1 / 3 + Dim precision As Integer = 7 + value1 = CSng(Math.Round(value1, precision)) + value2 = CSng(Math.Round(value2, precision)) + Console.WriteLine("{0:R} = {1:R}: {2}", value1, value2, value1.Equals(value2)) + End Sub +End Module +' The example displays the following output: +' 0.3333333 = 0.3333333: True +' + diff --git a/snippets/visualbasic/System/Single/Overview/comparison4.vb b/snippets/visualbasic/System/Single/Overview/comparison4.vb new file mode 100644 index 00000000000..f05888920ea --- /dev/null +++ b/snippets/visualbasic/System/Single/Overview/comparison4.vb @@ -0,0 +1,43 @@ +' Visual Basic .NET Document +Option Strict On + +Module Example4 + ' + Public Sub Main() + Dim one1 As Single = 0.1 * 10 + Dim one2 As Single = 0 + For ctr As Integer = 1 To 10 + one2 += CSng(0.1) + Next + Console.WriteLine("{0:R} = {1:R}: {2}", one1, one2, one1.Equals(one2)) + Console.WriteLine("{0:R} is approximately equal to {1:R}: {2}", + one1, one2, + IsApproximatelyEqual(one1, one2, 0.000001)) + End Sub + + Function IsApproximatelyEqual(value1 As Single, value2 As Single, + epsilon As Single) As Boolean + ' If they are equal anyway, just return True. + If value1.Equals(value2) Then Return True + + ' Handle NaN, Infinity. + If Single.IsInfinity(value1) Or Single.IsNaN(value1) Then + Return value1.Equals(value2) + ElseIf Single.IsInfinity(value2) Or Single.IsNaN(value2) Then + Return value1.Equals(value2) + End If + + ' Handle zero to avoid division by zero. + Dim divisor As Single = Math.Max(value1, value2) + If divisor.Equals(0) Then + divisor = Math.Min(value1, value2) + End If + + Return Math.Abs(value1 - value2) / divisor <= epsilon + End Function + + ' The example displays the following output: + ' 1 = 1.0000001: False + ' 1 is approximately equal to 1.0000001: True + ' +End Module diff --git a/snippets/visualbasic/System/Single/Overview/convert1.vb b/snippets/visualbasic/System/Single/Overview/convert1.vb new file mode 100644 index 00000000000..9b4c7fffb53 --- /dev/null +++ b/snippets/visualbasic/System/Single/Overview/convert1.vb @@ -0,0 +1,49 @@ +' Visual Basic .NET Document +'Option Strict On + +' +Module Example5 + Public Sub Main() + Dim values() As Object = {Byte.MinValue, Byte.MaxValue, Decimal.MinValue, + Decimal.MaxValue, Double.MinValue, Double.MaxValue, + Int16.MinValue, Int16.MaxValue, Int32.MinValue, + Int32.MaxValue, Int64.MinValue, Int64.MaxValue, + SByte.MinValue, SByte.MaxValue, UInt16.MinValue, + UInt16.MaxValue, UInt32.MinValue, UInt32.MaxValue, + UInt64.MinValue, UInt64.MaxValue} + Dim sngValue As Single + For Each value In values + If value.GetType() = GetType(Double) Then + sngValue = CSng(value) + Else + sngValue = value + End If + Console.WriteLine("{0} ({1}) --> {2:R} ({3})", + value, value.GetType().Name, + sngValue, sngValue.GetType().Name) + Next + End Sub +End Module +' The example displays the following output: +' 0 (Byte) --> 0 (Single) +' 255 (Byte) --> 255 (Single) +' -79228162514264337593543950335 (Decimal) --> -7.92281625E+28 (Single) +' 79228162514264337593543950335 (Decimal) --> 7.92281625E+28 (Single) +' -1.79769313486232E+308 (Double) --> -Infinity (Single) +' 1.79769313486232E+308 (Double) --> Infinity (Single) +' -32768 (Int16) --> -32768 (Single) +' 32767 (Int16) --> 32767 (Single) +' -2147483648 (Int32) --> -2.14748365E+09 (Single) +' 2147483647 (Int32) --> 2.14748365E+09 (Single) +' -9223372036854775808 (Int64) --> -9.223372E+18 (Single) +' 9223372036854775807 (Int64) --> 9.223372E+18 (Single) +' -128 (SByte) --> -128 (Single) +' 127 (SByte) --> 127 (Single) +' 0 (UInt16) --> 0 (Single) +' 65535 (UInt16) --> 65535 (Single) +' 0 (UInt32) --> 0 (Single) +' 4294967295 (UInt32) --> 4.2949673E+09 (Single) +' 0 (UInt64) --> 0 (Single) +' 18446744073709551615 (UInt64) --> 1.84467441E+19 (Single) +' + diff --git a/snippets/visualbasic/System/Single/Overview/convert2.vb b/snippets/visualbasic/System/Single/Overview/convert2.vb new file mode 100644 index 00000000000..c2192caf9cd --- /dev/null +++ b/snippets/visualbasic/System/Single/Overview/convert2.vb @@ -0,0 +1,92 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example6 + Public Sub Main() + Dim values() As Single = {Single.MinValue, -67890.1234, -12345.6789, + 12345.6789, 67890.1234, Single.MaxValue, + Single.NaN, Single.PositiveInfinity, + Single.NegativeInfinity} + For Each value In values + Try + Dim lValue As Long = CLng(value) + Console.WriteLine("{0} ({1}) --> {2} (0x{2:X16}) ({3})", + value, value.GetType().Name, + lValue, lValue.GetType().Name) + Catch e As OverflowException + Console.WriteLine("Unable to convert {0} to Int64.", value) + End Try + Try + Dim ulValue As UInt64 = CULng(value) + Console.WriteLine("{0} ({1}) --> {2} (0x{2:X16}) ({3})", + value, value.GetType().Name, + ulValue, ulValue.GetType().Name) + Catch e As OverflowException + Console.WriteLine("Unable to convert {0} to UInt64.", value) + End Try + Try + Dim dValue As Decimal = CDec(value) + Console.WriteLine("{0} ({1}) --> {2} ({3})", + value, value.GetType().Name, + dValue, dValue.GetType().Name) + Catch e As OverflowException + Console.WriteLine("Unable to convert {0} to Decimal.", value) + End Try + + Dim dblValue As Double = value + Console.WriteLine("{0} ({1}) --> {2} ({3})", + value, value.GetType().Name, + dblValue, dblValue.GetType().Name) + Console.WriteLine() + Next + End Sub +End Module + +' The example displays the following output for conversions performed +' in a checked context: +' Unable to convert -3.402823E+38 to Int64. +' Unable to convert -3.402823E+38 to UInt64. +' Unable to convert -3.402823E+38 to Decimal. +' -3.402823E+38 (Single) --> -3.40282346638529E+38 (Double) +' +' -67890.13 (Single) --> -67890 (0xFFFFFFFFFFFEF6CE) (Int64) +' Unable to convert -67890.13 to UInt64. +' -67890.13 (Single) --> -67890.12 (Decimal) +' -67890.13 (Single) --> -67890.125 (Double) +' +' -12345.68 (Single) --> -12346 (0xFFFFFFFFFFFFCFC6) (Int64) +' Unable to convert -12345.68 to UInt64. +' -12345.68 (Single) --> -12345.68 (Decimal) +' -12345.68 (Single) --> -12345.6787109375 (Double) +' +' 12345.68 (Single) --> 12346 (0x000000000000303A) (Int64) +' 12345.68 (Single) --> 12346 (0x000000000000303A) (UInt64) +' 12345.68 (Single) --> 12345.68 (Decimal) +' 12345.68 (Single) --> 12345.6787109375 (Double) +' +' 67890.13 (Single) --> 67890 (0x0000000000010932) (Int64) +' 67890.13 (Single) --> 67890 (0x0000000000010932) (UInt64) +' 67890.13 (Single) --> 67890.12 (Decimal) +' 67890.13 (Single) --> 67890.125 (Double) +' +' Unable to convert 3.402823E+38 to Int64. +' Unable to convert 3.402823E+38 to UInt64. +' Unable to convert 3.402823E+38 to Decimal. +' 3.402823E+38 (Single) --> 3.40282346638529E+38 (Double) +' +' Unable to convert NaN to Int64. +' Unable to convert NaN to UInt64. +' Unable to convert NaN to Decimal. +' NaN (Single) --> NaN (Double) +' +' Unable to convert ∞ to Int64. +' Unable to convert ∞ to UInt64. +' Unable to convert ∞ to Decimal. +' ∞ (Single) --> ∞ (Double) +' +' Unable to convert -∞ to Int64. +' Unable to convert -∞ to UInt64. +' Unable to convert -∞ to Decimal. +' -∞ (Single) --> -∞ (Double) +' diff --git a/snippets/visualbasic/System/Single/Overview/exceptional1.vb b/snippets/visualbasic/System/Single/Overview/exceptional1.vb new file mode 100644 index 00000000000..330616d78ba --- /dev/null +++ b/snippets/visualbasic/System/Single/Overview/exceptional1.vb @@ -0,0 +1,17 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example7 + Public Sub Main() + Dim value1 As Single = 1.163287E-36 + Dim value2 As Single = 9.164234E-25 + Dim result As Single = value1 * value2 + Console.WriteLine("{0} * {1} = {2:R}", value1, value2, result) + Console.WriteLine("{0} = 0: {1}", result, result.Equals(0)) + End Sub +End Module +' The example displays the following output: +' 1.163287E-36 * 9.164234E-25 = 0 +' 0 = 0: True +' diff --git a/snippets/visualbasic/System/Single/Overview/exceptional2.vb b/snippets/visualbasic/System/Single/Overview/exceptional2.vb new file mode 100644 index 00000000000..1ef9a90b7bb --- /dev/null +++ b/snippets/visualbasic/System/Single/Overview/exceptional2.vb @@ -0,0 +1,29 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example8 + Public Sub Main() + Dim value1 As Single = 3.065E+35 + Dim value2 As Single = 6.9375E+32 + Dim result As Single = value1 * value2 + Console.WriteLine("PositiveInfinity: {0}", + Single.IsPositiveInfinity(result)) + Console.WriteLine("NegativeInfinity: {0}", + Single.IsNegativeInfinity(result)) + Console.WriteLine() + value1 = -value1 + result = value1 * value2 + Console.WriteLine("PositiveInfinity: {0}", + Single.IsPositiveInfinity(result)) + Console.WriteLine("NegativeInfinity: {0}", + Single.IsNegativeInfinity(result)) + End Sub +End Module +' The example displays the following output: +' PositiveInfinity: True +' NegativeInfinity: False +' +' PositiveInfinity: False +' NegativeInfinity: True +' diff --git a/snippets/visualbasic/System/Single/Overview/precisionlist1.vb b/snippets/visualbasic/System/Single/Overview/precisionlist1.vb new file mode 100644 index 00000000000..a5812429656 --- /dev/null +++ b/snippets/visualbasic/System/Single/Overview/precisionlist1.vb @@ -0,0 +1,13 @@ +Module Example10 + Public Sub Main() + ' + Dim value1 As Double = 1 / 3 + Dim sValue2 As Single = 1 / 3 + Dim value2 As Double = CDbl(sValue2) + Console.WriteLine("{0} = {1}: {2}", value1, value2, value1.Equals(value2)) + + ' The example displays the following output: + ' 0.3333333333333333 = 0.3333333432674408: False + ' + End Sub +End Module diff --git a/snippets/visualbasic/System/Single/Overview/precisionlist3.vb b/snippets/visualbasic/System/Single/Overview/precisionlist3.vb new file mode 100644 index 00000000000..c859ea1c29a --- /dev/null +++ b/snippets/visualbasic/System/Single/Overview/precisionlist3.vb @@ -0,0 +1,25 @@ +' Visual Basic .NET Document +Option Strict On + +Module PrecisionList3 + Public Sub Main() + ' + Dim values() As Single = {10.01, 2.88, 2.88, 2.88, 9.0} + Dim result As Single = 27.65 + Dim total As Single + For Each value In values + total += value + Next + If total.Equals(result) Then + Console.WriteLine("The sum of the values equals the total.") + Else + Console.WriteLine($"The sum of the values ({total}) does not equal the total ({result}).") + End If + End Sub + + ' The example displays the following output on .NET: + ' The sum of the values (27.650002) does not equal the total (27.65). + ' The example displays the following output on .NET Framework: + ' The sum of the values (27.65) does not equal the total (27.65). + ' +End Module diff --git a/snippets/visualbasic/System/Single/Overview/representation1.vb b/snippets/visualbasic/System/Single/Overview/representation1.vb new file mode 100644 index 00000000000..fe77569fa9a --- /dev/null +++ b/snippets/visualbasic/System/Single/Overview/representation1.vb @@ -0,0 +1,22 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example13 + Public Sub Main() + Dim value As Single = 0.2 + Dim result1 As Single = value * 10 + Dim result2 As Single + For ctr As Integer = 1 To 10 + result2 += value + Next + Console.WriteLine(".2 * 10: {0:R}", result1) + Console.WriteLine(".2 Added 10 times: {0:R}", result2) + End Sub +End Module + +' The example displays the following output: +' .2 * 10: 2 +' .2 Added 10 times: 2.0000002 +' + diff --git a/snippets/visualbasic/System/Single/Overview/representation2.vb b/snippets/visualbasic/System/Single/Overview/representation2.vb new file mode 100644 index 00000000000..3b44c2f25c6 --- /dev/null +++ b/snippets/visualbasic/System/Single/Overview/representation2.vb @@ -0,0 +1,15 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example + Public Sub Main() + Dim value As Single = 123.456 + Dim additional As Single = Single.Epsilon * 1e15 + Console.WriteLine($"{value} + {additional} = {value + additional}") + End Sub +End Module +' The example displays the following output: +' 123.456 + 1.401298E-30 = 123.456 +' + diff --git a/snippets/visualbasic/System/String/.ctor/Project.vbproj b/snippets/visualbasic/System/String/.ctor/Project.vbproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/visualbasic/System/String/.ctor/Project.vbproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/visualbasic/System/String/.ctor/ctor1.vb b/snippets/visualbasic/System/String/.ctor/ctor1.vb new file mode 100644 index 00000000000..07eb0b334d4 --- /dev/null +++ b/snippets/visualbasic/System/String/.ctor/ctor1.vb @@ -0,0 +1,16 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example + Public Sub Main() + Dim value1 As String = "This is a string." + Dim value2 As String = value1 + Console.WriteLine(value1) + Console.WriteLine(value2) + End Sub +End Module +' The example displays the following output: +' This is a string. +' This is a string. +' diff --git a/snippets/visualbasic/System/String/.ctor/source.vb b/snippets/visualbasic/System/String/.ctor/source.vb new file mode 100644 index 00000000000..822f09067ac --- /dev/null +++ b/snippets/visualbasic/System/String/.ctor/source.vb @@ -0,0 +1,47 @@ +Option Strict On + +Imports System.Text + +Class ConsoleApp + Public Shared Sub Main() + ' + ' Unicode Mathematical operators + Dim charArr1() As Char = {ChrW(&H2200), ChrW(&H2202), _ + ChrW(&H200F), ChrW(&H2205)} + Dim szMathSymbols As New String(charArr1) + + ' Unicode Letterlike Symbols + Dim charArr2() As Char = {ChrW(&H2111), ChrW(&H2118), _ + ChrW(&H2122), ChrW(&H2126)} + Dim szLetterLike As New String(charArr2) + + ' Compare Strings - the result is false + Console.WriteLine("The strings are equal? " & _ + CStr(szMathSymbols.Equals(szLetterLike))) + ' + + ' + ' Create a Unicode String with 5 Greek Alpha characters + Dim szGreekAlpha As New String(ChrW(&H0391), 5) + ' Create a Unicode String with a Greek Omega character + Dim szGreekOmega As New String(New Char() {ChrW(&H03A9), ChrW(&H03A9), _ + ChrW(&H03A9)}, 2, 1) + + Dim szGreekLetters As String = String.Concat(szGreekOmega, szGreekAlpha, _ + szGreekOmega.Clone()) + + ' Examine the result + Console.WriteLine(szGreekLetters) + + ' The first index of Alpha + Dim iAlpha As Integer = szGreekLetters.IndexOf(ChrW(&H0391)) + ' The last index of Omega + Dim iomega As Integer = szGreekLetters.LastIndexOf(ChrW(&H03A9)) + + Console.WriteLine("The Greek letter Alpha first appears at index {0}.", _ + ialpha) + Console.WriteLIne("The Greek letter Omega last appears at index {0}.", _ + iomega) + ' + End Sub +End Class diff --git a/snippets/visualbasic/System/String/Format/Example1.vb b/snippets/visualbasic/System/String/Format/Example1.vb new file mode 100644 index 00000000000..25f6752711a --- /dev/null +++ b/snippets/visualbasic/System/String/Format/Example1.vb @@ -0,0 +1,24 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example1 + Public Sub Main() + Dim values() As Short = {Int16.MinValue, -27, 0, 1042, Int16.MaxValue} + Console.WriteLine("{0,10} {1,10}", "Decimal", "Hex") + Console.WriteLine() + For Each value As Short In values + Dim formatString As String = String.Format("{0,10:G}: {0,10:X}", value) + Console.WriteLine(formatString) + Next + End Sub +End Module +' The example displays the following output: +' Decimal Hex +' +' -32768: 8000 +' -27: FFE5 +' 0: 0 +' 1042: 412 +' 32767: 7FFF +' diff --git a/snippets/visualbasic/System/String/Format/Example2.vb b/snippets/visualbasic/System/String/Format/Example2.vb index 240bb492eea..6c7b7168da2 100644 --- a/snippets/visualbasic/System/String/Format/Example2.vb +++ b/snippets/visualbasic/System/String/Format/Example2.vb @@ -4,26 +4,26 @@ Option Strict On ' Imports System.Globalization -Module Example +Module Example2 Public Sub Main() Dim cultureNames() As String = { "en-US", "fr-FR", "de-DE", "es-ES" } - + Dim dateToDisplay As Date = #9/1/2009 6:32PM# Dim value As Double = 9164.32 Console.WriteLine("Culture Date Value") - Console.WriteLine() + Console.WriteLine() For Each cultureName As String In cultureNames Dim culture As New CultureInfo(cultureName) Dim output As String = String.Format(culture, "{0,-11} {1,-35:D} {2:N}", _ culture.Name, dateToDisplay, value) Console.WriteLine(output) - Next + Next End Sub End Module ' The example displays the following output: ' Culture Date Value -' +' ' en-US Tuesday, September 01, 2009 9,164.32 ' fr-FR mardi 1 septembre 2009 9 164,32 ' de-DE Dienstag, 1. September 2009 9.164,32 diff --git a/snippets/visualbasic/System/String/Format/FormatExample2.vb b/snippets/visualbasic/System/String/Format/FormatExample2.vb new file mode 100644 index 00000000000..26b3a3e6e19 --- /dev/null +++ b/snippets/visualbasic/System/String/Format/FormatExample2.vb @@ -0,0 +1,69 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module TestFormatter + Public Sub Main() + Dim acctNumber As Integer = 79203159 + Console.WriteLine(String.Format(New CustomerFormatter, "{0}", acctNumber)) + Console.WriteLine(String.Format(New CustomerFormatter, "{0:G}", acctNumber)) + Console.WriteLine(String.Format(New CustomerFormatter, "{0:S}", acctNumber)) + Console.WriteLine(String.Format(New CustomerFormatter, "{0:P}", acctNumber)) + Try + Console.WriteLine(String.Format(New CustomerFormatter, "{0:X}", acctNumber)) + Catch e As FormatException + Console.WriteLine(e.Message) + End Try + End Sub +End Module + +Public Class CustomerFormatter : Implements IFormatProvider, ICustomFormatter + Public Function GetFormat(type As Type) As Object _ + Implements IFormatProvider.GetFormat + If type Is GetType(ICustomFormatter) Then + Return Me + Else + Return Nothing + End If + End Function + + Public Function Format(fmt As String, _ + arg As Object, _ + formatProvider As IFormatProvider) As String _ + Implements ICustomFormatter.Format + If Not Me.Equals(formatProvider) Then + Return Nothing + Else + If String.IsNullOrEmpty(fmt) Then fmt = "G" + + Dim customerString As String = arg.ToString() + if customerString.Length < 8 Then _ + customerString = customerString.PadLeft(8, "0"c) + + Select Case fmt + Case "G" + Return customerString.Substring(0, 1) & "-" & _ + customerString.Substring(1, 5) & "-" & _ + customerString.Substring(6) + Case "S" + Return customerString.Substring(0, 1) & "/" & _ + customerString.Substring(1, 5) & "/" & _ + customerString.Substring(6) + Case "P" + Return customerString.Substring(0, 1) & "." & _ + customerString.Substring(1, 5) & "." & _ + customerString.Substring(6) + Case Else + Throw New FormatException( _ + String.Format("The '{0}' format specifier is not supported.", fmt)) + End Select + End If + End Function +End Class +' The example displays the following output: +' 7-92031-59 +' 7-92031-59 +' 7/92031/59 +' 7.92031.59 +' The 'X' format specifier is not supported. +' diff --git a/snippets/visualbasic/System/String/Format/Project.vbproj b/snippets/visualbasic/System/String/Format/Project.vbproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/visualbasic/System/String/Format/Project.vbproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/visualbasic/System/String/Format/formatoverload1.vb b/snippets/visualbasic/System/String/Format/formatoverload1.vb new file mode 100644 index 00000000000..5efa59a782a --- /dev/null +++ b/snippets/visualbasic/System/String/Format/formatoverload1.vb @@ -0,0 +1,18 @@ +' Visual Basic .NET Document +Option Strict On + +Module Example3 + Public Sub Main() + ' + Dim dat As Date = #1/17/2012 9:30AM# + Dim city As String = "Chicago" + Dim temp As Integer = -16 + Dim output As String = String.Format("At {0} in {1}, the temperature was {2} degrees.", + dat, city, temp) + Console.WriteLine(output) + ' The example displays the following output: + ' At 1/17/2012 9:30:00 AM in Chicago, the temperature was -16 degrees. + ' + End Sub +End Module + diff --git a/snippets/visualbasic/System/String/Format/formatoverload2.vb b/snippets/visualbasic/System/String/Format/formatoverload2.vb new file mode 100644 index 00000000000..d1067b3b567 --- /dev/null +++ b/snippets/visualbasic/System/String/Format/formatoverload2.vb @@ -0,0 +1,35 @@ +' Visual Basic .NET Document +Option Strict On +Option Infer On + +' +Module Example4 + Public Sub Main() + ' Create array of 5-tuples with population data for three U.S. cities, 1940-1950. + Dim cities() = + {Tuple.Create("Los Angeles", #1/1/1940#, 1504277, #1/1/1950#, 1970358), + Tuple.Create("New York", #1/1/1940#, 7454995, #1/1/1950#, 7891957), + Tuple.Create("Chicago", #1/1/1940#, 3396808, #1/1/1950#, 3620962), + Tuple.Create("Detroit", #1/1/1940#, 1623452, #1/1/1950#, 1849568)} + + ' Display header + Dim header As String = String.Format("{0,-12}{1,8}{2,12}{1,8}{2,12}{3,14}", + "City", "Year", "Population", "Change (%)") + Console.WriteLine(header) + Console.WriteLine() + For Each city In cities + Dim output = String.Format("{0,-12}{1,8:yyyy}{2,12:N0}{3,8:yyyy}{4,12:N0}{5,14:P1}", + city.Item1, city.Item2, city.Item3, city.Item4, city.Item5, + (city.Item5 - city.Item3) / city.Item3) + Console.WriteLine(output) + Next + End Sub +End Module +' The example displays the following output: +' City Year Population Year Population Change (%) +' +' Los Angeles 1940 1,504,277 1950 1,970,358 31.0 % +' New York 1940 7,454,995 1950 7,891,957 5.9 % +' Chicago 1940 3,396,808 1950 3,620,962 6.6 % +' Detroit 1940 1,623,452 1950 1,849,568 13.9 % +' diff --git a/snippets/visualbasic/System/String/Format/formatsyntax1.vb b/snippets/visualbasic/System/String/Format/formatsyntax1.vb new file mode 100644 index 00000000000..701f842ff8c --- /dev/null +++ b/snippets/visualbasic/System/String/Format/formatsyntax1.vb @@ -0,0 +1,12 @@ +' Visual Basic .NET Document +Option Strict On + +Module Example5 + Public Sub Main() + 'Dim value As String = + ' + String.Format("{0,-10:C}", 126347.89D) + ' + End Sub +End Module + diff --git a/snippets/visualbasic/System/String/Format/interceptor2.vb b/snippets/visualbasic/System/String/Format/interceptor2.vb new file mode 100644 index 00000000000..a52aaf9e61f --- /dev/null +++ b/snippets/visualbasic/System/String/Format/interceptor2.vb @@ -0,0 +1,120 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Globalization + +Public Class InterceptProvider : Implements IFormatProvider, ICustomFormatter + Public Function GetFormat(formatType As Type) As Object _ + Implements IFormatProvider.GetFormat + If formatType Is GetType(ICustomFormatter) Then + Return Me + Else + Return Nothing + End If + End Function + + Public Function Format(fmt As String, obj As Object, provider As IFormatProvider) As String _ + Implements ICustomFormatter.Format + + Dim formatString As String = If(fmt IsNot Nothing, fmt, "") + Console.WriteLine("Provider: {0}, Object: {1}, Format String: {2}", + provider, If(obj IsNot Nothing, obj, ""), formatString) + + If obj Is Nothing Then Return String.Empty + + ' If this is a byte and the "R" format string, format it with Roman numerals. + If TypeOf(obj) Is Byte AndAlso formatString.ToUpper.Equals("R") Then + Dim value As Byte = CByte(obj) + Dim remainder As Integer + Dim result As Integer + Dim returnString As String = String.Empty + + ' Get the hundreds digit(s) + result = Math.DivRem(value, 100, remainder) + If result > 0 Then returnString = New String("C"c, result) + value = CByte(remainder) + ' Get the 50s digit + result = Math.DivRem(value, 50, remainder) + If result = 1 Then returnString += "L" + value = CByte(remainder) + ' Get the tens digit. + result = Math.DivRem(value, 10, remainder) + If result > 0 Then returnString += New String("X"c, result) + value = CByte(remainder) + ' Get the fives digit. + result = Math.DivRem(value, 5, remainder) + If result > 0 Then returnString += "V" + value = CByte(remainder) + ' Add the ones digit. + If remainder > 0 Then returnString += New String("I"c, remainder) + + ' Check whether we have too many X characters. + Dim pos As Integer = returnString.IndexOf("XXXX") + If pos >= 0 Then + Dim xPos As Integer = returnString.IndexOf("L") + If xPos >= 0 And xPos = pos - 1 Then + returnString = returnString.Replace("LXXXX", "XC") + Else + returnString = returnString.Replace("XXXX", "XL") + End If + End If + ' Check whether we have too many I characters + pos = returnString.IndexOf("IIII") + If pos >= 0 Then + If returnString.IndexOf("V") >= 0 Then + returnString = returnString.Replace("VIIII", "IX") + Else + returnString = returnString.Replace("IIII", "IV") + End If + End If + Return returnString + End If + + ' Use default for all other formatting. + If TypeOf obj Is IFormattable Then + Return CType(obj, IFormattable).ToString(fmt, CultureInfo.CurrentCulture) + Else + Return obj.ToString() + End If + End Function +End Class + +Module Example + Public Sub Main() + Dim n As Integer = 10 + Dim value As Double = 16.935 + Dim day As DateTime = Date.Now + Dim provider As New InterceptProvider() + Console.WriteLine(String.Format(provider, "{0:N0}: {1:C2} on {2:d}", n, value, day)) + Console.WriteLine() + Console.WriteLine(String.Format(provider, "{0}: {1:F}", "Today", + CType(Date.Now.DayOfWeek, DayOfWeek))) + Console.WriteLine() + Console.WriteLine(String.Format(provider, "{0:X}, {1}, {2}\n", + CByte(2), CByte(12), CByte(199))) + Console.WriteLine() + Console.WriteLine(String.Format(provider, "{0:R}, {1:R}, {2:R}", + CByte(2), CByte(12), CByte(199))) + End Sub +End Module +' The example displays the following output: +' Provider: InterceptProvider, Object: 10, Format String: N0 +' Provider: InterceptProvider, Object: 16.935, Format String: C2 +' Provider: InterceptProvider, Object: 1/31/2013 6:10:28 PM, Format String: d +' 10: $16.94 on 1/31/2013 +' +' Provider: InterceptProvider, Object: Today: , Format String: +' Provider: InterceptProvider, Object: Thursday, Format String: F +' Today: : Thursday +' +' Provider: InterceptProvider, Object: 2, Format String: X +' Provider: InterceptProvider, Object: 12, Format String: +' Provider: InterceptProvider, Object: 199, Format String: +' 2, 12, 199 +' +' Provider: InterceptProvider, Object: 2, Format String: R +' Provider: InterceptProvider, Object: 12, Format String: R +' Provider: InterceptProvider, Object: 199, Format String: R +' II, XII, CXCIX +' diff --git a/snippets/visualbasic/System/String/Format/qa-interpolated1.vb b/snippets/visualbasic/System/String/Format/qa-interpolated1.vb new file mode 100644 index 00000000000..7444b0bf30a --- /dev/null +++ b/snippets/visualbasic/System/String/Format/qa-interpolated1.vb @@ -0,0 +1,20 @@ + +Module Example12 + Public Sub Main() + Dim names = {"Balto", "Vanya", "Dakota", "Samuel", "Koani", "Yiska", "Yuma"} + Dim output = names(0) + ", " + names(1) + ", " + names(2) + ", " + + names(3) + ", " + names(4) + ", " + names(5) + ", " + + names(6) + + output += vbCrLf + Dim dat = DateTime.Now + output += String.Format("It is {0:t} on {0:d}. The day of the week is {1}.", + dat, dat.DayOfWeek) + Console.WriteLine(output) + End Sub +End Module +' The example displays the following output: +' Balto, Vanya, Dakota, Samuel, Koani, Yiska, Yuma +' It is 10:29 AM on 1/8/2018. The day of the week is Monday. + + diff --git a/snippets/visualbasic/System/String/Format/qa-interpolated2.vb b/snippets/visualbasic/System/String/Format/qa-interpolated2.vb new file mode 100644 index 00000000000..9f4953e45f3 --- /dev/null +++ b/snippets/visualbasic/System/String/Format/qa-interpolated2.vb @@ -0,0 +1,17 @@ + +Module Example13 + Public Sub Main() + Dim names = {"Balto", "Vanya", "Dakota", "Samuel", "Koani", "Yiska", "Yuma"} + Dim output = $"{names(0)}, {names(1)}, {names(2)}, {names(3)}, {names(4)}, " + + $"{names(5)}, {names(6)}" + + Dim dat = DateTime.Now + output += $"{vbCrLf}It is {dat:t} on {dat:d}. The day of the week is {dat.DayOfWeek}." + Console.WriteLine(output) + End Sub +End Module +' The example displays the following output: +' Balto, Vanya, Dakota, Samuel, Koani, Yiska, Yuma +' It is 10:29 AM on 1/8/2018. The day of the week is Monday. + + diff --git a/snippets/visualbasic/System/String/Format/qa1.vb b/snippets/visualbasic/System/String/Format/qa1.vb new file mode 100644 index 00000000000..66e34573cf0 --- /dev/null +++ b/snippets/visualbasic/System/String/Format/qa1.vb @@ -0,0 +1,20 @@ +' Visual Basic .NET Document +Option Strict On + +' + +Module Example5a + Public Sub Main() + Dim rnd As New Random() + Dim numbers(3) As Integer + Dim total As Integer = 0 + For ctr = 0 To 2 + Dim number As Integer = rnd.Next(1001) + numbers(ctr) = number + total += number + Next + numbers(3) = total + Console.WriteLine("{0} + {1} + {2} = {3}", numbers) + End Sub +End Module +' diff --git a/snippets/visualbasic/System/String/Format/qa2.vb b/snippets/visualbasic/System/String/Format/qa2.vb new file mode 100644 index 00000000000..969c9664337 --- /dev/null +++ b/snippets/visualbasic/System/String/Format/qa2.vb @@ -0,0 +1,25 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Collections.Generic + +Module Example6 + Public Sub Main() + Dim rnd As New Random() + Dim numbers(3) As Integer + Dim total As Integer = 0 + For ctr = 0 To 2 + Dim number As Integer = rnd.Next(1001) + numbers(ctr) = number + total += number + Next + numbers(3) = total + Dim values(numbers.Length - 1) As Object + numbers.CopyTo(values, 0) + Console.WriteLine("{0} + {1} + {2} = {3}", values) + End Sub +End Module +' + + diff --git a/snippets/visualbasic/System/String/Format/qa26.vb b/snippets/visualbasic/System/String/Format/qa26.vb new file mode 100644 index 00000000000..eab0d501593 --- /dev/null +++ b/snippets/visualbasic/System/String/Format/qa26.vb @@ -0,0 +1,23 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example7 + Public Sub Main() + Dim values() As Object = {1603, 1794.68235, 15436.14} + Dim result As String + For Each value In values + result = String.Format("{0,12:C2} {0,12:E3} {0,12:F4} {0,12:N3} {1,12:P2}", + value, CDbl(value) / 10000) + Console.WriteLine(result) + Console.WriteLine() + Next + End Sub +End Module +' The example displays the following output: +' $1,603.00 1.603E+003 1603.0000 1,603.000 16.03 % +' +' $1,794.68 1.795E+003 1794.6824 1,794.682 17.95 % +' +' $15,436.14 1.544E+004 15436.1400 15,436.140 154.36 % +' diff --git a/snippets/visualbasic/System/String/Format/qa27.vb b/snippets/visualbasic/System/String/Format/qa27.vb new file mode 100644 index 00000000000..faf15d373a3 --- /dev/null +++ b/snippets/visualbasic/System/String/Format/qa27.vb @@ -0,0 +1,16 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example8 + Public Sub Main() + Dim value As Decimal = 16309.5436D + Dim result As String = String.Format("{0,12:#.00000} {0,12:0,000.00} {0,12:000.00#}", + value) + Console.WriteLine(result) + End Sub +End Module +' The example displays the following output: +' 16309.54360 16,309.54 16309.544 +' + diff --git a/snippets/visualbasic/System/String/Format/qa28.vb b/snippets/visualbasic/System/String/Format/qa28.vb new file mode 100644 index 00000000000..9612caac6ff --- /dev/null +++ b/snippets/visualbasic/System/String/Format/qa28.vb @@ -0,0 +1,16 @@ +'Visual Basic .NET Document + +Option Strict On + +' +Module Example9 + Public Sub Main() + Dim value As Integer = 16342 + Dim result As String = String.Format("{0,18:00000000} {0,18:00000000.000} {0,18:000,0000,000.0}", + value) + Console.WriteLine(result) + End Sub +End Module +' The example displays the following output: +' 00016342 00016342.000 0,000,016,342.0 +' diff --git a/snippets/visualbasic/System/String/Format/qa29.vb b/snippets/visualbasic/System/String/Format/qa29.vb new file mode 100644 index 00000000000..70e558104aa --- /dev/null +++ b/snippets/visualbasic/System/String/Format/qa29.vb @@ -0,0 +1,14 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example10 + Public Sub Main() + Dim value As Integer = 1326 + Dim result As String = String.Format("{0,10:D6} {0,10:X8}", value) + Console.WriteLine(result) + End Sub +End Module +' The example displays the following output: +' 001326 0000052E +' diff --git a/snippets/visualbasic/System/String/Format/qa3.vb b/snippets/visualbasic/System/String/Format/qa3.vb new file mode 100644 index 00000000000..22254d6772b --- /dev/null +++ b/snippets/visualbasic/System/String/Format/qa3.vb @@ -0,0 +1,58 @@ +' Visual Basic .NET Document +Option Strict On + +Module Example11 + Public Sub Main() + WillThrow() + Console.WriteLine() + WontThrow() + Console.WriteLine() + Recommended() + End Sub + + Public Sub WillThrow() + Dim result As String + Dim nOpen As Integer = 1 + Dim nClose As Integer = 2 + Try + ' + result = String.Format("The text has {0} '{' characters and {1} '}' characters.", + nOpen, nClose) + ' + Console.WriteLine(result) + Catch e As FormatException + Console.WriteLine("FormatException") + End Try + End Sub + + Public Sub WontThrow() + Dim result As String + Dim nOpen As Integer = 1 + Dim nClose As Integer = 2 + Try + ' + result = String.Format("The text has {0} '{{' characters and {1} '}}' characters.", + nOpen, nClose) + ' + Console.WriteLine(result) + Catch e As FormatException + Console.WriteLine("FormatException") + End Try + End Sub + + Public Sub Recommended() + Dim result As String + Dim nOpen As Integer = 1 + Dim nClose As Integer = 2 + Try + ' + result = String.Format("The text has {0} '{1}' characters and {2} '{3}' characters.", + nOpen, "{", nClose, "}") + ' + Console.WriteLine(result) + Catch e As FormatException + Console.WriteLine("FormatException") + End Try + End Sub +End Module + diff --git a/snippets/visualbasic/System/String/Format/starting1.vb b/snippets/visualbasic/System/String/Format/starting1.vb new file mode 100644 index 00000000000..692f6eb6270 --- /dev/null +++ b/snippets/visualbasic/System/String/Format/starting1.vb @@ -0,0 +1,80 @@ +' Visual Basic .NET Document +Option Strict On + +Imports System.Text + +Module Example14 + Public Sub Main() + ' + Dim temp As Decimal = 20.4D + Dim s As String = String.Format("The temperature is {0}°C.", temp) + Console.WriteLine(s) + ' Displays 'The temperature is 20.4°C.' + ' + + Snippet31() + Snippet32() + Snippet33() + Snippet34() + End Sub + + Private Sub Snippet31() + ' + Dim s As String = String.Format("At {0}, the temperature is {1}°C.", + Date.Now, 20.4) + ' Output similar to: 'At 4/10/2015 9:29:41 AM, the temperature is 20.4°C.' + ' + Console.WriteLine(s) + End Sub + + Private Sub Snippet32() + ' + Dim s As String = String.Format("It is now {0:d} at {0:t}", + Date.Now) + ' Output similar to: 'It is now 4/10/2015 at 10:04 AM' + ' + Console.WriteLine(s) + End Sub + + Private Sub Snippet33() + ' + Dim years() As Integer = {2013, 2014, 2015} + Dim population() As Integer = {1025632, 1105967, 1148203} + Dim sb As New StringBuilder() + sb.Append(String.Format("{0,6} {1,15}{2}{2}", + "Year", "Population", vbCrLf)) + For index As Integer = 0 To years.Length - 1 + sb.AppendFormat("{0,6} {1,15:N0}{2}", + years(index), population(index), vbCrLf) + Next + ' Result: + ' Year Population + ' + ' 2013 1,025,632 + ' 2014 1,105,967 + ' 2015 1,148,203 + ' + Console.WriteLine(sb) + End Sub + + Private Sub Snippet34() + ' + Dim years() As Integer = {2013, 2014, 2015} + Dim population() As Integer = {1025632, 1105967, 1148203} + Dim s As String = String.Format("{0,-10} {1,-10}{2}{2}", + "Year", "Population", vbCrLf) + For index As Integer = 0 To years.Length - 1 + s += String.Format("{0,-10} {1,-10:N0}{2}", + years(index), population(index), vbCrLf) + Next + ' Result: + ' Year Population + ' + ' 2013 1,025,632 + ' 2014 1,105,967 + ' 2015 1,148,203 + ' + Console.WriteLine(vbCrLf + s) + End Sub +End Module + diff --git a/snippets/visualbasic/System/String/Format/starting2.vb b/snippets/visualbasic/System/String/Format/starting2.vb new file mode 100644 index 00000000000..9267fd49bae --- /dev/null +++ b/snippets/visualbasic/System/String/Format/starting2.vb @@ -0,0 +1,27 @@ +' Visual Basic .NET Document +Option Strict On + +Module Example15 + Public Sub Main() + ' + Dim pricePerOunce As Decimal = 17.36D + Dim s As String = String.Format("The current price is {0} per ounce.", + pricePerOunce) + ' Result: The current price is 17.36 per ounce. + ' + Console.WriteLine(s) + ShowFormatted() + End Sub + + Private Sub ShowFormatted() + ' + Dim pricePerOunce As Decimal = 17.36D + Dim s As String = String.Format("The current price is {0:C2} per ounce.", + pricePerOunce) + ' Result if current culture is en-US: + ' The current price is $17.36 per ounce. + ' + Console.WriteLine(s) + End Sub +End Module + diff --git a/snippets/visualbasic/System/String/Intern/Intern1.vb b/snippets/visualbasic/System/String/Intern/Intern1.vb new file mode 100644 index 00000000000..cf5eb1e1d28 --- /dev/null +++ b/snippets/visualbasic/System/String/Intern/Intern1.vb @@ -0,0 +1,18 @@ +' Visual Basic .NET Document +Option Strict On + +Imports System.Text + + +Module modMain + Public Sub Main() + ' + Dim s1 As String = "MyTest" + Dim s2 As String = New StringBuilder().Append("My").Append("Test").ToString() + Dim s3 As String = String.Intern(s2) + Console.WriteLine(CObj(s2) Is CObj(s1)) ' Different references. + Console.WriteLine(CObj(s3) Is CObj(s1)) ' The same reference. + ' + End Sub +End Module + diff --git a/snippets/visualbasic/System/String/Intern/string_intern.vb b/snippets/visualbasic/System/String/Intern/string_intern.vb index c8805b9125a..f007a8cece7 100644 --- a/snippets/visualbasic/System/String/Intern/string_intern.vb +++ b/snippets/visualbasic/System/String/Intern/string_intern.vb @@ -3,7 +3,7 @@ Imports System.Text Class Sample - Public Shared Sub Main() + Public Shared Sub Run() Dim s1 As String = New StringBuilder().Append("My").Append("Test").ToString() Dim s2 As String = New StringBuilder().Append("My").Append("Test").ToString() Console.WriteLine($"s1 = {s1}") diff --git a/snippets/visualbasic/System/String/IsNullOrEmpty/NullString1.vb b/snippets/visualbasic/System/String/IsNullOrEmpty/NullString1.vb new file mode 100644 index 00000000000..dbb4879f8dc --- /dev/null +++ b/snippets/visualbasic/System/String/IsNullOrEmpty/NullString1.vb @@ -0,0 +1,34 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example + Public Sub Main3() + Dim s As String + + Console.WriteLine("The value of the string is '{0}'", s) + + Try + Console.WriteLine("String length is {0}", s.Length) + Catch e As NullReferenceException + Console.WriteLine(e.Message) + End Try + End Sub +End Module +' The example displays the following output: +' The value of the string is '' +' Object reference not set to an instance of an object. +' + +Public Class Empty + Public Sub Test() + ' + Dim s As String = "" + Console.WriteLine("The length of '{0}' is {1}.", s, s.Length) + ' The example displays the following output: + ' The length of '' is 0. + ' + End Sub +End Class + + diff --git a/snippets/visualbasic/System/String/IsNullOrEmpty/isnullorempty1.vb b/snippets/visualbasic/System/String/IsNullOrEmpty/isnullorempty1.vb new file mode 100644 index 00000000000..da31b0e6466 --- /dev/null +++ b/snippets/visualbasic/System/String/IsNullOrEmpty/isnullorempty1.vb @@ -0,0 +1,20 @@ +' Visual Basic .NET Document +Option Strict On + +Module Example1 + Public Sub Main1() + Dim s1 As String = Nothing + Dim s2 As String = "" + Console.WriteLine(TestForNullOrEmpty(s1)) + Console.WriteLine(TestForNullOrEmpty(s2)) + End Sub + + Private Function TestForNullOrEmpty(s As String) As Boolean + Dim result As Boolean + ' + result = s Is Nothing OrElse s = String.Empty + ' + Return result + End Function +End Module + diff --git a/snippets/visualbasic/System/String/Overview/Project.vbproj b/snippets/visualbasic/System/String/Overview/Project.vbproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/visualbasic/System/String/Overview/Project.vbproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/visualbasic/System/String/Overview/case1.vb b/snippets/visualbasic/System/String/Overview/case1.vb new file mode 100644 index 00000000000..3c508dc5a1b --- /dev/null +++ b/snippets/visualbasic/System/String/Overview/case1.vb @@ -0,0 +1,57 @@ +' Visual Basic .NET Document +Option Strict On +Option Infer On + +' +Imports System.Globalization +Imports System.IO + +Module Example1 + Public Sub Main() + Dim sw As New StreamWriter(".\case.txt") + Dim words As String() = {"file", "sıfır", "Dženana"} + Dim cultures() As CultureInfo = {CultureInfo.InvariantCulture, + New CultureInfo("en-US"), + New CultureInfo("tr-TR")} + + For Each word In words + sw.WriteLine("{0}:", word) + For Each culture In cultures + Dim name As String = If(String.IsNullOrEmpty(culture.Name), + "Invariant", culture.Name) + Dim upperWord As String = word.ToUpper(culture) + sw.WriteLine(" {0,10}: {1,7} {2, 38}", name, + upperWord, ShowHexValue(upperWord)) + + Next + sw.WriteLine() + Next + sw.Close() + End Sub + + Private Function ShowHexValue(s As String) As String + Dim retval As String = Nothing + For Each ch In s + Dim bytes() As Byte = BitConverter.GetBytes(ch) + retval += String.Format("{0:X2} {1:X2} ", bytes(1), bytes(0)) + Next + Return retval + End Function +End Module +' The example displays the following output: +' file: +' Invariant: FILE 00 46 00 49 00 4C 00 45 +' en-US: FILE 00 46 00 49 00 4C 00 45 +' tr-TR: FİLE 00 46 01 30 00 4C 00 45 +' +' sıfır: +' Invariant: SıFıR 00 53 01 31 00 46 01 31 00 52 +' en-US: SIFIR 00 53 00 49 00 46 00 49 00 52 +' tr-TR: SIFIR 00 53 00 49 00 46 00 49 00 52 +' +' Dženana: +' Invariant: DžENANA 01 C5 00 45 00 4E 00 41 00 4E 00 41 +' en-US: DŽENANA 01 C4 00 45 00 4E 00 41 00 4E 00 41 +' tr-TR: DŽENANA 01 C4 00 45 00 4E 00 41 00 4E 00 41 +' + diff --git a/snippets/visualbasic/System/String/Overview/case2.vb b/snippets/visualbasic/System/String/Overview/case2.vb new file mode 100644 index 00000000000..72954381ab8 --- /dev/null +++ b/snippets/visualbasic/System/String/Overview/case2.vb @@ -0,0 +1,41 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Globalization +Imports System.Threading + +Module Example2 + Const disallowed = "file" + + Public Sub Main() + IsAccessAllowed("FILE:\\\c:\users\user001\documents\FinancialInfo.txt") + End Sub + + Private Sub IsAccessAllowed(resource As String) + Dim cultures() As CultureInfo = {CultureInfo.CreateSpecificCulture("en-US"), + CultureInfo.CreateSpecificCulture("tr-TR")} + Dim scheme As String = Nothing + Dim index As Integer = resource.IndexOfAny({"\"c, "/"c}) + If index > 0 Then scheme = resource.Substring(0, index - 1) + + ' Change the current culture and perform the comparison. + For Each culture In cultures + Thread.CurrentThread.CurrentCulture = culture + Console.WriteLine("Culture: {0}", CultureInfo.CurrentCulture.DisplayName) + Console.WriteLine(resource) + Console.WriteLine("Access allowed: {0}", + Not String.Equals(disallowed, scheme, StringComparison.CurrentCultureIgnoreCase)) + Console.WriteLine() + Next + End Sub +End Module +' The example displays the following output: +' Culture: English (United States) +' FILE:\\\c:\users\user001\documents\FinancialInfo.txt +' Access allowed: False +' +' Culture: Turkish (Turkey) +' FILE:\\\c:\users\user001\documents\FinancialInfo.txt +' Access allowed: True +' diff --git a/snippets/visualbasic/System/String/Overview/compare1.vb b/snippets/visualbasic/System/String/Overview/compare1.vb new file mode 100644 index 00000000000..3ddd13df075 --- /dev/null +++ b/snippets/visualbasic/System/String/Overview/compare1.vb @@ -0,0 +1,18 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Globalization +Imports System.Threading + +Module Example3 + Public Sub Main() + Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US") + Console.WriteLine(String.Compare("A", "a", StringComparison.CurrentCulture)) + Console.WriteLine(String.Compare("A", "a", StringComparison.Ordinal)) + End Sub +End Module +' The example displays the following output: +' 1 +' -32 +' diff --git a/snippets/visualbasic/System/String/Overview/compare2.vb b/snippets/visualbasic/System/String/Overview/compare2.vb new file mode 100644 index 00000000000..13abcbc847a --- /dev/null +++ b/snippets/visualbasic/System/String/Overview/compare2.vb @@ -0,0 +1,66 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Collections +Imports System.Collections.Generic +Imports System.Globalization + +Module Example4 + Public Sub Main() + Dim strings() As String = {"coop", "co-op", "cooperative", + "co" + ChrW(&HAD) + "operative", + "cœur", "coeur"} + + ' Perform a word sort using the current (en-US) culture. + Dim current(strings.Length - 1) As String + strings.CopyTo(current, 0) + Array.Sort(current, StringComparer.CurrentCulture) + + ' Perform a word sort using the invariant culture. + Dim invariant(strings.Length - 1) As String + strings.CopyTo(invariant, 0) + Array.Sort(invariant, StringComparer.InvariantCulture) + + ' Perform an ordinal sort. + Dim ordinal(strings.Length - 1) As String + strings.CopyTo(ordinal, 0) + Array.Sort(ordinal, StringComparer.Ordinal) + + ' Perform a string sort using the current culture. + Dim stringSort(strings.Length - 1) As String + strings.CopyTo(stringSort, 0) + Array.Sort(stringSort, New SCompare()) + + ' Display array values + Console.WriteLine("{0,13} {1,13} {2,15} {3,13} {4,13}", + "Original", "Word Sort", "Invariant Word", + "Ordinal Sort", "String Sort") + Console.WriteLine() + + For ctr As Integer = 0 To strings.Length - 1 + Console.WriteLine("{0,13} {1,13} {2,15} {3,13} {4,13}", + strings(ctr), current(ctr), invariant(ctr), + ordinal(ctr), stringSort(ctr)) + Next + End Sub +End Module + +' IComparer implementation to perform string sort. +Friend Class SCompare : Implements IComparer(Of String) + Public Function Compare(x As String, y As String) As Integer _ + Implements IComparer(Of String).Compare + Return CultureInfo.CurrentCulture.CompareInfo.Compare(x, y, CompareOptions.StringSort) + End Function +End Class +' The example displays the following output: +' Original Word Sort Invariant Word Ordinal Sort String Sort +' +' coop cœur cœur co-op co-op +' co-op coeur coeur coeur cœur +' cooperative coop coop coop coeur +' co­operative co-op co-op cooperative coop +' cœur cooperative cooperative co­operative cooperative +' coeur co­operative co­operative cœur co­operative +' + diff --git a/snippets/visualbasic/System/String/Overview/compare3.vb b/snippets/visualbasic/System/String/Overview/compare3.vb new file mode 100644 index 00000000000..c8529fc8a23 --- /dev/null +++ b/snippets/visualbasic/System/String/Overview/compare3.vb @@ -0,0 +1,42 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example5 + Public Sub Main() + ' Search for "oe" and "œu" in "œufs" and "oeufs". + Dim s1 As String = "œufs" + Dim s2 As String = "oeufs" + FindInString(s1, "oe", StringComparison.CurrentCulture) + FindInString(s1, "oe", StringComparison.Ordinal) + FindInString(s2, "œu", StringComparison.CurrentCulture) + FindInString(s2, "œu", StringComparison.Ordinal) + Console.WriteLine() + + Dim softHyphen As String = ChrW(&HAD) + Dim s3 As String = "co" + softHyphen + "operative" + FindInString(s3, softHyphen, StringComparison.CurrentCulture) + FindInString(s3, softHyphen, StringComparison.Ordinal) + End Sub + + Private Sub FindInString(s As String, substring As String, + options As StringComparison) + Dim result As Integer = s.IndexOf(substring, options) + If result <> -1 Then + Console.WriteLine("'{0}' found in {1} at position {2}", + substring, s, result) + Else + Console.WriteLine("'{0}' not found in {1}", + substring, s) + End If + End Sub +End Module +' The example displays the following output: +' 'oe' found in œufs at position 0 +' 'oe' not found in œufs +' 'œu' found in oeufs at position 0 +' 'œu' not found in oeufs +' +' '­' found in co­operative at position 0 +' '­' found in co­operative at position 2 +' diff --git a/snippets/visualbasic/System/String/Overview/compare4.vb b/snippets/visualbasic/System/String/Overview/compare4.vb new file mode 100644 index 00000000000..b7816e2d1a6 --- /dev/null +++ b/snippets/visualbasic/System/String/Overview/compare4.vb @@ -0,0 +1,53 @@ +' +Imports System.Globalization +Imports System.Threading + +Public Module Example6 + Public Sub Main() + Dim str1 As String = "Apple" + Dim str2 As String = "Æble" + Dim str3 As String = "AEble" + + ' Set the current culture to Danish in Denmark. + Thread.CurrentThread.CurrentCulture = New CultureInfo("da-DK") + Console.WriteLine("Current culture: {0}", + CultureInfo.CurrentCulture.Name) + Console.WriteLine("Comparison of {0} with {1}: {2}", + str1, str2, String.Compare(str1, str2)) + Console.WriteLine("Comparison of {0} with {1}: {2}", + str2, str3, String.Compare(str2, str3)) + Console.WriteLine() + + ' Set the current culture to English in the U.S. + Thread.CurrentThread.CurrentCulture = New CultureInfo("en-US") + Console.WriteLine("Current culture: {0}", + CultureInfo.CurrentCulture.Name) + Console.WriteLine("Comparison of {0} with {1}: {2}", + str1, str2, String.Compare(str1, str2)) + Console.WriteLine("Comparison of {0} with {1}: {2}", + str2, str3, String.Compare(str2, str3)) + Console.WriteLine() + + ' Perform an ordinal comparison. + Console.WriteLine("Ordinal comparison") + Console.WriteLine("Comparison of {0} with {1}: {2}", + str1, str2, + String.Compare(str1, str2, StringComparison.Ordinal)) + Console.WriteLine("Comparison of {0} with {1}: {2}", + str2, str3, + String.Compare(str2, str3, StringComparison.Ordinal)) + End Sub +End Module +' The example displays the following output: +' Current culture: da-DK +' Comparison of Apple with Æble: -1 +' Comparison of Æble with AEble: 1 +' +' Current culture: en-US +' Comparison of Apple with Æble: 1 +' Comparison of Æble with AEble: 0 +' +' Ordinal comparison +' Comparison of Apple with Æble: -133 +' Comparison of Æble with AEble: 133 +' diff --git a/snippets/visualbasic/System/String/Overview/equality1.vb b/snippets/visualbasic/System/String/Overview/equality1.vb new file mode 100644 index 00000000000..9f547d867cf --- /dev/null +++ b/snippets/visualbasic/System/String/Overview/equality1.vb @@ -0,0 +1,45 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Globalization +Imports System.Threading + +Module Example7 + Public Sub Main() + Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("tr-TR") + + Dim filePath As String = "file://c:/notes.txt" + + Console.WriteLine("Culture-sensitive test for equality:") + If Not TestForEquality(filePath, StringComparison.CurrentCultureIgnoreCase) Then + Console.WriteLine("Access to {0} is allowed.", filePath) + Else + Console.WriteLine("Access to {0} is not allowed.", filePath) + End If + Console.WriteLine() + + Console.WriteLine("Ordinal test for equality:") + If Not TestForEquality(filePath, StringComparison.OrdinalIgnoreCase) Then + Console.WriteLine("Access to {0} is allowed.", filePath) + Else + Console.WriteLine("Access to {0} is not allowed.", filePath) + End If + End Sub + + Private Function TestForEquality(str As String, cmp As StringComparison) As Boolean + Dim position As Integer = str.IndexOf("://") + If position < 0 Then Return False + + Dim substring As String = str.Substring(0, position) + Return substring.Equals("FILE", cmp) + End Function +End Module +' The example displays the following output: +' Culture-sensitive test for equality: +' Access to file://c:/notes.txt is allowed. +' +' Ordinal test for equality: +' Access to file://c:/notes.txt is not allowed. +' + diff --git a/snippets/visualbasic/System/String/Overview/format1.vb b/snippets/visualbasic/System/String/Overview/format1.vb new file mode 100644 index 00000000000..193ff794318 --- /dev/null +++ b/snippets/visualbasic/System/String/Overview/format1.vb @@ -0,0 +1,26 @@ +' Visual Basic .NET Document +Option Strict On +Option Infer On + +' +Imports System.Globalization + +Module Example8 + Public Sub Main() + Dim dat As Date = #3/1/2011# + Dim cultures() As CultureInfo = {CultureInfo.InvariantCulture, + New CultureInfo("en-US"), + New CultureInfo("fr-FR")} + + For Each culture In cultures + Console.WriteLine("{0,-12} {1}", If(String.IsNullOrEmpty(culture.Name), + "Invariant", culture.Name), + dat.ToString("d", culture)) + Next + End Sub +End Module +' The example displays the following output: +' Invariant 03/01/2011 +' en-US 3/1/2011 +' fr-FR 01/03/2011 +' diff --git a/snippets/visualbasic/System/String/Overview/grapheme1.vb b/snippets/visualbasic/System/String/Overview/grapheme1.vb new file mode 100644 index 00000000000..4bd322a3278 --- /dev/null +++ b/snippets/visualbasic/System/String/Overview/grapheme1.vb @@ -0,0 +1,36 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Globalization +Imports System.IO + +Module Example9 + Public Sub Main() + Dim sw As New StreamWriter(".\graphemes.txt") + Dim grapheme As String = ChrW(&H61) + ChrW(&H308) + sw.WriteLine(grapheme) + + Dim singleChar As String = ChrW(&HE4) + sw.WriteLine(singleChar) + + sw.WriteLine("{0} = {1} (Culture-sensitive): {2}", grapheme, singleChar, + String.Equals(grapheme, singleChar, + StringComparison.CurrentCulture)) + sw.WriteLine("{0} = {1} (Ordinal): {2}", grapheme, singleChar, + String.Equals(grapheme, singleChar, + StringComparison.Ordinal)) + sw.WriteLine("{0} = {1} (Normalized Ordinal): {2}", grapheme, singleChar, + String.Equals(grapheme.Normalize(), + singleChar.Normalize(), + StringComparison.Ordinal)) + sw.Close() + End Sub +End Module +' The example produces the following output: +' ä +' ä +' ä = ä (Culture-sensitive): True +' ä = ä (Ordinal): False +' ä = ä (Normalized Ordinal): True +' diff --git a/snippets/visualbasic/System/String/Overview/immutable.vb b/snippets/visualbasic/System/String/Overview/immutable.vb new file mode 100644 index 00000000000..279b9af029a --- /dev/null +++ b/snippets/visualbasic/System/String/Overview/immutable.vb @@ -0,0 +1,26 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.IO +Imports System.Text + +Module Example10 + Public Sub Main() + Dim rnd As New Random() + + Dim str As String = String.Empty + Dim sw As New StreamWriter(".\StringFile.txt", + False, Encoding.Unicode) + + For ctr As Integer = 0 To 1000 + str += ChrW(rnd.Next(1, &H530)) + If str.Length Mod 60 = 0 Then str += vbCrLf + Next + sw.Write(str) + sw.Close() + End Sub +End Module +' + + diff --git a/snippets/visualbasic/System/String/Overview/immutable1.vb b/snippets/visualbasic/System/String/Overview/immutable1.vb new file mode 100644 index 00000000000..bcd5f0abc19 --- /dev/null +++ b/snippets/visualbasic/System/String/Overview/immutable1.vb @@ -0,0 +1,24 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.IO +Imports System.Text + +Module Example11 + Public Sub Main() + Dim rnd As New Random() + Dim sb As New StringBuilder() + Dim sw As New StreamWriter(".\StringFile.txt", + False, Encoding.Unicode) + + For ctr As Integer = 0 To 1000 + sb.Append(ChrW(rnd.Next(1, &H530))) + If sb.Length Mod 60 = 0 Then sb.AppendLine() + Next + sw.Write(sb.ToString()) + sw.Close() + End Sub +End Module +' + diff --git a/snippets/visualbasic/System/String/Overview/index1.vb b/snippets/visualbasic/System/String/Overview/index1.vb new file mode 100644 index 00000000000..80b45c6a808 --- /dev/null +++ b/snippets/visualbasic/System/String/Overview/index1.vb @@ -0,0 +1,23 @@ +' Visual Basic .NET Document +Option Strict On +' +Module Example12 + Public Sub Main() + Dim s1 As String = "This string consists of a single short sentence." + Dim nWords As Integer = 0 + + s1 = s1.Trim() + For ctr As Integer = 0 To s1.Length - 1 + If Char.IsPunctuation(s1(ctr)) Or Char.IsWhiteSpace(s1(ctr)) Then + nWords += 1 + End If + Next + Console.WriteLine("The sentence{2} {0}{2}has {1} words.", + s1, nWords, vbCrLf) + End Sub +End Module +' The example displays the following output: +' The sentence +' This string consists of a single short sentence. +' has 8 words. +' diff --git a/snippets/visualbasic/System/String/Overview/index2.vb b/snippets/visualbasic/System/String/Overview/index2.vb new file mode 100644 index 00000000000..37efc190d9a --- /dev/null +++ b/snippets/visualbasic/System/String/Overview/index2.vb @@ -0,0 +1,23 @@ +' Visual Basic .NET Document +Option Strict On +' +Module Example13 + Public Sub Main() + Dim s1 As String = "This string consists of a single short sentence." + Dim nWords As Integer = 0 + + s1 = s1.Trim() + For Each ch In s1 + If Char.IsPunctuation(ch) Or Char.IsWhiteSpace(ch) Then + nWords += 1 + End If + Next + Console.WriteLine("The sentence{2} {0}{2}has {1} words.", + s1, nWords, vbCrLf) + End Sub +End Module +' The example displays the following output: +' The sentence +' This string consists of a single short sentence. +' has 8 words. +' diff --git a/snippets/visualbasic/System/String/Overview/index3.vb b/snippets/visualbasic/System/String/Overview/index3.vb new file mode 100644 index 00000000000..3a121ab0f1c --- /dev/null +++ b/snippets/visualbasic/System/String/Overview/index3.vb @@ -0,0 +1,76 @@ +' Visual Basic .NET Document +Option Strict On +Option Infer On + +' +Imports System.Collections.Generic +Imports System.Globalization + +Module Example14 + Public Sub Main() + ' First sentence of The Mystery of the Yellow Room, by Leroux. + Dim opening As String = "Ce n'est pas sans une certaine émotion que " + + "je commence à raconter ici les aventures " + + "extraordinaires de Joseph Rouletabille." + ' Character counters. + Dim nChars As Integer = 0 + ' Objects to store word count. + Dim chars As New List(Of Integer)() + Dim elements As New List(Of Integer)() + + For Each ch In opening + ' Skip the ' character. + If ch = ChrW(&H27) Then Continue For + + If Char.IsWhiteSpace(ch) Or Char.IsPunctuation(ch) Then + chars.Add(nChars) + nChars = 0 + Else + nChars += 1 + End If + Next + + Dim te As TextElementEnumerator = StringInfo.GetTextElementEnumerator(opening) + Do While te.MoveNext() + Dim s As String = te.GetTextElement() + ' Skip the ' character. + If s = ChrW(&H27) Then Continue Do + If String.IsNullOrEmpty(s.Trim()) Or (s.Length = 1 AndAlso Char.IsPunctuation(Convert.ToChar(s))) Then + elements.Add(nChars) + nChars = 0 + Else + nChars += 1 + End If + Loop + + ' Display character counts. + Console.WriteLine("{0,6} {1,20} {2,20}", + "Word #", "Char Objects", "Characters") + For ctr As Integer = 0 To chars.Count - 1 + Console.WriteLine("{0,6} {1,20} {2,20}", + ctr, chars(ctr), elements(ctr)) + Next + End Sub +End Module +' The example displays the following output: +' Word # Char Objects Characters +' 0 2 2 +' 1 4 4 +' 2 3 3 +' 3 4 4 +' 4 3 3 +' 5 8 8 +' 6 8 7 +' 7 3 3 +' 8 2 2 +' 9 8 8 +' 10 2 1 +' 11 8 8 +' 12 3 3 +' 13 3 3 +' 14 9 9 +' 15 15 15 +' 16 2 2 +' 17 6 6 +' 18 12 12 +' diff --git a/snippets/visualbasic/System/String/Overview/instantiate1.vb b/snippets/visualbasic/System/String/Overview/instantiate1.vb new file mode 100644 index 00000000000..7dab99bae97 --- /dev/null +++ b/snippets/visualbasic/System/String/Overview/instantiate1.vb @@ -0,0 +1,84 @@ +' Visual Basic .NET Document +Option Strict On + +Module Example15 + Public Sub Main() + InstantiateByAssignment() + Console.WriteLine("-----") + CallConstructors() + Console.WriteLine("-----") + Concatenate() + Console.WriteLine("-----") + ExtractString() + Console.WriteLine("-----") + Formatting() + End Sub + + Private Sub InstantiateByAssignment() + ' + Dim string1 As String = "This is a string created by assignment." + Console.WriteLine(string1) + Dim string2 As String = "The path is C:\PublicDocuments\Report1.doc" + Console.WriteLine(string2) + ' The example displays the following output: + ' This is a string created by assignment. + ' The path is C:\PublicDocuments\Report1.doc + ' + End Sub + + Private Sub CallConstructors() + ' + Dim chars() As Char = {"w"c, "o"c, "r"c, "d"c} + + ' Create a string from a character array. + Dim string1 As New String(chars) + Console.WriteLine(string1) + + ' Create a string that consists of a character repeated 20 times. + Dim string2 As New String("c"c, 20) + Console.WriteLine(string2) + ' The example displays the following output: + ' word + ' cccccccccccccccccccc + ' + End Sub + + Private Sub Concatenate() + ' + Dim string1 As String = "Today is " + Date.Now.ToString("D") + "." + Console.WriteLine(string1) + Dim string2 As String = "This is one sentence. " + "This is a second. " + string2 += "This is a third sentence." + Console.WriteLine(string2) + ' The example displays output like the following: + ' Today is Tuesday, July 06, 2011. + ' This is one sentence. This is a second. This is a third sentence. + ' + End Sub + + Private Sub ExtractString() + ' + Dim sentence As String = "This sentence has five words." + ' Extract the second word. + Dim startPosition As Integer = sentence.IndexOf(" ") + 1 + Dim word2 As String = sentence.Substring(startPosition, + sentence.IndexOf(" ", startPosition) - startPosition) + Console.WriteLine("Second word: " + word2) + ' The example displays the following output: + ' Second word: sentence + ' + End Sub + + Private Sub Formatting() + ' + Dim dateAndTime As DateTime = #07/06/2011 7:32:00AM# + Dim temperature As Double = 68.3 + Dim result As String = String.Format("At {0:t} on {0:D}, the temperature was {1:F1} degrees Fahrenheit.", + dateAndTime, temperature) + Console.WriteLine(result) + ' The example displays the following output: + ' At 7:32 AM on Wednesday, July 06, 2011, the temperature was 68.3 degrees Fahrenheit. + ' + End Sub +End Module + diff --git a/snippets/visualbasic/System/String/Overview/normalize1.vb b/snippets/visualbasic/System/String/Overview/normalize1.vb new file mode 100644 index 00000000000..5aab63cf363 --- /dev/null +++ b/snippets/visualbasic/System/String/Overview/normalize1.vb @@ -0,0 +1,96 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Globalization +Imports System.IO +Imports System.Text + +Module Example16 + Private sw As StreamWriter + + Public Sub Main() + sw = New StreamWriter(".\TestNorm1.txt") + + ' Define three versions of the same word. + Dim s1 As String = "sống" ' create word with U+1ED1 + Dim s2 As String = "s" + ChrW(&HF4) + ChrW(&H301) + "ng" + Dim s3 As String = "so" + ChrW(&H302) + ChrW(&H301) + "ng" + + TestForEquality(s1, s2, s3) + sw.WriteLine() + + ' Normalize and compare strings using each normalization form. + For Each formName In [Enum].GetNames(GetType(NormalizationForm)) + sw.WriteLine("Normalization {0}:", formName) + Dim nf As NormalizationForm = CType([Enum].Parse(GetType(NormalizationForm), formName), + NormalizationForm) + Dim sn() As String = NormalizeStrings(nf, s1, s2, s3) + TestForEquality(sn) + sw.WriteLine(vbCrLf) + Next + + sw.Close() + End Sub + + Private Sub TestForEquality(ParamArray words As String()) + For ctr As Integer = 0 To words.Length - 2 + For ctr2 As Integer = ctr + 1 To words.Length - 1 + sw.WriteLine("{0} ({1}) = {2} ({3}): {4}", + words(ctr), ShowBytes(words(ctr)), + words(ctr2), ShowBytes(words(ctr2)), + words(ctr).Equals(words(ctr2), StringComparison.Ordinal)) + Next + Next + End Sub + + Private Function ShowBytes(str As String) As String + Dim result As String = Nothing + For Each ch In str + result += String.Format("{0} ", Convert.ToUInt16(ch).ToString("X4")) + Next + Return result.Trim() + End Function + + Private Function NormalizeStrings(nf As NormalizationForm, ParamArray words() As String) As String() + For ctr As Integer = 0 To words.Length - 1 + If Not words(ctr).IsNormalized(nf) Then + words(ctr) = words(ctr).Normalize(nf) + End If + Next + Return words + End Function +End Module +' The example displays the following output: +' sống (0073 1ED1 006E 0067) = sống (0073 00F4 0301 006E 0067): False +' sống (0073 1ED1 006E 0067) = sống (0073 006F 0302 0301 006E 0067): False +' sống (0073 00F4 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): False +' +' Normalization FormC: +' +' sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True +' sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True +' sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True +' +' +' Normalization FormD: +' +' sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True +' sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True +' sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True +' +' +' Normalization FormKC: +' +' sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True +' sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True +' sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True +' +' +' Normalization FormKD: +' +' sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True +' sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True +' sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True +' + diff --git a/snippets/visualbasic/System/String/Overview/nullorempty1.vb b/snippets/visualbasic/System/String/Overview/nullorempty1.vb new file mode 100644 index 00000000000..00973e644ed --- /dev/null +++ b/snippets/visualbasic/System/String/Overview/nullorempty1.vb @@ -0,0 +1,74 @@ +' Visual Basic .NET Document +Option Strict On + +Imports System.Globalization + +Module Example17 + Public Sub Main() + TestForIsNullOrEmpty() + Console.WriteLine("-----") + TestForIsNullOrEmptyOrWhitespaceOnly() + End Sub + + Private Sub TestForIsNullOrEmpty() + Dim str As String = Nothing + ' + If str Is Nothing OrElse str.Equals(String.Empty) Then + ' + + Else + + End If + End Sub + + Private Sub TestForIsNullOrEmptyOrWhitespaceOnly() + Dim str As String = " " + ' + If str Is Nothing OrElse str.Equals(String.Empty) OrElse str.Trim().Equals(String.Empty) Then + ' + Console.WriteLine("Bad!") + Else + Console.WriteLine("Good!") + End If + End Sub +End Module + +Public Class Temperature : Implements IFormattable + Dim temp As Double + + Public Sub New(temp As Double) + Me.temp = temp + End Sub + + Public Overrides Function ToString() As String + Return Me.ToString("G", CultureInfo.CurrentCulture) + End Function + + Public Overloads Function ToString(fmt As String) As String + Return Me.ToString(fmt, CultureInfo.CurrentCulture) + End Function + + ' + Public Overloads Function ToString(fmt As String, provider As IFormatProvider) As String _ + Implements IFormattable.ToString + If String.IsNullOrEmpty(fmt) Then fmt = "G" + If provider Is Nothing Then provider = CultureInfo.CurrentCulture + + Select Case fmt.ToUpperInvariant() + ' Return degrees in Celsius. + Case "G", "C" + Return temp.ToString("F2", provider) + "°C" + ' Return degrees in Fahrenheit. + Case "F" + Return (temp * 9 / 5 + 32).ToString("F2", provider) + "°F" + ' Return degrees in Kelvin. + Case "K" + Return (temp + 273.15).ToString() + Case Else + Throw New FormatException( + String.Format("The {0} format string is not supported.", + fmt)) + End Select + End Function + ' +End Class diff --git a/snippets/visualbasic/System/String/Overview/parse1.vb b/snippets/visualbasic/System/String/Overview/parse1.vb new file mode 100644 index 00000000000..939154de358 --- /dev/null +++ b/snippets/visualbasic/System/String/Overview/parse1.vb @@ -0,0 +1,33 @@ +' Visual Basic .NET Document +Option Strict On +Option Infer On + +' +Imports System.Globalization + +Module Example18 + Public Sub Main() + Dim dateString As String = "07/10/2011" + Dim cultures() As CultureInfo = {CultureInfo.InvariantCulture, + CultureInfo.CreateSpecificCulture("en-GB"), + CultureInfo.CreateSpecificCulture("en-US")} + Console.WriteLine("{0,-12} {1,10} {2,8} {3,8}", "Date String", "Culture", + "Month", "Day") + Console.WriteLine() + For Each culture In cultures + Dim dat As Date = DateTime.Parse(dateString, culture) + Console.WriteLine("{0,-12} {1,10} {2,8} {3,8}", dateString, + If(String.IsNullOrEmpty(culture.Name), + "Invariant", culture.Name), + dat.Month, dat.Day) + Next + End Sub +End Module +' The example displays the following output: +' Date String Culture Month Day +' +' 07/10/2011 Invariant 7 10 +' 07/10/2011 en-GB 10 7 +' 07/10/2011 en-US 7 10 +' + diff --git a/snippets/visualbasic/System/String/Overview/search1.vb b/snippets/visualbasic/System/String/Overview/search1.vb new file mode 100644 index 00000000000..7b6b60f1623 --- /dev/null +++ b/snippets/visualbasic/System/String/Overview/search1.vb @@ -0,0 +1,30 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Globalization + +Module Example19 + Public Sub Main() + Dim cultureNames() As String = {"da-DK", "en-US"} + Dim ci As CompareInfo + Dim str As String = "aerial" + Dim ch As Char = "æ"c ' U+00E6 + + Console.Write("Ordinal comparison -- ") + Console.WriteLine("Position of '{0}' in {1}: {2}", ch, str, + str.IndexOf(ch)) + + For Each cultureName In cultureNames + ci = CultureInfo.CreateSpecificCulture(cultureName).CompareInfo + Console.Write("{0} cultural comparison -- ", cultureName) + Console.WriteLine("Position of '{0}' in {1}: {2}", ch, str, + ci.IndexOf(str, ch)) + Next + End Sub +End Module +' The example displays the following output: +' Ordinal comparison -- Position of 'æ' in aerial: -1 +' da-DK cultural comparison -- Position of 'æ' in aerial: -1 +' en-US cultural comparison -- Position of 'æ' in aerial: 0 +' diff --git a/snippets/visualbasic/System/String/Overview/sort1.vb b/snippets/visualbasic/System/String/Overview/sort1.vb new file mode 100644 index 00000000000..3dd6966da04 --- /dev/null +++ b/snippets/visualbasic/System/String/Overview/sort1.vb @@ -0,0 +1,57 @@ +' +Imports System.Globalization +Imports System.IO +Imports System.Threading + +Public Class TextToFile + Public Shared Sub Main() + ' Creates and initializes a new array to store + ' these date/time objects. + Dim stringArray() As String = { "Apple", "Æble", "Zebra"} + + ' Displays the values of the array. + Console.WriteLine("The original string array:") + PrintIndexAndValues(stringArray) + + ' Set the CurrentCulture to "en-US". + Thread.CurrentThread.CurrentCulture = New CultureInfo("en-US") + ' Sort the values of the Array. + Array.Sort(stringArray) + + ' Display the values of the array. + Console.WriteLine("After sorting for the ""en-US"" culture:") + PrintIndexAndValues(stringArray) + + ' Set the CurrentCulture to "da-DK". + Thread.CurrentThread.CurrentCulture = New CultureInfo("da-DK") + ' Sort the values of the Array. + Array.Sort(stringArray) + + ' Displays the values of the Array. + Console.WriteLine("After sorting for the culture ""da-DK"":") + PrintIndexAndValues(stringArray) + End Sub + + Public Shared Sub PrintIndexAndValues(myArray() As String) + For i As Integer = myArray.GetLowerBound(0) To myArray.GetUpperBound(0) + Console.WriteLine("[{0}]: {1}", i, myArray(i)) + Next + Console.WriteLine() + End Sub +End Class +' The example displays the following output: +' The original string array: +' [0]: Apple +' [1]: Æble +' [2]: Zebra +' +' After sorting for the "en-US" culture: +' [0]: Æble +' [1]: Apple +' [2]: Zebra +' +' After sorting for the culture "da-DK": +' [0]: Apple +' [1]: Zebra +' [2]: Æble +' \ No newline at end of file diff --git a/snippets/visualbasic/System/String/Overview/surrogate1.vb b/snippets/visualbasic/System/String/Overview/surrogate1.vb new file mode 100644 index 00000000000..9c09c965190 --- /dev/null +++ b/snippets/visualbasic/System/String/Overview/surrogate1.vb @@ -0,0 +1,20 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example20 + Public Sub Main() + Dim surrogate As String = ChrW(&HD800) + ChrW(&HDC03) + For ctr As Integer = 0 To surrogate.Length - 1 + Console.Write("U+{0:X2} ", Convert.ToUInt16(surrogate(ctr))) + Next + Console.WriteLine() + Console.WriteLine(" Is Surrogate Pair: {0}", + Char.IsSurrogatePair(surrogate(0), surrogate(1))) + End Sub +End Module + +' The example displays the following output: +' U+D800 U+DC03 +' Is Surrogate Pair: True +' diff --git a/snippets/visualbasic/System/TimeSpan/Overview/Project.vbproj b/snippets/visualbasic/System/TimeSpan/Overview/Project.vbproj new file mode 100644 index 00000000000..531d891cd55 --- /dev/null +++ b/snippets/visualbasic/System/TimeSpan/Overview/Project.vbproj @@ -0,0 +1,8 @@ + + + + Library + net48 + + + diff --git a/snippets/visualbasic/System/TimeSpan/Overview/instantiate1.vb b/snippets/visualbasic/System/TimeSpan/Overview/instantiate1.vb new file mode 100644 index 00000000000..ba36f342218 --- /dev/null +++ b/snippets/visualbasic/System/TimeSpan/Overview/instantiate1.vb @@ -0,0 +1,66 @@ +' Visual Basic .NET Document +Option Strict On + +Module Example1 + Public Sub Main() + Implicit() + Console.WriteLine() + Explicit() + Console.WriteLine() + TimeSpanOperation() + Console.WriteLine() + Parse() + Console.WriteLine() + End Sub + + Private Sub Implicit() + ' + Dim interval As New TimeSpan() + Console.WriteLine(interval.Equals(TimeSpan.Zero)) ' Displays "True". + ' + End Sub + + Private Sub Explicit() + ' + Dim interval As New TimeSpan(2, 14, 18) + Console.WriteLine(interval.ToString()) ' Displays "02:14:18". + ' + End Sub + + Private Sub TimeSpanOperation() + ' + Dim departure As DateTime = #06/12/2010 6:32PM# + Dim arrival As DateTime = #06/13/2010 10:47PM# + Dim travelTime As TimeSpan = arrival - departure + Console.WriteLine("{0} - {1} = {2}", arrival, departure, travelTime) + ' The example displays the following output: + ' 6/13/2010 10:47:00 PM - 6/12/2010 6:32:00 PM = 1.04:15:00 + ' + End Sub + + Private Sub Parse() + ' + Dim values() As String = {"12", "31.", "5.8:32:16", "12:12:15.95", ".12"} + For Each value As String In values + Try + Dim ts As TimeSpan = TimeSpan.Parse(value) + Console.WriteLine("'{0}' --> {1}", value, ts) + Catch e As FormatException + Console.WriteLine("Unable to parse '{0}'", value) + Catch e As OverflowException + Console.WriteLine("'{0}' is outside the range of a TimeSpan.", value) + End Try + Next + ' The example displays the following output: + ' '12' --> 12.00:00:00 + ' Unable to parse '31.' + ' '5.8:32:16' --> 5.08:32:16 + ' '12:12:15.95' --> 12:12:15.9500000 + ' Unable to parse '.12' + ' + End Sub +End Module + +' 02:10:21 +' +' 22:26:43 diff --git a/snippets/visualbasic/System/TimeSpan/Overview/zero1.vb b/snippets/visualbasic/System/TimeSpan/Overview/zero1.vb new file mode 100644 index 00000000000..fd9dda98826 --- /dev/null +++ b/snippets/visualbasic/System/TimeSpan/Overview/zero1.vb @@ -0,0 +1,27 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module MExample + Dim rnd As New Random() + + Public Sub Main() + Dim timeSpent As TimeSpan = TimeSpan.Zero + + timeSpent += GetTimeBeforeLunch() + timeSpent += GetTimeAfterLunch() + + Console.WriteLine("Total time: {0}", timeSpent) + End Sub + + Private Function GetTimeBeforeLunch() As TimeSpan + Return New TimeSpan(rnd.Next(3, 6), 0, 0) + End Function + + Private Function GetTimeAfterLunch() As TimeSpan + Return New TimeSpan(rnd.Next(3, 6), 0, 0) + End Function +End Module +' The example displays output like the following: +' Total time: 08:00:00 +' diff --git a/snippets/visualbasic/System/TimeSpan/Parse/parse1.vb b/snippets/visualbasic/System/TimeSpan/Parse/parse1.vb index 40e063e41cd..3bdf3be5a1e 100644 --- a/snippets/visualbasic/System/TimeSpan/Parse/parse1.vb +++ b/snippets/visualbasic/System/TimeSpan/Parse/parse1.vb @@ -5,7 +5,7 @@ Imports System.Globalization Imports System.Threading Module Example1 - Public Sub Main() + Public Sub Main1() ' Dim values() As String = {"6", "6:12", "6:12:14", "6:12:14:45", "6.12:14:45", "6:12:14:45.3448", @@ -40,7 +40,7 @@ Module Example1 ' 6:12:14:45.3448: Bad Format ' 6:12:14:45,3448 --> 6.12:14:45.3448000 ' 6:34:14:45: Overflow - ' + ' ' Current Culture: en-US ' 6 --> 6.00:00:00 ' 6:12 --> 06:12:00 diff --git a/snippets/visualbasic/System/TimeSpan/Parse/parsefailure1.vb b/snippets/visualbasic/System/TimeSpan/Parse/parsefailure1.vb new file mode 100644 index 00000000000..9aeb188c916 --- /dev/null +++ b/snippets/visualbasic/System/TimeSpan/Parse/parsefailure1.vb @@ -0,0 +1,27 @@ +' Visual Basic .NET Document +Option Strict On + +Module Example + Public Sub Main() + ' + Dim values() As String = { "000000006", "12.12:12:12.12345678" } + For Each value As String In values + Try + Dim interval As TimeSpan = TimeSpan.Parse(value) + Console.WriteLine("{0} --> {1}", value, interval) + Catch e As FormatException + Console.WriteLine("{0}: Bad Format", value) + Catch e As OverflowException + Console.WriteLine("{0}: Overflow", value) + End Try + Next + ' Output from .NET Framework 3.5 and earlier versions: + ' 000000006 --> 6.00:00:00 + ' 12.12:12:12.12345678: Bad Format + ' Output from .NET Framework 4: + ' 000000006: Overflow + ' 12.12:12:12.12345678: Overflow + ' + End Sub +End Module + diff --git a/snippets/visualbasic/System/Type/MakeGenericType/Project.vbproj b/snippets/visualbasic/System/Type/MakeGenericType/Project.vbproj index 92e46ddaccf..a15a29bf12c 100644 --- a/snippets/visualbasic/System/Type/MakeGenericType/Project.vbproj +++ b/snippets/visualbasic/System/Type/MakeGenericType/Project.vbproj @@ -2,7 +2,7 @@ Exe - net9.0 + net10.0 diff --git a/snippets/visualbasic/System/Type/MakeGenericType/remarks.vb b/snippets/visualbasic/System/Type/MakeGenericType/remarks.vb new file mode 100644 index 00000000000..718a6eba3d1 --- /dev/null +++ b/snippets/visualbasic/System/Type/MakeGenericType/remarks.vb @@ -0,0 +1,23 @@ +' +Public Class Base(Of T, U) +End Class +Public Class Derived(Of V) + Inherits Base(Of Integer, V) +End Class +' + +' +Public Class Outermost(Of T) + Public Class Inner(Of U) + Public Class Innermost1(Of V) + End Class + Public Class Innermost2 + End Class + End Class +End Class +' + +Public Class ProgStubClass + Shared Sub Main() + End Sub +End Class \ No newline at end of file diff --git a/snippets/visualbasic/System/Type/MakeGenericType/source.vb b/snippets/visualbasic/System/Type/MakeGenericType/source.vb index 337b298d25f..adc2032fa06 100644 --- a/snippets/visualbasic/System/Type/MakeGenericType/source.vb +++ b/snippets/visualbasic/System/Type/MakeGenericType/source.vb @@ -1,9 +1,7 @@ ' -Imports System.Reflection -Imports System.Collections.Generic Public Class Test - Public Shared Sub Main() + Public Shared Sub Main2() Console.WriteLine(vbCrLf & "--- Create a constructed type from the generic Dictionary type.") ' Create a type object representing the generic Dictionary @@ -16,7 +14,7 @@ Public Class Test ' Create an array of types to substitute for the type ' parameters of Dictionary. The key is of type string, and ' the type to be contained in the Dictionary is Test. - Dim typeArgs() As Type = { GetType(String), GetType(Test) } + Dim typeArgs() As Type = {GetType(String), GetType(Test)} ' Create a Type object representing the constructed generic ' type. @@ -30,7 +28,7 @@ Public Class Test Dim t As Type = GetType(Dictionary(Of String, Test)) Console.WriteLine(vbTab & "Are the constructed types equal? " _ & (t Is constructed)) - Console.WriteLine(vbTab & "Are the generic types equal? " _ + Console.WriteLine(vbTab & "Are the generic types equal? " _ & (t.GetGenericTypeDefinition() Is generic)) End Sub diff --git a/snippets/visualbasic/System/Type/Overview/Equals1.vb b/snippets/visualbasic/System/Type/Overview/Equals1.vb new file mode 100644 index 00000000000..b8cd09a6f44 --- /dev/null +++ b/snippets/visualbasic/System/Type/Overview/Equals1.vb @@ -0,0 +1,28 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module MExample1 + Public Sub Main() + Dim number1 As Long = 1635429 + Dim number2 As Integer = 16203 + Dim number3 As Double = 1639.41 + Dim number4 As Long = 193685412 + + ' Get the type of number1. + Dim t As Type = number1.GetType() + + ' Compare types of all objects with number1. + Console.WriteLine("Type of number1 and number2 are equal: {0}", + Object.ReferenceEquals(t, number2.GetType())) + Console.WriteLine("Type of number1 and number3 are equal: {0}", + Object.ReferenceEquals(t, number3.GetType())) + Console.WriteLine("Type of number1 and number4 are equal: {0}", + Object.ReferenceEquals(t, number4.GetType())) + End Sub +End Module +' The example displays the following output: +' Type of number1 and number2 are equal: False +' Type of number1 and number3 are equal: False +' Type of number1 and number4 are equal: True +' diff --git a/snippets/visualbasic/System/Type/Overview/GetType1.vb b/snippets/visualbasic/System/Type/Overview/GetType1.vb new file mode 100644 index 00000000000..3b2e05951be --- /dev/null +++ b/snippets/visualbasic/System/Type/Overview/GetType1.vb @@ -0,0 +1,20 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example1 + Public Sub Main() + Dim values() As Object = { "word", True, 120, 136.34, "a"c } + For Each value In values + Console.WriteLine("{0} - type {1}", value, + value.GetType().Name) + Next + End Sub +End Module +' The example displays the following output: +' word - type String +' True - type Boolean +' 120 - type Int32 +' 136.34 - type Double +' a - type Char +' diff --git a/snippets/visualbasic/System/Type/Overview/Project.vbproj b/snippets/visualbasic/System/Type/Overview/Project.vbproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/visualbasic/System/Type/Overview/Project.vbproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/visualbasic/System/TypeInitializationException/Overview/CtorException1.vb b/snippets/visualbasic/System/TypeInitializationException/Overview/CtorException1.vb new file mode 100644 index 00000000000..bd383e0ace6 --- /dev/null +++ b/snippets/visualbasic/System/TypeInitializationException/Overview/CtorException1.vb @@ -0,0 +1,34 @@ +' Visual Basic .NET Document +Option Strict On + +' +Public Class Example1 + Shared test As New TestClass(3) + + Public Shared Sub Main() + Dim ex As New Example1() + Console.WriteLine(test.Value) + End Sub +End Class + +Public Class TestClass + Public ReadOnly Value As Integer + + Public Sub New(value As Integer) + If value < 0 Or value > 1 Then + Throw New ArgumentOutOfRangeException(NameOf(value)) + End If + Value = value + End Sub +End Class + +' The example displays the following output: +' Unhandled Exception: System.TypeInitializationException: +' The type initializer for 'Example' threw an exception. ---> +' System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values. +' at TestClass..ctor(Int32 value) +' at Example..cctor() +' --- End of inner exception stack trace --- +' at Example.Main() +' + diff --git a/snippets/visualbasic/System/TypeInitializationException/Overview/Missing1.vb b/snippets/visualbasic/System/TypeInitializationException/Overview/Missing1.vb new file mode 100644 index 00000000000..8568b653323 --- /dev/null +++ b/snippets/visualbasic/System/TypeInitializationException/Overview/Missing1.vb @@ -0,0 +1,43 @@ +' Visual Basic .NET Document +Option Strict On + +' +Module Example3 + Public Sub Main() + Dim p As New Person("John", "Doe") + Console.WriteLine(p) + End Sub +End Module + +Public Class Person + Shared infoModule As InfoModule + + Dim fName As String + Dim mName As String + Dim lName As String + + Shared Sub New() + infoModule = New InfoModule(DateTime.UtcNow) + End Sub + + Public Sub New(fName As String, lName As String) + Me.fName = fName + Me.lName = lName + infoModule.Increment() + End Sub + + Public Overrides Function ToString() As String + Return String.Format("{0} {1}", fName, lName) + End Function +End Class +' The example displays the following output if missing1a.dll is renamed or removed: +' Unhandled Exception: System.TypeInitializationException: +' The type initializer for 'Person' threw an exception. ---> +' System.IO.FileNotFoundException: Could not load file or assembly +' 'Missing1a, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' +' or one of its dependencies. The system cannot find the file specified. +' at Person..cctor() +' --- End of inner exception stack trace --- +' at Person..ctor(String fName, String lName) +' at Example.Main() +' diff --git a/snippets/visualbasic/System/TypeInitializationException/Overview/Missing1a.vb b/snippets/visualbasic/System/TypeInitializationException/Overview/Missing1a.vb new file mode 100644 index 00000000000..1ee7064e804 --- /dev/null +++ b/snippets/visualbasic/System/TypeInitializationException/Overview/Missing1a.vb @@ -0,0 +1,23 @@ +' Visual Basic .NET Document +Option Strict On + +' +Public Class InfoModule + Private firstUse As DateTime + Private ctr As Integer = 0 + + Public Sub New(dat As DateTime) + firstUse = dat + End Sub + + Public Function Increment() As Integer + ctr += 1 + Return ctr + End Function + + Public Function GetInitializationTime() As DateTime + Return firstUse + End Function +End Class +' + diff --git a/snippets/visualbasic/System/TypeInitializationException/Overview/Project.vbproj b/snippets/visualbasic/System/TypeInitializationException/Overview/Project.vbproj new file mode 100644 index 00000000000..874c98f3477 --- /dev/null +++ b/snippets/visualbasic/System/TypeInitializationException/Overview/Project.vbproj @@ -0,0 +1,8 @@ + + + + Library + net10.0 + + + diff --git a/snippets/visualbasic/System/TypeInitializationException/Overview/Regex1.vb b/snippets/visualbasic/System/TypeInitializationException/Overview/Regex1.vb new file mode 100644 index 00000000000..2799d477a72 --- /dev/null +++ b/snippets/visualbasic/System/TypeInitializationException/Overview/Regex1.vb @@ -0,0 +1,30 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Text.RegularExpressions + +Module Example4 + Public Sub Main() + Dim domain As AppDomain = AppDomain.CurrentDomain + ' Set a timeout interval of -2 seconds. + domain.SetData("REGEX_DEFAULT_MATCH_TIMEOUT", TimeSpan.FromSeconds(-2)) + + Dim rgx As New Regex("[aeiouy]") + Console.WriteLine("Regular expression pattern: {0}", rgx.ToString()) + Console.WriteLine("Timeout interval for this regex: {0} seconds", + rgx.MatchTimeout.TotalSeconds) + End Sub +End Module +' The example displays the following output: +' Unhandled Exception: System.TypeInitializationException: +' The type initializer for 'System.Text.RegularExpressions.Regex' threw an exception. ---> +' System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values. +' Parameter name: AppDomain data 'REGEX_DEFAULT_MATCH_TIMEOUT' contains an invalid value or +' object for specifying a default matching timeout for System.Text.RegularExpressions.Regex. +' at System.Text.RegularExpressions.Regex.InitDefaultMatchTimeout() +' at System.Text.RegularExpressions.Regex..cctor() +' --- End of inner exception stack trace --- +' at System.Text.RegularExpressions.Regex..ctor(String pattern) +' at Example.Main() +' diff --git a/snippets/visualbasic/System/Version/Overview/GettingVersions1.vb b/snippets/visualbasic/System/Version/Overview/GettingVersions1.vb new file mode 100644 index 00000000000..52f3c0ae15d --- /dev/null +++ b/snippets/visualbasic/System/Version/Overview/GettingVersions1.vb @@ -0,0 +1,42 @@ +' Visual Basic .NET Document +Option Strict On + +Imports System.Reflection + + +Module modMain + + Public Sub Main() + GetOsVersion() + Console.WriteLine() + GetClrVersion() + Console.WriteLine() + End Sub + + Private Sub GetOsVersion() + ' + ' Get the operating system version. + Dim os As OperatingSystem = Environment.OSVersion + Dim ver As Version = os.Version + Console.WriteLine("Operating System: {0} ({1})", os.VersionString, ver.ToString()) + ' + End Sub + + Private Sub GetClrVersion() + ' + ' Get the common language runtime version. + Dim ver As Version = Environment.Version + Console.WriteLine("CLR Version {0}", ver.ToString()) + ' + End Sub +End Module + +Public Module Example4 + Public Sub GetExecutingAssemblyVersion() + ' Get the version of the current assembly. + Dim assem As Assembly = Assembly.GetExecutingAssembly() + Dim assemName As AssemblyName = assem.GetName() + Dim ver As Version = assemName.Version + Console.WriteLine("{0}, Version {1}", assemName.Name, ver.ToString()) + End Sub +End Module diff --git a/snippets/visualbasic/System/Version/Overview/Project.vbproj b/snippets/visualbasic/System/Version/Overview/Project.vbproj new file mode 100644 index 00000000000..96f746920dd --- /dev/null +++ b/snippets/visualbasic/System/Version/Overview/Project.vbproj @@ -0,0 +1,9 @@ + + + + Library + net10.0 + false + + + diff --git a/snippets/visualbasic/System/Version/Overview/comparisons1.vb b/snippets/visualbasic/System/Version/Overview/comparisons1.vb new file mode 100644 index 00000000000..f955dc5688b --- /dev/null +++ b/snippets/visualbasic/System/Version/Overview/comparisons1.vb @@ -0,0 +1,28 @@ +' Visual Basic .NET Document +Option Strict On + +Module Example + Public Sub Main() + CompareSimple() + End Sub + + Private Sub CompareSimple() + ' + Dim v1 As New Version(2,0) + Dim v2 As New Version("2.1") + Console.Write("Version {0} is ", v1) + Select Case v1.CompareTo(v2) + Case 0 + Console.Write("the same as") + Case 1 + Console.Write("later than") + Case -1 + Console.Write("earlier than") + End Select + Console.WriteLine(" Version {0}.", v2) + ' The example displays the following output: + ' Version 2.0 is earlier than Version 2.1. + ' + End Sub +End Module + diff --git a/snippets/visualbasic/System/Version/Overview/comparisons2.vb b/snippets/visualbasic/System/Version/Overview/comparisons2.vb new file mode 100644 index 00000000000..5d3923dff89 --- /dev/null +++ b/snippets/visualbasic/System/Version/Overview/comparisons2.vb @@ -0,0 +1,29 @@ +' Visual Basic .NET Document +Option Strict On + +' +Public Enum VersionTime + Earlier = -1 + Same = 0 + Later = 1 +End Enum + +Module Example2 + Public Sub Main() + Dim v1 As New Version(1, 1) + Dim v1a As New Version("1.1.0") + ShowRelationship(v1, v1a) + + Dim v1b As New Version(1, 1, 0, 0) + ShowRelationship(v1b, v1a) + End Sub + + Private Sub ShowRelationship(v1 As Version, v2 As Version) + Console.WriteLine("Relationship of {0} to {1}: {2}", + v1, v2, CType(v1.CompareTo(v2), VersionTime)) + End Sub +End Module +' The example displays the following output: +' Relationship of 1.1 to 1.1.0: Earlier +' Relationship of 1.1.0.0 to 1.1.0: Later +' diff --git a/snippets/visualbasic/System/Version/Overview/currentapp.vb b/snippets/visualbasic/System/Version/Overview/currentapp.vb new file mode 100644 index 00000000000..d4786b97b6b --- /dev/null +++ b/snippets/visualbasic/System/Version/Overview/currentapp.vb @@ -0,0 +1,17 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Reflection + +Module Example3 + Public Sub Main() + ' Get the version of the executing assembly (that is, this assembly). + Dim assem As Assembly = Assembly.GetEntryAssembly() + Dim assemName As AssemblyName = assem.GetName() + Dim ver As Version = assemName.Version + Console.WriteLine("Application {0}, Version {1}", assemName.Name, ver.ToString()) + End Sub +End Module +' + diff --git a/snippets/visualbasic/System/Version/Overview/currentassem.vb b/snippets/visualbasic/System/Version/Overview/currentassem.vb new file mode 100644 index 00000000000..874730bd3a9 --- /dev/null +++ b/snippets/visualbasic/System/Version/Overview/currentassem.vb @@ -0,0 +1,17 @@ +' Visual Basic .NET Document +Option Strict On + +' +Imports System.Reflection + +Module Example1 + Public Sub Main() + ' Get the version of the current assembly. + Dim assem As Assembly = Assembly.GetExecutingAssembly() + Dim assemName As AssemblyName = assem.GetName() + Dim ver As Version = assemName.Version + Console.WriteLine("{0}, Version {1}", assemName.Name, ver.ToString()) + End Sub +End Module +' + diff --git a/snippets/visualbasic/System/Version/Overview/example1.vb b/snippets/visualbasic/System/Version/Overview/example1.vb index 4bc4b4983ad..bf25a1d6901 100644 --- a/snippets/visualbasic/System/Version/Overview/example1.vb +++ b/snippets/visualbasic/System/Version/Overview/example1.vb @@ -5,16 +5,17 @@ Option Strict On Imports System.Reflection -Module Example1 - Public Sub Main() - Dim thisAssem As Assembly = GetType(Example1).Assembly - Dim thisAssemName As AssemblyName = thisAssem.GetName() - - Dim ver As Version = thisAssemName.Version - - Console.WriteLine("This is version {0} of {1}.", ver, thisAssemName.Name) - End Sub +Module MExample1 + Public Sub Main() + Dim thisAssem As Assembly = Assembly.GetExecutingAssembly() + Dim thisAssemName As AssemblyName = thisAssem.GetName() + + Dim ver As Version = thisAssemName.Version + + Console.WriteLine("This is version {0} of {1}.", ver, thisAssemName.Name) + End Sub End Module + ' The example displays the following output: ' This is version 2.0.1.0 of Example1. ' diff --git a/xml/System/Random.xml b/xml/System/Random.xml index 77b637a8d19..8e8172d1d9e 100644 --- a/xml/System/Random.xml +++ b/xml/System/Random.xml @@ -69,8 +69,218 @@ > [!NOTE] > To generate a cryptographically secure random number, such as one that's suitable for creating a random password, use one of the static methods in the class. -For more information about this API, see [Supplemental API remarks for Random](/dotnet/fundamentals/runtime-libraries/system-random). - ]]> +The class represents a pseudo-random number generator, which is an algorithm that produces a sequence of numbers that meet certain statistical requirements for randomness. + +Pseudo-random numbers are chosen with equal probability from a finite set of numbers. The chosen numbers are not completely random because a mathematical algorithm is used to select them, but they are sufficiently random for practical purposes. The implementation of the class is based on a modified version of Donald E. Knuth's subtractive random number generator algorithm. For more information, see D. E. Knuth. *The Art of Computer Programming, Volume 2: Seminumerical Algorithms*. Addison-Wesley, Reading, MA, third edition, 1997. + +To generate a cryptographically secure random number, such as one that's suitable for creating a random password, use one of the static methods in the class. + +## Instantiate the random number generator + +You instantiate the random number generator by providing a seed value (a starting value for the pseudo-random number generation algorithm) to a class constructor. You can supply the seed value either explicitly or implicitly: + +- The constructor uses an explicit seed value that you supply. +- The constructor uses the default seed value. This is the most common way of instantiating the random number generator. + +The default seed value is produced by the thread-static, pseudo-random number generator. + +If the same seed is used for separate objects, they will generate the same series of random numbers. This can be useful for creating a test suite that processes random values, or for replaying games that derive their data from random numbers. + +To produce different sequences of random numbers, you can make the seed value time-dependent, thereby producing a different series with each new instance of . The parameterized constructor can take an value based on the number of ticks in the current time, whereas the parameterless constructor uses the system clock to generate its seed value. + +## Thread safety + +Instead of instantiating individual objects, we recommend that you create a single instance to generate all the random numbers needed by your app. However, objects are not thread safe. If your app calls methods from multiple threads, you must use a synchronization object to ensure that only one thread can access the random number generator at a time. If you don't ensure that the object is accessed in a thread-safe way, calls to methods that return random numbers return 0. + +The following example uses the C# [lock Statement](/dotnet/csharp/language-reference/keywords/lock-statement), the F# [lock function](https://fsharp.github.io/fsharp-core-docs/reference/fsharp-core-operators.html#lock) and the Visual Basic [SyncLock statement](/dotnet/visual-basic/language-reference/statements/synclock-statement) to ensure that a single random number generator is accessed by 11 threads in a thread-safe manner. Each thread generates 2 million random numbers, counts the number of random numbers generated and calculates their sum, and then updates the totals for all threads when it finishes executing. + +:::code language="csharp" source="~/snippets/csharp/System/Random/Overview/threadsafeex1.cs" id="Snippet3"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Random/Overview/threadsafeex1.fs" id="Snippet3"::: +:::code language="vb" source="~/snippets/visualbasic/System/Random/Overview/threadsafeex1.vb" id="Snippet3"::: + +The example ensures thread-safety in the following ways: + +- The attribute is used to define thread-local variables that track the total number of random numbers generated and their sum for each thread. +- A lock (the `lock` statement in C#, the `lock` function in F# and the `SyncLock` statement in Visual Basic) protects access to the variables for the total count and sum of all random numbers generated on all threads. +- A semaphore (the object) is used to ensure that the main thread blocks until all other threads complete execution. +- The example checks whether the random number generator has become corrupted by determining whether two consecutive calls to random number generation methods return 0. If corruption is detected, the example uses the object to signal that all threads should be canceled. +- Before generating each random number, each thread checks the state of the object. If cancellation is requested, the example calls the method to cancel the thread. + +The following example is identical to the first, except that it uses a object and a lambda expression instead of objects. + +:::code language="csharp" source="~/snippets/csharp/System/Random/Overview/threadsafeex2.cs" id="Snippet4"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Random/Overview/threadsafeex2.fs" id="Snippet4"::: +:::code language="vb" source="~/snippets/visualbasic/System/Random/Overview/threadsafeex2.vb" id="Snippet4"::: + +It differs from the first example in the following ways: + +- The variables to keep track of the number of random numbers generated and their sum in each task are local to the task, so there is no need to use the attribute. +- The static method is used to ensure that the main thread doesn't complete before all tasks have finished. There is no need for the object. +- The exception that results from task cancellation is surfaced in the method. In the previous example, it is handled by each thread. + +## Generate different types of random numbers + +The random number generator provides methods that let you generate the following kinds of random numbers: + +- A series of values. You determine the number of byte values by passing an array initialized to the number of elements you want the method to return to the method. The following example generates 20 bytes. + + :::code language="csharp" source="~/snippets/csharp/System/Random/Overview/nextbytes1.cs" id="Snippet5"::: + :::code language="fsharp" source="~/snippets/fsharp/System/Random/Overview/nextbytes1.fs" id="Snippet5"::: + :::code language="vb" source="~/snippets/visualbasic/System/Random/Overview/nextbytes1.vb" id="Snippet5"::: + +- A single integer. You can choose whether you want an integer from 0 to a maximum value ( - 1) by calling the method, an integer between 0 and a specific value by calling the method, or an integer within a range of values by calling the method. In the parameterized overloads, the specified maximum value is exclusive; that is, the actual maximum number generated is one less than the specified value. + + The following example calls the method to generate 10 random numbers between -10 and 10. Note that the second argument to the method specifies the exclusive upper bound of the range of random values returned by the method. In other words, the largest integer that the method can return is one less than this value. + + :::code language="csharp" source="~/snippets/csharp/System/Random/Overview/nextex1.cs" id="Snippet6"::: + :::code language="fsharp" source="~/snippets/fsharp/System/Random/Overview/nextex1.fs" id="Snippet6"::: + :::code language="vb" source="~/snippets/visualbasic/System/Random/Overview/nextex1.vb" id="Snippet6"::: + +- A single floating-point value from 0.0 to less than 1.0 by calling the method. The exclusive upper bound of the random number returned by the method is 1, so its actual upper bound is 0.99999999999999978. The following example generates 10 random floating-point numbers. + + :::code language="csharp" source="~/snippets/csharp/System/Random/Overview/nextdoubleex1.cs" id="Snippet7"::: + :::code language="fsharp" source="~/snippets/fsharp/System/Random/Overview/nextdoubleex1.fs" id="Snippet7"::: + :::code language="vb" source="~/snippets/visualbasic/System/Random/Overview/nextdoubleex1.vb" id="Snippet7"::: + +> [!IMPORTANT] +> The method allows you to specify the range of the returned random number. However, the `maxValue` parameter, which specifies the upper range returned number, is an exclusive, not an inclusive, value. This means that the method call `Next(0, 100)` returns a value between 0 and 99, and not between 0 and 100. + +You can also use the class for such tasks as generating [random Boolean values](#generate-random-boolean-values), generating [random floating-point values in a specified range](#retrieve-floating-point-values-in-a-specified-range), generating [Generate random 64-bit integers](#generate-random-64-bit-integers), and [retrieving a unique element from an array or collection](#retrieve-a-unique-element-from-an-array-or-collection). + +## Substitute your own algorithm + +You can implement your own random number generator by inheriting from the class and supplying your random number generation algorithm. To supply your own algorithm, you must override the method, which implements the random number generation algorithm. You should also override the , , and methods to ensure that they call your overridden method. You don't have to override the and methods. + +For an example that derives from the class and modifies its default pseudo-random number generator, see the reference page. + +## Retrieve the same sequence of random values + +Sometimes you want to generate the same sequence of random numbers in software test scenarios and in game playing. Testing with the same sequence of random numbers allows you to detect regressions and confirm bug fixes. Using the same sequence of random number in games allows you to replay previous games. + +You can generate the same sequence of random numbers by providing the same seed value to the constructor. The seed value provides a starting value for the pseudo-random number generation algorithm. The following example uses 100100 as an arbitrary seed value to instantiate the object, displays 20 random floating-point values, and persists the seed value. It then restores the seed value, instantiates a new random number generator, and displays the same 20 random floating-point values. Note that the example may produce different sequences of random numbers if run on different versions of .NET. + +:::code language="csharp" source="~/snippets/csharp/System/Random/Overview/same1.cs" id="Snippet12"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Random/Overview/same1.fs" id="Snippet12"::: +:::code language="vb" source="~/snippets/visualbasic/System/Random/Overview/same1.vb" id="Snippet12"::: + +## Retrieve unique sequences of random numbers + +Providing different seed values to instances of the class causes each random number generator to produce a different sequence of values. You can provide a seed value either explicitly by calling the constructor, or implicitly by calling the constructor. Most developers call the parameterless constructor, which uses the system clock. The following example uses this approach to instantiate two instances. Each instance displays a series of 10 random integers. + +:::code language="csharp" source="~/snippets/csharp/System/Random/Overview/unique.cs" id="Snippet13"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Random/Overview/unique.fs" id="Snippet13"::: +:::code language="vb" source="~/snippets/visualbasic/System/Random/Overview/unique.vb" id="Snippet13"::: + +## Retrieve integers in a specified range + +You can retrieve integers in a specified range by calling the method, which lets you specify both the lower and the upper bound of the numbers you'd like the random number generator to return. The upper bound is an exclusive, not an inclusive, value. That is, it isn't included in the range of values returned by the method. The following example uses this method to generate random integers between -10 and 10. Note that it specifies 11, which is one greater than the desired value, as the value of the `maxValue` argument in the method call. + +:::code language="csharp" source="~/snippets/csharp/System/Random/Overview/range1.cs" id="Snippet15"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Random/Overview/range1.fs" id="Snippet15"::: +:::code language="vb" source="~/snippets/visualbasic/System/Random/Overview/range1.vb" id="Snippet15"::: + +## Retrieve integers with a specified number of digits + +You can call the method to retrieve numbers with a specified number of digits. For example, to retrieve numbers with four digits (that is, numbers that range from 1000 to 9999), you call the method with a `minValue` value of 1000 and a `maxValue` value of 10000, as the following example shows. + +:::code language="csharp" source="~/snippets/csharp/System/Random/Overview/range2.cs" id="Snippet16"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Random/Overview/range2.fs" id="Snippet16"::: +:::code language="vb" source="~/snippets/visualbasic/System/Random/Overview/range2.vb" id="Snippet16"::: + +## Retrieve floating-point values in a specified range + +The method returns random floating-point values that range from 0 to less than 1. However, you'll often want to generate random values in some other range. + +If the interval between the minimum and maximum desired values is 1, you can add the difference between the desired starting interval and 0 to the number returned by the method. The following example does this to generate 10 random numbers between -1 and 0. + +:::code language="csharp" source="~/snippets/csharp/System/Random/Overview/doublerange2.cs" id="Snippet17"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Random/Overview/doublerange2.fs" id="Snippet17"::: +:::code language="vb" source="~/snippets/visualbasic/System/Random/Overview/doublerange2.vb" id="Snippet17"::: + +To generate random floating-point numbers whose lower bound is 0 but upper bound is greater than 1 (or, in the case of negative numbers, whose lower bound is less than -1 and upper bound is 0), multiply the random number by the non-zero bound. The following example does this to generate 20 million random floating-point numbers that range from 0 to . In also displays the distribution of the random values generated by the method. + +:::code language="csharp" source="~/snippets/csharp/System/Random/Overview/doublerange1.cs" id="Snippet18"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Random/Overview/doublerange1.fs" id="Snippet18"::: +:::code language="vb" source="~/snippets/visualbasic/System/Random/Overview/doublerange1.vb" id="Snippet18"::: + +To generate random floating-point numbers between two arbitrary values, like the method does for integers, use the following formula: + +```csharp +Random.NextDouble() * (maxValue - minValue) + minValue +``` + +The following example generates 1 million random numbers that range from 10.0 to 11.0, and displays their distribution. + +:::code language="csharp" source="~/snippets/csharp/System/Random/Overview/doublerange3.cs" id="Snippet19"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Random/Overview/doublerange3.fs" id="Snippet19"::: +:::code language="vb" source="~/snippets/visualbasic/System/Random/Overview/doublerange3.vb" id="Snippet19"::: + +## Generate random Boolean values + +The class doesn't provide methods that generate values. However, you can define your own class or method to do that. The following example defines a class, `BooleanGenerator`, with a single method, `NextBoolean`. The `BooleanGenerator` class stores a object as a private variable. The `NextBoolean` method calls the method and passes the result to the method. Note that 2 is used as the argument to specify the upper bound of the random number. Since this is an exclusive value, the method call returns either 0 or 1. + +:::code language="csharp" source="~/snippets/csharp/System/Random/Overview/booleans1.cs" id="Snippet8"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Random/Overview/booleans1.fs" id="Snippet8"::: +:::code language="vb" source="~/snippets/visualbasic/System/Random/Overview/booleans1.vb" id="Snippet8"::: + +Instead of creating a separate class to generate random values, the example could simply have defined a single method. In that case, however, the object should have been defined as a class-level variable to avoid instantiating a new instance in each method call. In Visual Basic, the Random instance can be defined as a [Static](/dotnet/visual-basic/language-reference/modifiers/static) variable in the `NextBoolean` method. The following example provides an implementation. + +:::code language="csharp" source="~/snippets/csharp/System/Random/Overview/booleans2.cs" id="Snippet20"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Random/Overview/booleans2.fs" id="Snippet20"::: +:::code language="vb" source="~/snippets/visualbasic/System/Random/Overview/booleans2.vb" id="Snippet20"::: + +## Generate random 64-bit integers + +The overloads of the method return 32-bit integers. However, in some cases, you might want to work with 64-bit integers. You can do this as follows: + +1. Call the method to retrieve a double-precision floating point value. + +2. Multiply that value by . + +The following example uses this technique to generate 20 million random long integers and categorizes them in 10 equal groups. It then evaluates the distribution of the random numbers by counting the number in each group from 0 to . As the output from the example shows, the numbers are distributed more or less equally through the range of a long integer. + +:::code language="csharp" source="~/snippets/csharp/System/Random/Overview/long1.cs" id="Snippet14"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Random/Overview/long1.fs" id="Snippet14"::: +:::code language="vb" source="~/snippets/visualbasic/System/Random/Overview/long1.vb" id="Snippet14"::: + +An alternative technique that uses bit manipulation does not generate truly random numbers. This technique calls to generate two integers, left-shifts one by 32 bits, and ORs them together. This technique has two limitations: + +1. Because bit 31 is the sign bit, the value in bit 31 of the resulting long integer is always 0. This can be addressed by generating a random 0 or 1, left-shifting it 31 bits, and ORing it with the original random long integer. + +2. More seriously, because the probability that the value returned by will be 0, there will be few if any random numbers in the range 0x0-0x00000000FFFFFFFF. + +## Retrieve bytes in a specified range + +The overloads of the method allow you to specify the range of random numbers, but the method does not. The following example implements a `NextBytes` method that lets you specify the range of the returned bytes. It defines a `Random2` class that derives from and overloads its `NextBytes` method. + +:::code language="csharp" source="~/snippets/csharp/System/Random/Overview/bytes1.cs" id="Snippet9"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Random/Overview/bytes1.fs" id="Snippet9"::: +:::code language="vb" source="~/snippets/visualbasic/System/Random/Overview/bytes1.vb" id="Snippet9"::: + +The `NextBytes(Byte[], Byte, Byte)` method wraps a call to the method and specifies the minimum value and one greater than the maximum value (in this case, 0 and 101) that we want returned in the byte array. Because we are sure that the integer values returned by the method are within the range of the data type, we can safely cast them (in C# and F#) or convert them (in Visual Basic) from integers to bytes. + +## Retrieve an element from an array or collection at random + +Random numbers often serve as indexes to retrieve values from arrays or collections. To retrieve a random index value, you can call the method, and use the lower bound of the array as the value of its `minValue` argument and one greater than the upper bound of the array as the value of its `maxValue` argument. For a zero-based array, this is equivalent to its property, or one greater than the value returned by the method. The following example randomly retrieves the name of a city in the United States from an array of cities. + +:::code language="csharp" source="~/snippets/csharp/System/Random/Overview/array1.cs" id="Snippet10"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Random/Overview/array1.fs" id="Snippet10"::: +:::code language="vb" source="~/snippets/visualbasic/System/Random/Overview/array1.vb" id="Snippet10"::: + +## Retrieve a unique element from an array or collection + +A random number generator can always return duplicate values. As the range of numbers becomes smaller or the number of values generated becomes larger, the probability of duplicates grows. If random values must be unique, more numbers are generated to compensate for duplicates, resulting in increasingly poor performance. + +There are a number of techniques to handle this scenario. One common solution is to create an array or collection that contains the values to be retrieved, and a parallel array that contains random floating-point numbers. The second array is populated with random numbers at the time the first array is created, and the method is used to sort the first array by using the values in the parallel array. + +For example, if you're developing a Solitaire game, you want to ensure that each card is used only once. Instead of generating random numbers to retrieve a card and tracking whether that card has already been dealt, you can create a parallel array of random numbers that can be used to sort the deck. Once the deck is sorted, your app can maintain a pointer to indicate the index of the next card on the deck. + +The following example illustrates this approach. It defines a `Card` class that represents a playing card and a `Dealer` class that deals a deck of shuffled cards. The `Dealer` class constructor populates two arrays: a `deck` array that has class scope and that represents all the cards in the deck; and a local `order` array that has the same number of elements as the `deck` array and is populated with randomly generated values. The method is then called to sort the `deck` array based on the values in the `order` array. + +:::code language="csharp" source="~/snippets/csharp/System/Random/Overview/uniquearray1.cs" id="Snippet11"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Random/Overview/uniquearray1.fs" id="Snippet11"::: +:::code language="vb" source="~/snippets/visualbasic/System/Random/Overview/uniquearray1.vb" id="Snippet11"::: +]]> Represents a single-precision floating-point number. - For more information about this API, see Supplemental API remarks for Single. + + value type represents a single-precision 32-bit number with values ranging from negative 3.402823e38 to positive 3.402823e38, as well as positive or negative zero, , , and not a number (). It is intended to represent values that are extremely large (such as distances between planets or galaxies) or extremely small (such as the molecular mass of a substance in kilograms) and that often are imprecise (such as the distance from earth to another solar system). The type complies with the IEC 60559:1989 (IEEE 754) standard for binary floating-point arithmetic. + + provides methods to compare instances of this type, to convert the value of an instance to its string representation, and to convert the string representation of a number to an instance of this type. For information about how format specification codes control the string representation of value types, see [Formatting Types](/dotnet/standard/base-types/formatting-types), [Standard Numeric Format Strings](/dotnet/standard/base-types/standard-numeric-format-strings), and [Custom Numeric Format Strings](/dotnet/standard/base-types/custom-numeric-format-strings). + +## Floating-point representation and precision + +The data type stores single-precision floating-point values in a 32-bit binary format, as shown in the following table: + +| Part | Bits | +|-----------------------------------|-------| +| Significand or mantissa | 0-22 | +| Exponent | 23-30 | +| Sign (0 = positive, 1 = negative) | 31 | + +Just as decimal fractions are unable to precisely represent some fractional values (such as 1/3 or ), binary fractions are unable to represent some fractional values. For example, 2/10, which is represented precisely by .2 as a decimal fraction, is represented by .0011111001001100 as a binary fraction, with the pattern "1100" repeating to infinity. In this case, the floating-point value provides an imprecise representation of the number that it represents. Performing additional mathematical operations on the original floating-point value often increases its lack of precision. For example, if you compare the results of multiplying .3 by 10 and adding .3 to .3 nine times, you will see that addition produces the less precise result, because it involves eight more operations than multiplication. Note that this disparity is apparent only if you display the two values by using the "R" [standard numeric format string](/dotnet/standard/base-types/standard-numeric-format-strings), which, if necessary, displays all 9 digits of precision supported by the type. + +:::code language="csharp" source="~/snippets/csharp/System/Single/Overview/representation1.cs" id="Snippet3"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Single/Overview/representation1.fs" id="Snippet3"::: +:::code language="vb" source="~/snippets/visualbasic/System/Single/Overview/representation1.vb" id="Snippet3"::: + +Because some numbers cannot be represented exactly as fractional binary values, floating-point numbers can only approximate real numbers. + +All floating-point numbers have a limited number of significant digits, which also determines how accurately a floating-point value approximates a real number. A value has up to 7 decimal digits of precision, although a maximum of 9 digits is maintained internally. This means that some floating-point operations may lack the precision to change a floating-point value. The following example defines a large single-precision floating-point value, and then adds the product of and one quadrillion to it. However, the product is too small to modify the original floating-point value. Its least significant digit is thousandths, whereas the most significant digit in the product is 10-30. + +:::code language="csharp" source="~/snippets/csharp/System/Single/Overview/representation2.cs" id="Snippet4"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Single/Overview/representation2.fs" id="Snippet4"::: +:::code language="vb" source="~/snippets/visualbasic/System/Single/Overview/representation2.vb" id="Snippet4"::: + +The limited precision of a floating-point number has several consequences: + +- Two floating-point numbers that appear equal for a particular precision might not compare equal because their least significant digits are different. In the following example, a series of numbers are added together, and their total is compared with their expected total. A call to the `Equals` method indicates that the values aren't equal. + + :::code language="csharp" source="~/snippets/csharp/System/Single/Overview/precisionlist3.cs" id="Snippet6"::: + :::code language="fsharp" source="~/snippets/fsharp/System/Single/Overview/precisionlist3.fs" id="Snippet6"::: + :::code language="vb" source="~/snippets/visualbasic/System/Single/Overview/precisionlist3.vb" id="Snippet6"::: + + The two values are unequal because of a loss of precision during the addition operations. In this case, the issue can be resolved by calling the method to round the values to the desired precision before performing the comparison. + +- A mathematical or comparison operation that uses a floating-point number might not yield the same result if a decimal number is used, because the binary floating-point number might not equal the decimal number. A previous example illustrated this by displaying the result of multiplying .3 by 10 and adding .3 to .3 nine times. + + When accuracy in numeric operations with fractional values is important, use the type instead of the type. When accuracy in numeric operations with integral values beyond the range of the or types is important, use the type. + +- values have less precision than values. A value that is converted to a seemingly equivalent often does not equal the value because of differences in precision. In the following example, the result of identical division operations is assigned to a value and a value. After the value is cast to a , a comparison of the two values shows that they are unequal. + + :::code language="csharp" source="~/snippets/csharp/System/Double/Overview/precisionlist1.cs" id="Snippet5"::: + :::code language="fsharp" source="~/snippets/fsharp/System/Double/Overview/precisionlist1.fs" id="Snippet5"::: + :::code language="vb" source="~/snippets/visualbasic/System/Double/Overview/precisionlist1.vb" id="Snippet5"::: + + To avoid this problem, either use the data type in place of the data type, or use the method so that both values have the same precision. + +## Test for equality + +To be considered equal, two values must represent identical values. However, because of differences in precision between values, or because of a loss of precision by one or both values, floating-point values that are expected to be identical often turn out to be unequal due to differences in their least significant digits. As a result, calls to the method to determine whether two values are equal, or calls to the method to determine the relationship between two values, often yield unexpected results. This is evident in the following example, where two apparently equal values turn out to be unequal, because the first value has 7 digits of precision, whereas the second value has 9. + +:::code language="csharp" source="~/snippets/csharp/System/Single/Overview/comparison1.cs" id="Snippet9"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Single/Overview/comparison1.fs" id="Snippet9"::: +:::code language="vb" source="~/snippets/visualbasic/System/Single/Overview/comparison1.vb" id="Snippet9"::: + +Calculated values that follow different code paths and that are manipulated in different ways often prove to be unequal. In the following example, one value is squared, and then the square root is calculated to restore the original value. A second is multiplied by 3.51 and squared before the square root of the result is divided by 3.51 to restore the original value. Although the two values appear to be identical, a call to the method indicates that they are not equal. + +:::code language="csharp" source="~/snippets/csharp/System/Single/Overview/comparison2.cs" id="Snippet10"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Single/Overview/comparison2.fs" id="Snippet10"::: +:::code language="vb" source="~/snippets/visualbasic/System/Single/Overview/comparison2.vb" id="Snippet10"::: + +In cases where a loss of precision is likely to affect the result of a comparison, you can use the following techniques instead of calling the or method: + +- Call the method to ensure that both values have the same precision. The following example modifies a previous example to use this approach so that two fractional values are equivalent. + + :::code language="csharp" source="~/snippets/csharp/System/Single/Overview/comparison3.cs" id="Snippet11"::: + :::code language="fsharp" source="~/snippets/fsharp/System/Single/Overview/comparison3.fs" id="Snippet11"::: + :::code language="vb" source="~/snippets/visualbasic/System/Single/Overview/comparison3.vb" id="Snippet11"::: + + The problem of precision still applies to rounding of midpoint values. For more information, see the method. + +- Test for approximate equality instead of equality. This technique requires that you define either an absolute amount by which the two values can differ but still be equal, or that you define a relative amount by which the smaller value can diverge from the larger value. + + > [!WARNING] + > is sometimes used as an absolute measure of the distance between two values when testing for equality. However, measures the smallest possible value that can be added to, or subtracted from, a whose value is zero. For most positive and negative values, the value of is too small to be detected. Therefore, except for values that are zero, we do not recommend its use in tests for equality. + + The following example uses the latter approach to define an `IsApproximatelyEqual` method that tests the relative difference between two values. It also contrasts the result of calls to the `IsApproximatelyEqual` method and the method. + + :::code language="csharp" source="~/snippets/csharp/System/Single/Overview/comparison4.cs" id="Snippet12"::: + :::code language="fsharp" source="~/snippets/fsharp/System/Single/Overview/comparison4.fs" id="Snippet12"::: + :::code language="vb" source="~/snippets/visualbasic/System/Single/Overview/comparison4.vb" id="Snippet12"::: + +## Floating-point values and exceptions + +Operations with floating-point values do not throw exceptions, unlike operations with integral types, which throw exceptions in cases of illegal operations such as division by zero or overflow. Instead, in these situations, the result of a floating-point operation is zero, positive infinity, negative infinity, or not a number (NaN): + +- If the result of a floating-point operation is too small for the destination format, the result is zero. This can occur when two very small floating-point numbers are multiplied, as the following example shows. + + :::code language="csharp" source="~/snippets/csharp/System/Single/Overview/exceptional1.cs" id="Snippet1"::: + :::code language="fsharp" source="~/snippets/fsharp/System/Single/Overview/exceptional1.fs" id="Snippet1"::: + :::code language="vb" source="~/snippets/visualbasic/System/Single/Overview/exceptional1.vb" id="Snippet1"::: + +- If the magnitude of the result of a floating-point operation exceeds the range of the destination format, the result of the operation is or , as appropriate for the sign of the result. The result of an operation that overflows is , and the result of an operation that overflows is , as the following example shows. + + :::code language="csharp" source="~/snippets/csharp/System/Single/Overview/exceptional2.cs" id="Snippet2"::: + :::code language="fsharp" source="~/snippets/fsharp/System/Single/Overview/exceptional2.fs" id="Snippet2"::: + :::code language="vb" source="~/snippets/visualbasic/System/Single/Overview/exceptional2.vb" id="Snippet2"::: + + also results from a division by zero with a positive dividend, and results from a division by zero with a negative dividend. + +- If a floating-point operation is invalid, the result of the operation is . For example, results from the following operations: + + - Division by zero with a dividend of zero. Note that other cases of division by zero result in either or . + - Any floating-point operation with invalid input. For example, attempting to find the square root of a negative value returns . + - Any operation with an argument whose value is . + +## Type conversions + +The structure does not define any explicit or implicit conversion operators; instead, conversions are implemented by the compiler. + +The following table lists the possible conversions of a value of the other primitive numeric types to a value. It also indicates whether the conversion is widening or narrowing and whether the resulting may have less precision than the original value. + +| Conversion from | Widening/narrowing | Possible loss of precision | +|---------------------|--------------------|----------------------------| +| | Widening | No | +||Widening

Note that C# requires a cast operator.|Yes. supports 29 decimal digits of precision; supports 9.| +||Narrowing; out-of-range values are converted to or .|Yes. supports 17 decimal digits of precision; supports 9.| +| | Widening | No | +||Widening|Yes. supports 10 decimal digits of precision; supports 9.| +||Widening|Yes. supports 19 decimal digits of precision; supports 9.| +||Widening|No| +||Widening|No| +||Widening|Yes. supports 10 decimal digits of precision; supports 9.| +||Widening|Yes. supports 20 decimal digits of precision; supports 9.| + +The following example converts the minimum or maximum value of other primitive numeric types to a value. + +:::code language="csharp" source="~/snippets/csharp/System/Single/Overview/convert1.cs" id="Snippet20"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Single/Overview/convert1.fs" id="Snippet20"::: +:::code language="vb" source="~/snippets/visualbasic/System/Single/Overview/convert1.vb" id="Snippet20"::: + +In addition, the values , , and convert to , , and , respectively. + +Note that the conversion of the value of some numeric types to a value can involve a loss of precision. As the example illustrates, a loss of precision is possible when converting , , , , , and values to values. + +The conversion of a value to a is a widening conversion. The conversion may result in a loss of precision if the type does not have a precise representation for the value. + +The conversion of a value to a value of any primitive numeric data type other than a is a narrowing conversion and requires a cast operator (in C#) or a conversion method (in Visual Basic). Values that are outside the range of the target data type, which are defined by the target type's `MinValue` and `MaxValue` properties, behave as shown in the following table. + +| Target type | Result | +|-----------------------|-----------------------------------------------| +| Any integral type | An exception if the conversion occurs in a checked context.

If the conversion occurs in an unchecked context (the default in C#), the conversion operation succeeds but the value overflows. | +| | An exception. | + +In addition, , , and throw an for conversions to integers in a checked context, but these values overflow when converted to integers in an unchecked context. For conversions to , they always throw an . For conversions to , they convert to , , and , respectively. + +Note that a loss of precision may result from converting a value to another numeric type. In the case of converting non-integral values, as the output from the example shows, the fractional component is lost when the value is either rounded (as in Visual Basic) or truncated (as in C# and F#). For conversions to values, the value may not have a precise representation in the target data type. + +The following example converts a number of values to several other numeric types. The conversions occur in a checked context in Visual Basic (the default), in C# (because of the [checked](/dotnet/csharp/language-reference/keywords/checked) keyword), and in F# (because of the `open Checked` statement). The output from the example shows the result for conversions in both a checked an unchecked context. You can perform conversions in an unchecked context in Visual Basic by compiling with the `/removeintchecks+` compiler switch, in C# by commenting out the `checked` statement, and in F# by commenting out the `open Checked` statement. + +:::code language="csharp" source="~/snippets/csharp/System/Single/Overview/convert2.cs" id="Snippet21"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Single/Overview/convert2.fs" id="Snippet21"::: +:::code language="vb" source="~/snippets/visualbasic/System/Single/Overview/convert2.vb" id="Snippet21"::: + +For more information on the conversion of numeric types, see [Type Conversion in .NET](/dotnet/standard/base-types/type-conversion) and [Type Conversion Tables](/dotnet/standard/base-types/conversion-tables). + +## Floating-point functionality + +The structure and related types provide methods to perform the following categories of operations: + +- **Comparison of values**. You can call the method to determine whether two values are equal, or the method to determine the relationship between two values. + + The structure also supports a complete set of comparison operators. For example, you can test for equality or inequality, or determine whether one value is greater than or equal to another value. If one of the operands is a , the value is converted to a before performing the comparison. If one of the operands is an integral type, it is converted to a before performing the comparison. Although these are widening conversions, they may involve a loss of precision. + + > [!WARNING] + > Because of differences in precision, two values that you expect to be equal may turn out to be unequal, which affects the result of the comparison. See the [Test for equality](#test-for-equality) section for more information about comparing two values. + + You can also call the , , , and methods to test for these special values. + +- **Mathematical operations**. Common arithmetic operations such as addition, subtraction, multiplication, and division are implemented by language compilers and Common Intermediate Language (CIL) instructions rather than by methods. If the other operand in a mathematical operation is a , the is converted to a before performing the operation, and the result of the operation is also a value. If the other operand is an integral type, it is converted to a before performing the operation, and the result of the operation is also a value. + + You can perform other mathematical operations by calling `static` (`Shared` in Visual Basic) methods in the class. These include additional methods commonly used for arithmetic (such as , , and ), geometry (such as and ), and calculus (such as ). In all cases, the value is converted to a . + + You can also manipulate the individual bits in a value. The method returns its bit pattern in a byte array. By passing that byte array to the method, you can also preserve the value's bit pattern in a 32-bit integer. + +- **Rounding**. Rounding is often used as a technique for reducing the impact of differences between values caused by problems of floating-point representation and precision. You can round a value by calling the method. However, note that the value is converted to a before the method is called, and the conversion can involve a loss of precision. + +- **Formatting**. You can convert a value to its string representation by calling the method or by using the [composite formatting](/dotnet/standard/base-types/composite-formatting) feature. For information about how format strings control the string representation of floating-point values, see [Standard Numeric Format Strings](/dotnet/standard/base-types/standard-numeric-format-strings) and [Custom Numeric Format Strings](/dotnet/standard/base-types/custom-numeric-format-strings). + +- **Parsing strings**. You can convert the string representation of a floating-point value to a value by calling the or method. If the parse operation fails, the method throws an exception, whereas the method returns `false`. + +- **Type conversion**. The structure provides an explicit interface implementation for the interface, which supports conversion between any two standard .NET data types. Language compilers also support the implicit conversion of values for all other standard numeric types except for the conversion of to values. Conversion of a value of any standard numeric type other than a to a is a widening conversion and does not require the use of a casting operator or conversion method. + + However, conversion of 32-bit and 64-bit integer values can involve a loss of precision. The following table lists the differences in precision for 32-bit, 64-bit, and types: + + | Type | Maximum precision (decimal digits) | Internal precision (decimal digits) | + |----------------------|------------------------------------|-------------------------------------| + | | 15 | 17 | + | and | 10 | 10 | + | and | 19 | 19 | + | | 7 | 9 | + + The problem of precision most frequently affects values that are converted to values. In the following example, two values produced by identical division operations are unequal, because one of the values is a single-precision floating point value that is converted to a . + + :::code language="csharp" source="~/snippets/csharp/System/Single/Overview/precisionlist1.cs" id="Snippet5"::: + :::code language="fsharp" source="~/snippets/fsharp/System/Single/Overview/precisionlist1.fs" id="Snippet5"::: + :::code language="vb" source="~/snippets/visualbasic/System/Single/Overview/precisionlist1.vb" id="Snippet5"::: + + ]]>
+
All members of this type are thread safe. Members that appear to modify instance state actually return a new instance initialized with the new value. As with any other type, reading and writing to a shared variable that contains an instance of this type must be protected by a lock to guarantee thread safety. @@ -1089,7 +1294,45 @@ This computes `arctan(x) / π` in the interval `[-0.5, +0.5]`. Greater than zero This instance is greater than , OR this instance is a number and is not a number (), OR is . - For more information about this API, see Supplemental API remarks for Single.CompareTo. + + method may seem surprising at times. For example, multiplication by a particular value followed by division by the same value should produce the original value, but in the following example, the computed value turns out to be greater than the original value. Showing all significant digits of the two values by using the "R" [standard numeric format string](/dotnet/standard/base-types/standard-numeric-format-strings) indicates that the computed value differs from the original value in its least significant digits. For information about handling such comparisons, see the Remarks section of the method. + +Although an object whose value is is not considered equal to another object whose value is (even itself), the interface requires that `A.CompareTo(A)` return zero. + +## CompareTo(System.Object) + +The `value` parameter must be `null` or an instance of ; otherwise, an exception is thrown. Any instance of , regardless of its value, is considered greater than `null`. + +:::code language="csharp" source="~/snippets/csharp/System/Single/CompareTo/compareto3.cs" id="Snippet2"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Single/CompareTo/compareto3.fs" id="Snippet2"::: +:::code language="vb" source="~/snippets/visualbasic/System/Single/CompareTo/compareto3.vb" id="Snippet2"::: + +This method is implemented to support the interface. + +## CompareTo(System.Single) + +This method implements the interface and performs slightly better than the overload because it doesn't have to convert the `value` parameter to an object. + +:::code language="csharp" source="~/snippets/csharp/System/Single/CompareTo/compareto2.cs" id="Snippet1"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Single/CompareTo/compareto2.fs" id="Snippet1"::: +:::code language="vb" source="~/snippets/visualbasic/System/Single/CompareTo/compareto2.vb" id="Snippet1"::: + +## Widening conversions + +Depending on your programming language, it might be possible to code a method where the parameter type has fewer bits (is narrower) than the instance type. This is possible because some programming languages perform an implicit widening conversion that represents the parameter as a type with as many bits as the instance. + +For example, suppose the instance type is and the parameter type is . The Microsoft C# compiler generates instructions to represent the value of the parameter as a object, then generates a method that compares the values of the instance and the widened representation of the parameter. + +Consult your programming language's documentation to determine if its compiler performs implicit widening conversions of numeric types. For more information, see the [Type Conversion Tables](/dotnet/standard/base-types/conversion-tables) topic. + +## Precision in comparisons + +The precision of floating-point numbers beyond the documented precision is specific to the implementation and version of .NET. Consequently, a comparison of two particular numbers might change between versions of .NET because the precision of the numbers' internal representation might change. + + ]]> + method. @@ -1168,7 +1411,45 @@ The following code example demonstrates the meth This instance is greater than , or this instance is a number and is not a number (). - For more information about this API, see Supplemental API remarks for Single.CompareTo. + + method may seem surprising at times. For example, multiplication by a particular value followed by division by the same value should produce the original value, but in the following example, the computed value turns out to be greater than the original value. Showing all significant digits of the two values by using the "R" [standard numeric format string](/dotnet/standard/base-types/standard-numeric-format-strings) indicates that the computed value differs from the original value in its least significant digits. For information about handling such comparisons, see the Remarks section of the method. + +Although an object whose value is is not considered equal to another object whose value is (even itself), the interface requires that `A.CompareTo(A)` return zero. + +## CompareTo(System.Object) + +The `value` parameter must be `null` or an instance of ; otherwise, an exception is thrown. Any instance of , regardless of its value, is considered greater than `null`. + +:::code language="csharp" source="~/snippets/csharp/System/Single/CompareTo/compareto3.cs" id="Snippet2"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Single/CompareTo/compareto3.fs" id="Snippet2"::: +:::code language="vb" source="~/snippets/visualbasic/System/Single/CompareTo/compareto3.vb" id="Snippet2"::: + +This method is implemented to support the interface. + +## CompareTo(System.Single) + +This method implements the interface and performs slightly better than the overload because it doesn't have to convert the `value` parameter to an object. + +:::code language="csharp" source="~/snippets/csharp/System/Single/CompareTo/compareto2.cs" id="Snippet1"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Single/CompareTo/compareto2.fs" id="Snippet1"::: +:::code language="vb" source="~/snippets/visualbasic/System/Single/CompareTo/compareto2.vb" id="Snippet1"::: + +## Widening conversions + +Depending on your programming language, it might be possible to code a method where the parameter type has fewer bits (is narrower) than the instance type. This is possible because some programming languages perform an implicit widening conversion that represents the parameter as a type with as many bits as the instance. + +For example, suppose the instance type is and the parameter type is . The Microsoft C# compiler generates instructions to represent the value of the parameter as a object, then generates a method that compares the values of the instance and the widened representation of the parameter. + +Consult your programming language's documentation to determine if its compiler performs implicit widening conversions of numeric types. For more information, see the [Type Conversion Tables](/dotnet/standard/base-types/conversion-tables) topic. + +## Precision in comparisons + +The precision of floating-point numbers beyond the documented precision is specific to the implementation and version of .NET. Consequently, a comparison of two particular numbers might change between versions of .NET because the precision of the numbers' internal representation might change. + + ]]> + method for several value and reference types. @@ -1702,7 +1983,36 @@ This is known as Euler's number and is approximately 2.7182818284590452354. 1.401298E-45 Represents the smallest positive value that is greater than zero. This field is constant. - For more information about this API, see Supplemental API remarks for Single.Epsilon. + + property reflects the smallest positive value that is significant in numeric operations or comparisons when the value of the instance is zero. For example, the following code shows that zero and are considered to be unequal values, whereas zero and half the value of are considered to be equal. + +:::code language="csharp" source="~/snippets/csharp/System/Single/Epsilon/epsilon.cs" id="Snippet5"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Single/Epsilon/epsilon.fs" id="Snippet5"::: +:::code language="vb" source="~/snippets/visualbasic/System/Single/Epsilon/epsilon.vb" id="Snippet5"::: + +More precisely, the single-precision floating-point format consists of a sign, a 23-bit mantissa or significand, and an 8-bit exponent. As the following example shows, zero has an exponent of -126 and a mantissa of 0. has an exponent of -126 and a mantissa of 1. This means that is the smallest positive value that is greater than zero and represents the smallest possible value and the smallest possible increment for a whose exponent is -126. + +:::code language="csharp" source="~/snippets/csharp/System/Single/Epsilon/epsilon1.cs" id="Snippet6"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Single/Epsilon/epsilon1.fs" id="Snippet6"::: +:::code language="vb" source="~/snippets/visualbasic/System/Single/Epsilon/epsilon1.vb" id="Snippet6"::: + +However, the property is not a general measure of precision of the type; it applies only to instances that have a value of zero. + +> [!NOTE] +> The value of the property is not equivalent to machine epsilon, which represents the upper bound of the relative error due to rounding in floating-point arithmetic. + +The value of this constant is 1.4e-45. + +Two apparently equivalent floating-point numbers might not compare equal because of differences in their least significant digits. For example, the C# expression, `(float)1/3 == (float)0.33333`, does not compare equal because the division operation on the left side has maximum precision while the constant on the right side is precise only to the specified digits. If you create a custom algorithm that determines whether two floating-point numbers can be considered equal, you must use a value that is greater than the constant to establish the acceptable absolute margin of difference for the two values to be considered equal. (Typically, that margin of difference is many times greater than .) + +## Platform notes + +On ARM systems, the value of the constant is too small to be detected, so it equates to zero. You can define an alternative epsilon value that equals 1.175494351E-38 instead. + + ]]> + @@ -1860,7 +2170,48 @@ This is known as Euler's number and is approximately 2.7182818284590452354. Returns a value indicating whether this instance and a specified object represent the same value. if is equal to this instance; otherwise, . - For more information about this API, see Supplemental API remarks for Single.Equals. + + method implements the interface, and performs slightly better than because it does not have to convert the `obj` parameter to an object. + +## Widening conversions + +Depending on your programming language, it might be possible to code an method where the parameter type has fewer bits (is narrower) than the instance type. This is possible because some programming languages perform an implicit widening conversion that represents the parameter as a type with as many bits as the instance. + +For example, suppose the instance type is and the parameter type is . The Microsoft C# compiler generates instructions to represent the value of the parameter as a object, and then generates a method that compares the values of the instance and the widened representation of the parameter. + +Consult your programming language's documentation to determine if its compiler performs implicit widening conversions of numeric types. For more information, see [Type Conversion Tables](/dotnet/standard/base-types/conversion-tables). + +## Precision in comparisons + +The method should be used with caution, because two apparently equivalent values can be unequal because of the differing precision of the two values. The following example reports that the value .3333 and the returned by dividing 1 by 3 are unequal. + +:::code language="csharp" source="~/snippets/csharp/System/Single/Epsilon/SingleEquals_25051.cs" id="Snippet1"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Single/Epsilon/SingleEquals_25051.fs" id="Snippet1"::: +:::code language="vb" source="~/snippets/visualbasic/System/Single/Epsilon/SingleEquals_25051.vb" id="Snippet1"::: + +One comparison technique that avoids the problems associated with comparing for equality involves defining an acceptable margin of difference between two values (such as .01% of one of the values). If the absolute value of the difference between the two values is less than or equal to that margin, the difference is likely to be an outcome of differences in precision and, therefore, the values are likely to be equal. The following example uses this technique to compare .33333 and 1/3, which are the two values that the previous code example found to be unequal. + +:::code language="csharp" source="~/snippets/csharp/System/Single/Epsilon/SingleEquals_25051.cs" id="Snippet2"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Single/Epsilon/SingleEquals_25051.fs" id="Snippet2"::: +:::code language="vb" source="~/snippets/visualbasic/System/Single/Epsilon/SingleEquals_25051.vb" id="Snippet2"::: + +In this case, the values are equal. + +> [!NOTE] +> Because defines the minimum expression of a positive value whose range is near zero, the margin of difference must be greater than . Typically, it is many times greater than . Because of this, we recommend that you do not use when comparing values for equality. + +A second technique that avoids the problems associated with comparing for equality involves comparing the difference between two floating-point numbers with some absolute value. If the difference is less than or equal to that absolute value, the numbers are equal. If it is greater, the numbers are not equal. One way to do this is to arbitrarily select an absolute value. However, this is problematic, because an acceptable margin of difference depends on the magnitude of the values. A second way takes advantage of a design feature of the floating-point format: The difference between the mantissa components in the integer representations of two floating-point values indicates the number of possible floating-point values that separates the two values. For example, the difference between 0.0 and is 1, because is the smallest representable value when working with a whose value is zero. The following example uses this technique to compare .33333 and 1/3, which are the two values that the previous code example with the method found to be unequal. Note that the example uses the and methods to convert a single-precision floating-point value to its integer representation. + +:::code language="csharp" source="~/snippets/csharp/System/Single/Equals/equalsabs1.cs" id="Snippet1"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Single/Equals/equalsabs1.fs" id="Snippet1"::: +:::code language="vb" source="~/snippets/visualbasic/System/Single/Equals/equalsabs1.vb" id="Snippet1"::: + +The precision of floating-point numbers beyond the documented precision is specific to the implementation and version of .NET. Consequently, a comparison of two numbers might produce different results depending on the version of .NET, because the precision of the numbers' internal representation might change. + + ]]> + Compiler overload resolution may account for an apparent difference in the behavior of the two method overloads. If an implicit conversion between the argument and a is defined and the argument is not typed as an , compilers may perform an implicit conversion and call the method. Otherwise, they call the method, which always returns if its argument is not a value. The following example illustrates the difference in behavior between the two method overloads. In the case of all primitive numeric types except for in Visual Basic and except for and in C#, the first comparison returns because the compiler automatically performs a widening conversion and calls the method, whereas the second comparison returns because the compiler calls the method. diff --git a/xml/System/Span`1.xml b/xml/System/Span`1.xml index 730fc6cf8b9..f76ba114a47 100644 --- a/xml/System/Span`1.xml +++ b/xml/System/Span`1.xml @@ -86,7 +86,68 @@ The type of items in the . Provides a type-safe and memory-safe representation of a contiguous region of arbitrary memory. - For more information about this API, see Supplemental API remarks for Span<T>. + + type is a [ref struct](/dotnet/csharp/language-reference/builtin-types/ref-struct) that is allocated on the stack rather than on the managed heap. Ref struct types have some restrictions to ensure that they cannot be promoted to the managed heap, including that they can't be: + +- Boxed. +- Assigned to variables of type or `dynamic`, or to any interface typ. +- Fields in a reference type. +- Used across `await` and `yield` boundaries. + +In addition, calls to two methods, and , throw a . + +> [!IMPORTANT] +> Because it is a stack-only type, `Span` is unsuitable for many scenarios that require storing references to buffers on the heap. This is true, for example, of routines that make asynchronous method calls. For such scenarios, you can use the complementary and types. + +For spans that represent immutable or read-only structures, use . + +## Memory + +A `Span` represents a contiguous region of arbitrary memory. A `Span` instance is often used to hold the elements of an array or a portion of an array. Unlike an array, however, a `Span` instance can point to managed memory, native memory, or memory managed on the stack. The following example creates a `Span` from an array: + +:::code language="csharp" source="~/snippets/csharp/System/Span/Overview/program.cs" id="Snippet1"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Span/Overview/program.fs" id="Snippet1"::: + +The following example creates a `Span` from 100 bytes of native memory: + +:::code language="csharp" source="~/snippets/csharp/System/Span/Overview/program.cs" id="Snippet2"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Span/Overview/program.fs" id="Snippet2"::: + +The following example uses the C# [stackalloc](/dotnet/csharp/language-reference/keywords/stackalloc) keyword to allocate 100 bytes of memory on the stack: + +:::code language="csharp" source="~/snippets/csharp/System/Span/Overview/program.cs" id="Snippet3"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Span/Overview/program.fs" id="Snippet3"::: + +Because `Span` is an abstraction over an arbitrary block of memory, methods of the `Span` type and methods with `Span` parameters operate on any `Span` object regardless of the kind of memory it encapsulates. For example, each of the separate sections of code that initialize the span and calculate the sum of its elements can be refactored into single initialization and calculation methods, as the following example illustrates: + +:::code language="csharp" source="~/snippets/csharp/System/Span/Overview/program.cs" id="Snippet4"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Span/Overview/program.fs" id="Snippet4"::: + +## Arrays + +When it wraps an array, `Span` can wrap an entire array, as it did in the examples in the [Memory](#memory) section. Because it supports slicing, `Span` can also point to any contiguous range within the array. + +The following example creates a slice of the middle five elements of a 10-element integer array. Note that the code doubles the values of each integer in the slice. As the output shows, the changes made by the span are reflected in the values of the array. + +:::code language="csharp" source="~/snippets/csharp/System/Span/Slice/Program.cs"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Span/Slice/Program.fs"::: + +## Slices + +`Span` includes two overloads of the method that form a slice out of the current span that starts at a specified index. This makes it possible to treat the data in a `Span` as a set of logical chunks that can be processed as needed by portions of a data processing pipeline with minimal performance impact. For example, since modern server protocols are often text-based, manipulation of strings and substrings is particularly important. In the class, the major method for extracting substrings is . For data pipelines that rely on extensive string manipulation, its use offers some performance penalties, since it: + +1. Creates a new string to hold the substring. +2. Copies a subset of the characters from the original string to the new string. + +This allocation and copy operation can be eliminated by using either `Span` or , as the following example shows: + +:::code language="csharp" source="~/snippets/csharp/System/Span/Slice/Program2.cs"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Span/Slice/Program2.fs"::: + + ]]> + Memory- and span-related types Memory<T> and Span<T> usage guidelines diff --git a/xml/System/String.xml b/xml/System/String.xml index 336139cf114..6d24b526356 100644 --- a/xml/System/String.xml +++ b/xml/System/String.xml @@ -97,7 +97,449 @@ Represents text as a sequence of UTF-16 code units. - For more information about this API, see Supplemental API remarks for String. + + object is a sequential collection of objects that represent a string; a object corresponds to a UTF-16 code unit. The value of the object is the content of the sequential collection of objects, and that value is immutable (that is, it is read-only). For more information about the immutability of strings, see the [Immutability and the StringBuilder class](#immutability-and-the-stringbuilder-class) section. The maximum size of a object in memory is 2-GB, or about 1 billion characters. + +For more information about Unicode, UTF-16, code units, code points, and the and types, see [Introduction to character encoding in .NET](/dotnet/standard/base-types/character-encoding-introduction). + +## Instantiate a String object + +You can instantiate a object in the following ways: + +- By assigning a string literal to a variable. This is the most commonly used method for creating a string. The following example uses assignment to create several strings. Note that in C# and F#, because the backslash (\\) is an escape character, literal backslashes in a string must be escaped or the entire string must be @-quoted. + + :::code language="csharp" source="~/snippets/csharp/System/String/Overview/program.cs" id="Snippet1"::: + :::code language="fsharp" source="~/snippets/fsharp/System/String/Overview/program.fs" id="Snippet1"::: + :::code language="vb" source="~/snippets/visualbasic/System/String/Overview/instantiate1.vb" id="Snippet1"::: + +- By calling a class constructor. The following example instantiates strings by calling several class constructors. Note that some of the constructors include pointers to character arrays or signed byte arrays as parameters. Visual Basic does not support calls to these constructors. For detailed information about constructors, see the constructor summary. + + :::code language="csharp" source="~/snippets/csharp/System/String/Overview/program.cs" id="Snippet2"::: + :::code language="fsharp" source="~/snippets/fsharp/System/String/Overview/program.fs" id="Snippet2"::: + :::code language="vb" source="~/snippets/visualbasic/System/String/Overview/instantiate1.vb" id="Snippet2"::: + +- By using the string concatenation operator (+ in C# and F#, and & or + in Visual Basic) to create a single string from any combination of instances and string literals. The following example illustrates the use of the string concatenation operator. + + :::code language="csharp" source="~/snippets/csharp/System/String/Overview/program.cs" id="Snippet3"::: + :::code language="fsharp" source="~/snippets/fsharp/System/String/Overview/program.fs" id="Snippet3"::: + :::code language="vb" source="~/snippets/visualbasic/System/String/Overview/instantiate1.vb" id="Snippet3"::: + +- By retrieving a property or calling a method that returns a string. The following example uses the methods of the class to extract a substring from a larger string. + + :::code language="csharp" source="~/snippets/csharp/System/String/Overview/program.cs" id="Snippet4"::: + :::code language="fsharp" source="~/snippets/fsharp/System/String/Overview/program.fs" id="Snippet4"::: + :::code language="vb" source="~/snippets/visualbasic/System/String/Overview/instantiate1.vb" id="Snippet4"::: + +- By calling a formatting method to convert a value or object to its string representation. The following example uses the [composite formatting](/dotnet/standard/base-types/composite-formatting) feature to embed the string representation of two objects into a string. + + :::code language="csharp" source="~/snippets/csharp/System/String/Overview/program.cs" id="Snippet5"::: + :::code language="fsharp" source="~/snippets/fsharp/System/String/Overview/program.fs" id="Snippet5"::: + :::code language="vb" source="~/snippets/visualbasic/System/String/Overview/instantiate1.vb" id="Snippet5"::: + +## Char objects and Unicode characters + +Each character in a string is defined by a Unicode scalar value, also called a Unicode code point or the ordinal (numeric) value of the Unicode character. Each code point is encoded by using UTF-16 encoding, and the numeric value of each element of the encoding is represented by a object. + +> [!NOTE] +> Note that, because a instance consists of a sequential collection of UTF-16 code units, it is possible to create a object that is not a well-formed Unicode string. For example, it is possible to create a string that has a low surrogate without a corresponding high surrogate. Although some methods, such as the methods of encoding and decoding objects in the namespace, may performs checks to ensure that strings are well-formed, class members don't ensure that a string is well-formed. + +A single object usually represents a single code point; that is, the numeric value of the equals the code point. For example, the code point for the character "a" is U+0061. However, a code point might require more than one encoded element (more than one object). The Unicode standard defines two types of characters that correspond to multiple objects: graphemes, and Unicode supplementary code points that correspond to characters in the Unicode supplementary planes. + +- A grapheme is represented by a base character followed by one or more combining characters. For example, the character ä is represented by a object whose code point is U+0061 followed by a object whose code point is U+0308. This character can also be defined by a single object that has a code point of U+00E4. As the following example shows, a culture-sensitive comparison for equality indicates that these two representations are equal, although an ordinary ordinal comparison does not. However, if the two strings are normalized, an ordinal comparison also indicates that they are equal. (For more information on normalizing strings, see the [Normalization](#normalization) section.) + + :::code language="csharp" source="~/snippets/csharp/System/String/Overview/grapheme1.cs" id="Snippet2"::: + :::code language="fsharp" source="~/snippets/fsharp/System/String/Overview/grapheme1.fs" id="Snippet2"::: + :::code language="vb" source="~/snippets/visualbasic/System/String/Overview/grapheme1.vb" id="Snippet2"::: + +- A Unicode supplementary code point (a surrogate pair) is represented by a object whose code point is a high surrogate followed by a object whose code point is a low surrogate. The code units of high surrogates range from U+D800 to U+DBFF. The code units of low surrogates range from U+DC00 to U+DFFF. Surrogate pairs are used to represent characters in the 16 Unicode supplementary planes. The following example creates a surrogate character and passes it to the method to determine whether it is a surrogate pair. + + :::code language="csharp" source="~/snippets/csharp/System/String/Overview/surrogate1.cs" id="Snippet3"::: + :::code language="fsharp" source="~/snippets/fsharp/System/String/Overview/surrogate1.fs" id="Snippet3"::: + :::code language="vb" source="~/snippets/visualbasic/System/String/Overview/surrogate1.vb" id="Snippet3"::: + +## The Unicode standard + +Characters in a string are represented by UTF-16 encoded code units, which correspond to values. + +Each character in a string has an associated Unicode character category, which is represented in .NET by the enumeration. The category of a character or a surrogate pair can be determined by calling the method. + +[!INCLUDE[character-categories](~/includes/unicode-categories.md)] + +In addition, .NET supports string comparison and sorting based on the Unicode standard. String comparison and sorting information is provided by [International Components for Unicode](https://icu.unicode.org/) libraries (except on Windows versions prior to Windows 10 May 2019 Update). + +## Embedded null characters + +In .NET, a object can include embedded null characters, which count as a part of the string's length. However, in some languages such as C and C++, a null character indicates the end of a string; it is not considered a part of the string and is not counted as part of the string's length. This means that the following common assumptions that C and C++ programmers or libraries written in C or C++ might make about strings are not necessarily valid when applied to objects: + +- The value returned by the `strlen` or `wcslen` functions does not necessarily equal . + +- The string created by the `strcpy_s` or `wcscpy_s` functions is not necessarily identical to the string being copied. + +You should ensure that native C and C++ code that instantiates objects, and code that is passed objects through platform invoke, don't assume that an embedded null character marks the end of the string. + +Embedded null characters in a string are also treated differently when a string is sorted (or compared) and when a string is searched. Null characters are ignored when performing culture-sensitive comparisons between two strings, including comparisons using the invariant culture. They are considered only for ordinal or case-insensitive ordinal comparisons. On the other hand, embedded null characters are always considered when searching a string with methods such as , , and . + +## Strings and indexes + +An index is the position of a object (not a Unicode character) in a . An index is a zero-based, nonnegative number that starts from the first position in the string, which is index position zero. A number of search methods, such as and , return the index of a character or substring in the string instance. + +The property lets you access individual objects by their index position in the string. Because the property is the default property (in Visual Basic) or the indexer (in C# and F#), you can access the individual objects in a string by using code such as the following. This code looks for white space or punctuation characters in a string to determine how many words the string contains. + +:::code language="csharp" source="~/snippets/csharp/System/String/Overview/index11.cs" id="Snippet4"::: +:::code language="fsharp" source="~/snippets/fsharp/System/String/Overview/index11.fs" id="Snippet4"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Overview/index1.vb" id="Snippet4"::: + +Because the class implements the interface, you can also iterate through the objects in a string by using a `foreach` construct, as the following example shows. + +:::code language="csharp" source="~/snippets/csharp/System/String/Overview/index2.cs" id="Snippet5"::: +:::code language="fsharp" source="~/snippets/fsharp/System/String/Overview/index2.fs" id="Snippet5"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Overview/index2.vb" id="Snippet5"::: + +Consecutive index values might not correspond to consecutive Unicode characters, because a Unicode character might be encoded as more than one object. In particular, a string may contain multi-character units of text that are formed by a base character followed by one or more combining characters or by surrogate pairs. To work with Unicode characters instead of objects, use the and classes, or the method and the struct. The following example illustrates the difference between code that works with objects and code that works with Unicode characters. It compares the number of characters or text elements in each word of a sentence. The string includes two sequences of a base character followed by a combining character. + +:::code language="csharp" source="~/snippets/csharp/System/String/Overview/index3.cs" id="Snippet6"::: +:::code language="fsharp" source="~/snippets/fsharp/System/String/Overview/index3.fs" id="Snippet6"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Overview/index3.vb" id="Snippet6"::: + +This example works with text elements by using the method and the class to enumerate all the text elements in a string. You can also retrieve an array that contains the starting index of each text element by calling the method. + +For more information about working with units of text rather than individual values, see [Introduction to character encoding in .NET](/dotnet/standard/base-types/character-encoding-introduction). + +## Null strings and empty strings + +A string that has been declared but has not been assigned a value is `null`. Attempting to call methods on that string throws a . A null string is different from an empty string, which is a string whose value is "" or . In some cases, passing either a null string or an empty string as an argument in a method call throws an exception. For example, passing a null string to the method throws an , and passing an empty string throws a . In other cases, a method argument can be either a null string or an empty string. For example, if you are providing an implementation for a class, you want to equate both a null string and an empty string with the general ("G") format specifier. + +The class includes the following two convenience methods that enable you to test whether a string is `null` or empty: + +- , which indicates whether a string is either `null` or is equal to . This method eliminates the need to use code such as the following: + + :::code language="csharp" source="~/snippets/csharp/System/String/Overview/nullorempty1.cs" id="Snippet1"::: + :::code language="fsharp" source="~/snippets/fsharp/System/String/Overview/nullorempty1.fs" id="Snippet1"::: + :::code language="vb" source="~/snippets/visualbasic/System/String/Overview/nullorempty1.vb" id="Snippet1"::: + +- , which indicates whether a string is `null`, equals , or consists exclusively of white-space characters. This method eliminates the need to use code such as the following: + + :::code language="csharp" source="~/snippets/csharp/System/String/Overview/nullorempty1.cs" id="Snippet2"::: + :::code language="fsharp" source="~/snippets/fsharp/System/String/Overview/nullorempty1.fs" id="Snippet2"::: + :::code language="vb" source="~/snippets/visualbasic/System/String/Overview/nullorempty1.vb" id="Snippet2"::: + +The following example uses the method in the implementation of a custom `Temperature` class. The method supports the "G", "C", "F", and "K" format strings. If an empty format string or a format string whose value is `null` is passed to the method, its value is changed to the "G" format string. + +:::code language="csharp" source="~/snippets/csharp/System/String/Overview/nullorempty1.cs" id="Snippet3"::: +:::code language="fsharp" source="~/snippets/fsharp/System/String/Overview/nullorempty1.fs" id="Snippet3"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Overview/nullorempty1.vb" id="Snippet3"::: + +## Immutability and the StringBuilder class + +A object is called immutable (read-only), because its value cannot be modified after it has been created. Methods that appear to modify a object actually return a new object that contains the modification. + +Because strings are immutable, string manipulation routines that perform repeated additions or deletions to what appears to be a single string can exact a significant performance penalty. For example, the following code uses a random number generator to create a string with 1000 characters in the range 0x0001 to 0x052F. Although the code appears to use string concatenation to append a new character to the existing string named `str`, it actually creates a new object for each concatenation operation. + +:::code language="csharp" source="~/snippets/csharp/System/String/Overview/immutable.cs" id="Snippet15"::: +:::code language="fsharp" source="~/snippets/fsharp/System/String/Overview/immutable.fs" id="Snippet15"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Overview/immutable.vb" id="Snippet15"::: + +You can use the class instead of the class for operations that make multiple changes to the value of a string. Unlike instances of the class, objects are mutable; when you concatenate, append, or delete substrings from a string, the operations are performed on a single string. When you have finished modifying the value of a object, you can call its method to convert it to a string. The following example replaces the used in the previous example to concatenate 1000 random characters in the range to 0x0001 to 0x052F with a object. + +:::code language="csharp" source="~/snippets/csharp/System/String/Overview/immutable1.cs" id="Snippet16"::: +:::code language="fsharp" source="~/snippets/fsharp/System/String/Overview/immutable1.fs" id="Snippet16"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Overview/immutable1.vb" id="Snippet16"::: + +## Ordinal vs. culture-sensitive operations + +Members of the class perform either ordinal or culture-sensitive (linguistic) operations on a object. An ordinal operation acts on the numeric value of each object. A culture-sensitive operation acts on the value of the object, and takes culture-specific casing, sorting, formatting, and parsing rules into account. Culture-sensitive operations execute in the context of an explicitly declared culture or the implicit current culture. The two kinds of operations can produce very different results when they are performed on the same string. + +.NET also supports culture-insensitive linguistic string operations by using the invariant culture (), which is loosely based on the culture settings of the English language independent of region. Unlike other settings, the settings of the invariant culture are guaranteed to remain consistent on a single computer, from system to system, and across versions of .NET. The invariant culture can be seen as a kind of black box that ensures stability of string comparisons and ordering across all cultures. + +> [!IMPORTANT] +> If your application makes a security decision about a symbolic identifier such as a file name or named pipe, or about persisted data such as the text-based data in an XML file, the operation should use an ordinal comparison instead of a culture-sensitive comparison. This is because a culture-sensitive comparison can yield different results depending on the culture in effect, whereas an ordinal comparison depends solely on the binary value of the compared characters. + +> [!IMPORTANT] +> Most methods that perform string operations include an overload that has a parameter of type , which enables you to specify whether the method performs an ordinal or culture-sensitive operation. In general, you should call this overload to make the intent of your method call clear. For best practices and guidance for using ordinal and culture-sensitive operations on strings, see [Best Practices for Using Strings](/dotnet/standard/base-types/best-practices-strings). + +Operations for casing, parsing and formatting, comparison and sorting, and testing for equality can be either ordinal or culture-sensitive. The following sections discuss each category of operation. + +> [!TIP] +> You should always call a method overload that makes the intent of your method call clear. For example, instead of calling the method to perform a culture-sensitive comparison of two strings by using the conventions of the current culture, you should call the method with a value of for the `comparisonType` argument. For more information, see [Best Practices for Using Strings](/dotnet/standard/base-types/best-practices-strings). + +You can download the sorting weight tables, a set of text files that contain information on the character weights used in sorting and comparison operations, from [Default Unicode Collation Element Table](https://www.unicode.org/Public/UCA/latest/allkeys.txt). + +### Casing + +Casing rules determine how to change the capitalization of a Unicode character; for example, from lowercase to uppercase. Often, a casing operation is performed before a string comparison. For example, a string might be converted to uppercase so that it can be compared with another uppercase string. You can convert the characters in a string to lowercase by calling the or method, and you can convert them to uppercase by calling the or method. In addition, you can use the method to convert a string to title case. + +[!INCLUDE[platform-note](~/includes/c-and-posix-cultures.md)] + +Casing operations can be based on the rules of the current culture, a specified culture, or the invariant culture. Because case mappings can vary depending on the culture used, the result of casing operations can vary based on culture. The actual differences in casing are of three kinds: + +- Differences in the case mapping of LATIN CAPITAL LETTER I (U+0049), LATIN SMALL LETTER I (U+0069), LATIN CAPITAL LETTER I WITH DOT ABOVE (U+0130), and LATIN SMALL LETTER DOTLESS I (U+0131). In the tr-TR (Turkish (Turkey)) and az-Latn-AZ (Azerbaijan, Latin) cultures, and in the tr, az, and az-Latn neutral cultures, the lowercase equivalent of LATIN CAPITAL LETTER I is LATIN SMALL LETTER DOTLESS I, and the uppercase equivalent of LATIN SMALL LETTER I is LATIN CAPITAL LETTER I WITH DOT ABOVE. In all other cultures, including the invariant culture, LATIN SMALL LETTER I and LATIN CAPITAL LETTER I are lowercase and uppercase equivalents. + + The following example demonstrates how a string comparison designed to prevent file system access can fail if it relies on a culture-sensitive casing comparison. (The casing conventions of the invariant culture should have been used.) + + :::code language="csharp" source="~/snippets/csharp/System/String/Overview/case2.cs" id="Snippet17"::: + :::code language="fsharp" source="~/snippets/fsharp/System/String/Overview/case2.fs" id="Snippet17"::: + :::code language="vb" source="~/snippets/visualbasic/System/String/Overview/case2.vb" id="Snippet17"::: + +- Differences in case mappings between the invariant culture and all other cultures. In these cases, using the casing rules of the invariant culture to change a character to uppercase or lowercase returns the same character. For all other cultures, it returns a different character. Some of the affected characters are listed in the following table. + + |Character|If changed to|Returns| + |---------------|-------------------|-------------| + |MICRON SIGN (U+00B5)|Uppercase|GREEK CAPITAL LETTER MU (U+-39C)| + |LATIN CAPITAL LETTER I WITH DOT ABOVE (U+0130)|Lowercase|LATIN SMALL LETTER I (U+0069)| + |LATIN SMALL LETTER DOTLESS I (U+0131)|Uppercase|LATIN CAPITAL LETTER I (U+0049)| + |LATIN SMALL LETTER LONG S (U+017F)|Uppercase|LATIN CAPITAL LETTER S (U+0053)| + |LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON (U+01C5)|Lowercase|LATIN SMALL LETTER DZ WITH CARON (U+01C6)| + |COMBINING GREEK YPOGEGRAMMENI (U+0345)|Uppercase|GREEK CAPITAL LETTER IOTA (U+0399)| + +- Differences in case mappings of two-letter mixed-case pairs in the ASCII character range. In most cultures, a two-letter mixed-case pair is equal to the equivalent two-letter uppercase or lowercase pair. This is not true for the following two-letter pairs in the following cultures, because in each case they are compared to a digraph: + + - "lJ" and "nJ" in the hr-HR (Croatian (Croatia)) culture. + - "cH" in the cs-CZ (Czech (Czech Republic)) and sk-SK (Slovak (Slovakia)) cultures. + - "aA" in the da-DK (Danish (Denmark)) culture. + - "cS", "dZ", "dZS", "nY", "sZ", "tY", and "zS" in the hu-HU (Hungarian (Hungary)) culture. + - "cH" and "lL" in the es-ES_tradnl (Spanish (Spain, Traditional Sort)) culture. + - "cH", "gI", "kH", "nG" "nH", "pH", "qU', "tH", and "tR" in the vi-VN (Vietnamese (Vietnam)) culture. + + However, it is unusual to encounter a situation in which a culture-sensitive comparison of these pairs creates problems, because these pairs are uncommon in fixed strings or identifiers. + +The following example illustrates some of the differences in casing rules between cultures when converting strings to uppercase. + +:::code language="csharp" source="~/snippets/csharp/System/String/Overview/case1.cs" id="Snippet7"::: +:::code language="fsharp" source="~/snippets/fsharp/System/String/Overview/case1.fs" id="Snippet7"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Overview/case1.vb" id="Snippet7"::: + +### Parsing and formatting + +Formatting and parsing are inverse operations. Formatting rules determine how to convert a value, such as a date and time or a number, to its string representation, whereas parsing rules determine how to convert a string representation to a value such as a date and time. Both formatting and parsing rules are dependent on cultural conventions. The following example illustrates the ambiguity that can arise when interpreting a culture-specific date string. Without knowing the conventions of the culture that was used to produce a date string, it is not possible to know whether 03/01/2011, 3/1/2011, and 01/03/2011 represent January 3, 2011 or March 1, 2011. + +:::code language="csharp" source="~/snippets/csharp/System/String/Overview/format1.cs" id="Snippet8"::: +:::code language="fsharp" source="~/snippets/fsharp/System/String/Overview/format1.fs" id="Snippet8"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Overview/format1.vb" id="Snippet8"::: + +Similarly, as the following example shows, a single string can produce different dates depending on the culture whose conventions are used in the parsing operation. + +:::code language="csharp" source="~/snippets/csharp/System/String/Overview/parse1.cs" id="Snippet9"::: +:::code language="fsharp" source="~/snippets/fsharp/System/String/Overview/parse1.fs" id="Snippet9"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Overview/parse1.vb" id="Snippet9"::: + +### String comparison and sorting + +Conventions for comparing and sorting strings vary from culture to culture. For example, the sort order may be based on phonetics or on the visual representation of characters. In East Asian languages, characters are sorted by the stroke and radical of ideographs. Sorting also depends on the order languages and cultures use for the alphabet. For example, the Danish language has an "Æ" character that it sorts after "Z" in the alphabet. In addition, comparisons can be case-sensitive or case-insensitive, and casing rules might differ by culture. Ordinal comparison, on the other hand, uses the Unicode code points of individual characters in a string when comparing and sorting strings. + +Sort rules determine the alphabetic order of Unicode characters and how two strings compare to each other. For example, the method compares two strings based on the parameter. If the parameter value is , the method performs a linguistic comparison that uses the conventions of the current culture; if the parameter value is , the method performs an ordinal comparison. Consequently, as the following example shows, if the current culture is U.S. English, the first call to the method (using culture-sensitive comparison) considers "a" less than "A", but the second call to the same method (using ordinal comparison) considers "a" greater than "A". + +:::code language="csharp" source="~/snippets/csharp/System/String/Overview/compare11.cs" id="Snippet10"::: +:::code language="fsharp" source="~/snippets/fsharp/System/String/Overview/compare11.fs" id="Snippet10"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Overview/compare1.vb" id="Snippet10"::: + +.NET supports word, string, and ordinal sort rules: + +- A word sort performs a culture-sensitive comparison of strings in which certain nonalphanumeric Unicode characters might have special weights assigned to them. For example, the hyphen (-) might have a very small weight assigned to it so that "coop" and "co-op" appear next to each other in a sorted list. For a list of the methods that compare two strings using word sort rules, see the [String operations by category](#string-operations-by-category) section. + +- A string sort also performs a culture-sensitive comparison. It is similar to a word sort, except that there are no special cases, and all nonalphanumeric symbols come before all alphanumeric Unicode characters. Two strings can be compared using string sort rules by calling the method overloads that have an `options` parameter that is supplied a value of . Note that this is the only method that .NET provides to compare two strings using string sort rules. + +- An ordinal sort compares strings based on the numeric value of each object in the string. An ordinal comparison is automatically case-sensitive because the lowercase and uppercase versions of a character have different code points. However, if case is not important, you can specify an ordinal comparison that ignores case. This is equivalent to converting the string to uppercase by using the invariant culture and then performing an ordinal comparison on the result. For a list of the methods that compare two strings using ordinal sort rules, see the [String operations by category](#string-operations-by-category) section. + +A culture-sensitive comparison is any comparison that explicitly or implicitly uses a object, including the invariant culture that is specified by the property. The implicit culture is the current culture, which is specified by the and properties. There is considerable variation in the sort order of alphabetic characters (that is, characters for which the method returns `true`) across cultures. You can specify a culture-sensitive comparison that uses the conventions of a specific culture by supplying a object to a string comparison method such as . You can specify a culture-sensitive comparison that uses the conventions of the current culture by supplying , , or any member of the enumeration other than or to an appropriate overload of the method. A culture-sensitive comparison is generally appropriate for sorting whereas an ordinal comparison is not. An ordinal comparison is generally appropriate for determining whether two strings are equal (that is, for determining identity) whereas a culture-sensitive comparison is not. + +The following example illustrates the difference between culture-sensitive and ordinal comparison. The example evaluates three strings, "Apple", "Æble", and "AEble", using ordinal comparison and the conventions of the da-DK and en-US cultures (each of which is the default culture at the time the method is called). Because the Danish language treats the character "Æ" as an individual letter and sorts it after "Z" in the alphabet, the string "Æble" is greater than "Apple". However, "Æble" is not considered equivalent to "AEble", so "Æble" is also greater than "AEble". The en-US culture doesn't include the letter"Æ" but treats it as equivalent to "AE", which explains why "Æble" is less than "Apple" but equal to "AEble". Ordinal comparison, on the other hand, considers "Apple" to be less than "Æble", and "Æble" to be greater than "AEble". + +:::code language="csharp" source="~/snippets/csharp/System/String/Overview/compare4.cs" id="Snippet21"::: +:::code language="fsharp" source="~/snippets/fsharp/System/String/Overview/compare4.fs" id="Snippet21"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Overview/compare4.vb" id="Snippet21"::: + +Use the following general guidelines to choose an appropriate sorting or string comparison method: + +- If you want the strings to be ordered based on the user's culture, you should order them based on the conventions of the current culture. If the user's culture changes, the order of sorted strings will also change accordingly. For example, a thesaurus application should always sort words based on the user's culture. + +- If you want the strings to be ordered based on the conventions of a specific culture, you should order them by supplying a object that represents that culture to a comparison method. For example, in an application designed to teach students a particular language, you want strings to be ordered based on the conventions of one of the cultures that speaks that language. + +- If you want the order of strings to remain unchanged across cultures, you should order them based on the conventions of the invariant culture or use an ordinal comparison. For example, you would use an ordinal sort to organize the names of files, processes, mutexes, or named pipes. + +- For a comparison that involves a security decision (such as whether a username is valid), you should always perform an ordinal test for equality by calling an overload of the method. + +> [!NOTE] +> The culture-sensitive sorting and casing rules used in string comparison depend on the version of the Unicode Standard supported by the underlying operating system. + +For more information about word, string, and ordinal sort rules, see the topic. For additional recommendations on when to use each rule, see [Best Practices for Using Strings](/dotnet/standard/base-types/best-practices-strings). + +Ordinarily, you don't call string comparison methods such as directly to determine the sort order of strings. Instead, comparison methods are called by sorting methods such as or . The following example performs four different sorting operations (word sort using the current culture, word sort using the invariant culture, ordinal sort, and string sort using the invariant culture) without explicitly calling a string comparison method, although they do specify the type of comparison to use. Note that each type of sort produces a unique ordering of strings in its array. + +:::code language="csharp" source="~/snippets/csharp/System/String/Overview/compare2.cs" id="Snippet12"::: +:::code language="fsharp" source="~/snippets/fsharp/System/String/Overview/compare2.fs" id="Snippet12"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Overview/compare2.vb" id="Snippet12"::: + +> [!TIP] +> Internally, .NET uses sort keys to support culturally sensitive string comparison. Each character in a string is given several categories of sort weights, including alphabetic, case, and diacritic. A sort key, represented by the class, provides a repository of these weights for a particular string. If your app performs a large number of searching or sorting operations on the same set of strings, you can improve its performance by generating and storing sort keys for all the strings that it uses. When a sort or comparison operation is required, you use the sort keys instead of the strings. For more information, see the class. + +If you don't specify a string comparison convention, sorting methods such as perform a culture-sensitive, case-sensitive sort on strings. The following example illustrates how changing the current culture affects the order of sorted strings in an array. It creates an array of three strings. First, it sets the `System.Threading.Thread.CurrentThread.CurrentCulture` property to en-US and calls the method. The resulting sort order is based on sorting conventions for the English (United States) culture. Next, the example sets the `System.Threading.Thread.CurrentThread.CurrentCulture` property to da-DK and calls the method again. Notice how the resulting sort order differs from the en-US results because it uses the sorting conventions for Danish (Denmark). + +:::code language="csharp" source="~/snippets/csharp/System/String/Overview/sort1.cs" id="Snippet3"::: +:::code language="fsharp" source="~/snippets/fsharp/System/String/Overview/sort1.fs" id="Snippet3"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Overview/sort1.vb" id="Snippet3"::: + +> [!WARNING] +> If your primary purpose in comparing strings is to determine whether they are equal, you should call the method. Typically, you should use to perform an ordinal comparison. The method is intended primarily to sort strings. + +String search methods, such as and , also can perform culture-sensitive or ordinal string comparisons. The following example illustrates the differences between ordinal and culture-sensitive comparisons using the method. A culture-sensitive search in which the current culture is English (United States) considers the substring "oe" to match the ligature "œ". Because a soft hyphen (U+00AD) is a zero-width character, the search treats the soft hyphen as equivalent to and finds a match at the beginning of the string. An ordinal search, on the other hand, does not find a match in either case. + +:::code language="csharp" source="~/snippets/csharp/System/String/Overview/compare3.cs" id="Snippet13"::: +:::code language="fsharp" source="~/snippets/fsharp/System/String/Overview/compare3.fs" id="Snippet13"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Overview/compare3.vb" id="Snippet13"::: + +### Search in strings + +String search methods, such as and , also can perform culture-sensitive or ordinal string comparisons to determine whether a character or substring is found in a specified string. + +The search methods in the class that search for an individual character, such as the method, or one of a set of characters, such as the method, all perform an ordinal search. To perform a culture-sensitive search for a character, you must call a method such as or . Note that the results of searching for a character using ordinal and culture-sensitive comparison can be very different. For example, a search for a precomposed Unicode character such as the ligature "Æ" (U+00C6) might match any occurrence of its components in the correct sequence, such as "AE" (U+041U+0045), depending on the culture. The following example illustrates the difference between the and methods when searching for an individual character. The ligature "æ" (U+00E6) is found in the string "aerial" when using the conventions of the en-US culture, but not when using the conventions of the da-DK culture or when performing an ordinal comparison. + +:::code language="csharp" source="~/snippets/csharp/System/String/Overview/search1.cs" id="Snippet22"::: +:::code language="fsharp" source="~/snippets/fsharp/System/String/Overview/search1.fs" id="Snippet22"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Overview/search1.vb" id="Snippet22"::: + +On the other hand, class methods that search for a string rather than a character perform a culture-sensitive search if search options are not explicitly specified by a parameter of type . The sole exception is , which performs an ordinal search. + +### Test for equality + +Use the method to determine the relationship of two strings in the sort order. Typically, this is a culture-sensitive operation. In contrast, call the method to test for equality. Because the test for equality usually compares user input with some known string, such as a valid user name, a password, or a file system path, it is typically an ordinal operation. + +> [!WARNING] +> It is possible to test for equality by calling the method and determining whether the return value is zero. However, this practice is not recommended. To determine whether two strings are equal, you should call one of the overloads of the method. The preferred overload to call is either the instance method or the static method, because both methods include a parameter that explicitly specifies the type of comparison. + +The following example illustrates the danger of performing a culture-sensitive comparison for equality when an ordinal one should be used instead. In this case, the intent of the code is to prohibit file system access from URLs that begin with "FILE://" or "file://" by performing a case-insensitive comparison of the beginning of a URL with the string "FILE://". However, if a culture-sensitive comparison is performed using the Turkish (Turkey) culture on a URL that begins with "file://", the comparison for equality fails, because the Turkish uppercase equivalent of the lowercase "i" is "İ" instead of "I". As a result, file system access is inadvertently permitted. On the other hand, if an ordinal comparison is performed, the comparison for equality succeeds, and file system access is denied. + +:::code language="csharp" source="~/snippets/csharp/System/String/Overview/equality1.cs" id="Snippet11"::: +:::code language="fsharp" source="~/snippets/fsharp/System/String/Overview/equality1.fs" id="Snippet11"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Overview/equality1.vb" id="Snippet11"::: + +## Normalization + +Some Unicode characters have multiple representations. For example, any of the following code points can represent the letter "ắ": + +- U+1EAF +- U+0103 U+0301 +- U+0061 U+0306 U+0301 + +Multiple representations for a single character complicate searching, sorting, matching, and other string operations. + +The Unicode standard defines a process called normalization that returns one binary representation of a Unicode character for any of its equivalent binary representations. Normalization can use several algorithms, called normalization forms, that follow different rules. .NET supports Unicode normalization forms C, D, KC, and KD. When strings have been normalized to the same normalization form, they can be compared by using ordinal comparison. + +An ordinal comparison is a binary comparison of the Unicode scalar value of corresponding objects in each string. The class includes a number of methods that can perform an ordinal comparison, including the following: + +- Any overload of the , , , , , and methods that includes a parameter. The method performs an ordinal comparison if you supply a value of or for this parameter. + +- The overloads of the method. + +- Methods that use ordinal comparison by default, such as , , and . + +- Methods that search for a value or for the elements in a array in a string instance. Such methods include and . + +You can determine whether a string is normalized to normalization form C by calling the method, or you can call the method to determine whether a string is normalized to a specified normalization form. You can also call the method to convert a string to normalization form C, or you can call the method to convert a string to a specified normalization form. For step-by-step information about normalizing and comparing strings, see the and methods. + +The following simple example illustrates string normalization. It defines the letter "ố" in three different ways in three different strings, and uses an ordinal comparison for equality to determine that each string differs from the other two strings. It then converts each string to the supported normalization forms, and again performs an ordinal comparison of each string in a specified normalization form. In each case, the second test for equality shows that the strings are equal. + +:::code language="csharp" source="~/snippets/csharp/System/String/Overview/normalize1.cs" id="Snippet14"::: +:::code language="fsharp" source="~/snippets/fsharp/System/String/Overview/normalize1.fs" id="Snippet14"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Overview/normalize1.vb" id="Snippet14"::: + +For more information about normalization and normalization forms, see , as well as [Unicode Standard Annex #15: Unicode Normalization Forms](https://unicode.org/reports/tr15/) and the [Normalization FAQ](https://www.unicode.org/faq/normalization.html) on the unicode.org website. + +## String operations by category + +The class provides members for comparing strings, testing strings for equality, finding characters or substrings in a string, modifying a string, extracting substrings from a string, combining strings, formatting values, copying a string, and normalizing a string. + +### Compare strings + +You can compare strings to determine their relative position in the sort order by using the following methods: + +- returns an integer that indicates the relationship of one string to a second string in the sort order. + +- returns an integer that indicates the relationship of one string to a second string based on a comparison of their code points. + +- returns an integer that indicates the relationship of the current string instance to a second string in the sort order. The method provides the and implementations for the class. + +### Test strings for equality + +You call the method to determine whether two strings are equal. The instance and the static overloads let you specify whether the comparison is culture-sensitive or ordinal, and whether case is considered or ignored. Most tests for equality are ordinal, and comparisons for equality that determine access to a system resource (such as a file system object) should always be ordinal. + +### Find characters in a string + +The class includes two kinds of search methods: + +- Methods that return a value to indicate whether a particular substring is present in a string instance. These include the , , and methods. + +- Methods that indicate the starting position of a substring in a string instance. These include the , , , and methods. + +> [!WARNING] +> If you want to search a string for a particular pattern rather than a specific substring, you should use regular expressions. For more information, see [.NET Regular Expressions](/dotnet/standard/base-types/regular-expressions). + +### Modify a string + +The class includes the following methods that appear to modify the value of a string: + +- inserts a string into the current instance. + +- inserts one or more occurrences of a specified character at the beginning of a string. + +- inserts one or more occurrences of a specified character at the end of a string. + +- deletes a substring from the current instance. + +- replaces a substring with another substring in the current instance. + +- and convert all the characters in a string to lowercase. + +- and convert all the characters in a string to uppercase. + +- removes all occurrences of a character from the beginning and end of a string. + +- removes all occurrences of a character from the end of a string. + +- removes all occurrences of a character from the beginning of a string. + +> [!IMPORTANT] +> All string modification methods return a new object. They don't modify the value of the current instance. + +### Extract substrings from a string + +The method separates a single string into multiple strings. Overloads of the method allow you to specify multiple delimiters, to limit the number of substrings that the method extracts, to trim white space from substrings, and to specify whether empty strings (which occur when delimiters are adjacent) are included among the returned strings. + +### Combine strings + +The following methods can be used for string concatenation: + +- combines one or more substrings into a single string. +- concatenates one or more substrings into a single element and adds a separator between each substring. + +### Format values + +The method uses the composite formatting feature to replace one or more placeholders in a string with the string representation of some object or value. The method is often used to do the following: + +- To embed the string representation of a numeric value in a string. +- To embed the string representation of a date and time value in a string. +- To embed the string representation of an enumeration value in a string. +- To embed the string representation of some object that supports the interface in a string. +- To right-justify or left-justify a substring in a field within a larger string. + +For detailed information about formatting operations and examples, see the overload summary. + +### Copy a string + +You can call the following methods to make a copy of a string: + +- returns a reference to an existing object. +- copies a portion of a string to a character array. + +### Normalize a string + +In Unicode, a single character can have multiple code points. Normalization converts these equivalent characters into the same binary representation. The method performs the normalization, and the method determines whether a string is normalized. + +For more information and an example, see the [Normalization](#normalization) section earlier in this article. + + ]]> + Default Unicode Collation Element Tables This type is thread safe. @@ -120,7 +562,180 @@ Initializes a new instance of the class. - For more information about this API, see Supplemental API remarks for String constructor. + + ). The constructor processes characters from `value` starting from the location specified by the pointer until a null character (0x00) is reached ([Example 6: Instantiate a string from a pointer to a signed byte array](#example-6-instantiate-a-string-from-a-pointer-to-a-signed-byte-array)). + +`String(SByte* value, Int32 startIndex, Int32 length)`\ +**(Not CLS-compliant)** Initializes the new instance to the value indicated by a pointer to an array of 8-bit signed integers, a starting position within that array, and a length. The array is assumed to represent a string encoded using the current system code page (that is, the encoding specified by ). The constructor processes characters from value starting at `startIndex` and ending at `startIndex` + `length` - 1 ([Example 6: Instantiate a string from a pointer to a signed byte array](#example-6-instantiate-a-string-from-a-pointer-to-a-signed-byte-array)). + +`String(SByte* value, Int32 startIndex, Int32 length, Encoding enc)`\ +**(Not CLS-compliant)** Initializes the new instance to the value indicated by a pointer to an array of 8-bit signed integers, a starting position within that array, a length, and an object. + +## Parameters + +Here is a complete list of parameters used by constructors that don't include a pointer parameter. For the parameters used by each overload, see the overload syntax above. + +| Parameter | Type | Description | +|-----------|----------------------|---------------------------------| +| `value` | [] | An array of Unicode characters. | +| `c` | | A Unicode character. | +| `startIndex` | |The starting position in `value` of the first character in the new string.

Default value: 0| +| `length` | |The number of characters in `value` to include in the new string.

Default value: | +| `count` | |The number of times the character `c` is repeated in the new string. If `count` is zero, the value of the new object is .| + +Here is a complete list of parameters used by constructors that include a pointer parameter. For the parameters used by each overload, see the overload syntax above. + +| Parameter | Type | Description | +|-----------|------|-------------| +|`value`|*

-or-

\*|A pointer to a null-terminated array of Unicode characters or an array of 8-bit signed integers. If `value` is `null` or an empty array, the value of the new string is .| +|`startIndex`||The index of the array element that defines the first character in the new string.

Default value: 0| +|`length`||The number of array elements to use to create the new string. If length is zero, the constructor creates a string whose value is .

Default value: | +|`enc`||An object that specifies how the `value` array is encoded.

Default value: , or the system's current ANSI code page| + +## Exceptions + +Here's a list of exceptions thrown by constructors that don't include pointer parameters. + +| Exception | Condition | Thrown by | +|-----------|-----------|-----------| +||`value` is `null`.|| +||`startIndex`, `length`, or `count` is less than zero.

-or-

The sum of `startIndex` and `length` is greater than the number of elements in `value`.

-or-

`count` is less than zero.|

| + +Here's a list of exceptions thrown by constructors that include pointer parameters. + +| Exception | Condition | Thrown by | +|-----------|-----------|-----------| +||`value` specifies an array that contains an invalid Unicode character.

-or-

`value` or `value` + `startIndex` specifies an address that is less than 64K.

-or-

A new instance could not be initialized from the `value` byte array because `value` does not use the default code page encoding.|All constructors with pointers.| +||`value` is null.|



| +||The current process does not have read access to all the addressed characters.

-or-

`startIndex` or `length` is less than zero, `value` + `startIndex` cause a pointer overflow, or the current process does not have read access to all the addressed characters.

-or-

The length of the new string is too large to allocate.|All constructors with pointers.| +||`value`, or `value` + `startIndex` + `length` - 1, specifies an invalid address.|



| + +## Which method do I call? + +| To | Call or use | +|----|-------------| +|Create a string.|Assignment from a string literal or an existing string ([Example 1: Use string assignment](#example-1-use-string-assignment))| +|Create a string from an entire character array.| ([Example 2: Use a character array](#example-2-use-a-character-array))| +|Create a string from a portion of a character array.| ([Example 3: Use a portion of a character array and repeating a single character](#example-3-use-a-portion-of-a-character-array-and-repeating-a-single-character))| +|Create a string that repeats the same character multiple times.| ([Example 3: Use a portion of a character array and repeating a single character](#example-3-use-a-portion-of-a-character-array-and-repeating-a-single-character))| +|Create a string from a pointer to a Unicode or wide character array.|| +|Create a string from a portion of a Unicode or wide character array by using its pointer.|| +|Create a string from a C++ `char` array.|,

-or-

| +|Create a string from ASCII characters.|| + +## Create strings + +The most commonly used technique for creating strings programmatically is simple assignment, as illustrated in [Example 1](#example-1-use-string-assignment). The class also includes four types of constructor overloads that let you create strings from the following values: + +- From a character array (an array of UTF-16-encoded characters). You can create a new object from the characters in the entire array or a portion of it. The constructor copies all the characters in the array to the new string. The constructor copies the characters from index `startIndex` to index `startIndex` + `length` - 1 to the new string. If `length` is zero, the value of the new string is . + + If your code repeatedly instantiates strings that have the same value, you can improve application performance by using an alternate means of creating strings. For more information, see [Handle repetitive strings](#handle-repetitive-strings). + +- From a single character that is duplicated zero, one, or more times, by using the constructor. If `count` is zero, the value of the new string is . + +- From a pointer to a null-terminated character array, by using the or constructor. Either the entire array or a specified range can be used to initialize the string. The constructor copies a sequence of Unicode characters starting from the specified pointer or from the specified pointer plus `startIndex` and continuing to the end of the array or for `length` characters. If `value` is a null pointer or `length` is zero, the constructor creates a string whose value is . If the copy operation proceeds to the end of the array and the array is not null-terminated, the constructor behavior is system-dependent. Such a condition might cause an access violation. + + If the array contains any embedded null characters (U+0000 or '\0') and the overload is called, the string instance contains `length` characters including any embedded nulls. The following example shows what happens when a pointer to an array of 10 elements that includes two null characters is passed to the method. Because the address is the beginning of the array and all elements in the array are to be added to the string, the constructor instantiates a string with ten characters, including two embedded nulls. On the other hand, if the same array is passed to the constructor, the result is a four-character string that does not include the first null character. + + :::code language="csharp" source="~/snippets/csharp/System/String/.ctor/chptrctor_null.cs" id="Snippet5"::: + :::code language="fsharp" source="~/snippets/fsharp/System/String/.ctor/chptrctor_null.fs" id="Snippet5"::: + + The array must contain Unicode characters. In C++, this means that the character array must be defined either as the managed [] type or the unmanaged`wchar_t`[] type. + + If the overload is called and the array is not null-terminated, or if the overload is called and `startIndex` + `length`-1 includes a range that is outside the memory allocated for the sequence of characters, the behavior of the constructor is system-dependent, and an access violation may occur. + +- From a pointer to a signed byte array. Either the entire array or a specified range can be used to initialize the string. The sequence of bytes can be interpreted by using the default code page encoding, or an encoding can be specified in the constructor call. If the constructor tries to instantiate a string from an entire array that is not null-terminated, or if the range of the array from `value` + `startIndex` to `value` + `startIndex` + `length` -1 is outside of the memory allocated for the array, the behavior of this constructor is system-dependent, and an access violation may occur. + + The three constructors that include a signed byte array as a parameter are designed primarily to convert a C++ `char` array to a string, as shown in this example: + + :::code language="cpp" source="~/snippets/cpp/System/String/.ctor/sbyte_ctor1.cpp" id="Snippet4"::: + + If the array contains any null characters ('\0') or bytes whose value is 0 and the overload is called, the string instance contains `length` characters including any embedded nulls. The following example shows what happens when a pointer to an array of 10 elements that includes two null characters is passed to the method. Because the address is the beginning of the array and all elements in the array are to be added to the string, the constructor instantiates a string with ten characters, including two embedded nulls. On the other hand, if the same array is passed to the constructor, the result is a four-character string that does not include the first null character. + + :::code language="csharp" source="~/snippets/csharp/System/String/.ctor/ptrctor_null.cs" id="Snippet6"::: + :::code language="fsharp" source="~/snippets/fsharp/System/String/.ctor/ptrctor_null.fs" id="Snippet6"::: + + Because the and constructors interpret `value` by using the default ANSI code page, calling these constructors with identical byte arrays may create strings that have different values on different systems. + +## Handle repetitive strings + +Apps that parse or decode streams of text often use the constructor or the method to convert sequences of characters into a string. Repeatedly creating new strings with the same value instead of creating and reusing one string wastes memory. If you are likely to create the same string value repeatedly by calling the constructor, even if you don't know in advance what those identical string values may be, you can use a lookup table instead. + +For example, suppose you read and parse a stream of characters from a file that contains XML tags and attributes. When you parse the stream, you repeatedly encounter certain tokens (that is, sequences of characters that have a symbolic meaning). Tokens equivalent to the strings "0", "1", "true", and "false" are likely to occur frequently in an XML stream. + +Instead of converting each token into a new string, you can create a object to hold commonly occurring strings. The object improves performance, because it retrieves stored strings without allocating temporary memory. When you encounter a token, use the method to retrieve the token from the table. If the token exists, the method returns the corresponding string. If the token does not exist, use the method to insert the token into the table and to get the corresponding string. + +## Example 1: Use string assignment + +The following example creates a new string by assigning it a string literal. It creates a second string by assigning the value of the first string to it. These are the two most common ways to instantiate a new object. + +:::code language="csharp" source="~/snippets/csharp/System/String/.ctor/ctor1.cs" id="Snippet1"::: +:::code language="fsharp" source="~/snippets/fsharp/System/String/.ctor/ctor1.fs" id="Snippet1"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/.ctor/ctor1.vb" id="Snippet1"::: + +## Example 2: Use a character array + +The following example demonstrates how to create a new object from a character array. + +:::code language="csharp" source="~/snippets/csharp/System/String/.ctor/source.cs" id="Snippet1"::: +:::code language="fsharp" source="~/snippets/fsharp/System/String/.ctor/source.fs" id="Snippet1"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/.ctor/source.vb" id="Snippet1"::: + +## Example 3: Use a portion of a character array and repeating a single character + +The following example demonstrates how to create a new object from a portion of a character array, and how to create a new object that contains multiple occurrences of a single character. + +:::code language="csharp" source="~/snippets/csharp/System/String/.ctor/source.cs" id="Snippet3"::: +:::code language="fsharp" source="~/snippets/fsharp/System/String/.ctor/source.fs" id="Snippet3"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/.ctor/source.vb" id="Snippet3"::: + +## Example 4: Use a pointer to a character array + +The following example demonstrates how to create a new object from a pointer to an array of characters. The C# example must be compiled by using the `/unsafe` compiler switch. + +:::code language="csharp" source="~/snippets/csharp/System/String/.ctor/ctor2.cs" id="Snippet2"::: +:::code language="fsharp" source="~/snippets/fsharp/System/String/.ctor/ctor2.fs" id="Snippet2"::: + +## Example 5: Instantiate a string from a pointer and a range of an array + +The following example examines the elements of a character array for either a period or an exclamation point. If one is found, it instantiates a string from the characters in the array that precede the punctuation symbol. If not, it instantiates a string with the entire contents of the array. The C# example must be compiled using the `/unsafe` compiler switch. + +:::code language="csharp" source="~/snippets/csharp/System/String/.ctor/char2_ctor.cs" id="Snippet3"::: +:::code language="fsharp" source="~/snippets/fsharp/System/String/.ctor/char2_ctor.fs" id="Snippet3"::: + +## Example 6: Instantiate a string from a pointer to a signed byte array + +The following example demonstrates how you can create an instance of the class with the constructor. + +:::code language="csharp" source="~/snippets/csharp/System/String/.ctor/source.cs" id="Snippet2"::: +:::code language="fsharp" source="~/snippets/fsharp/System/String/.ctor/source.fs" id="Snippet2"::: + + ]]>
+
@@ -5051,7 +5666,342 @@ The following example compares three sets of strings by using each member of the Converts the value of objects to strings based on the formats specified and inserts them into another string. If you are new to the `String.Format` method, see Get started with the String.Format method for a quick overview. - For more information about this API, see Supplemental API remarks for String.Format. + + method are interspersed throughout this article. You can also download a complete set of `String.Format` examples, which are included a [.NET Core project for C#](/samples/dotnet/samples/string-format/). + +The following are some of the examples included in the article: + +### Create a format string + +[Insert a string](#insert-a-string)\ +[The format item](#the-format-item)\ +[Format items that have the same index](#format-items-that-have-the-same-index) + +### Control formatted output + +[Control formatting](#control-formatting)\ +[Control spacing](#control-spacing)\ +[Control alignment](#control-alignment)\ +[Control the number of integral digits](#how-do-i-control-the-number-of-integral-digits)\ +[Control the number of digits after the decimal separator](#how-do-i-control-the-number-of-digits-after-the-decimal-separator)\ +[Include literal braces in the result string](#how-do-i-include-literal-braces--and--in-the-result-string) + +### Make format strings culture-sensitive + +[Make format strings culture-sensitive](#make-format-strings-culture-sensitive) + +### Customize the formatting operation + +[A custom formatting operation](#example-a-custom-formatting-operation)\ +[An intercept provider and Roman numeral formatter](#example-an-intercept-provider-and-roman-numeral-formatter) + +## Get started with the String.Format method + +Use if you need to insert the value of an object, variable, or expression into another string. For example, you can insert the value of a value into a string to display it to the user as a single string: + +:::code language="csharp" source="~/snippets/csharp/System/FormatException/Overview/starting2.cs" id="Snippet35"::: +:::code language="fsharp" source="~/snippets/fsharp/System/FormatException/Overview/starting2.fs" id="Snippet35"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Format/starting2.vb" id="Snippet35"::: + +And you can control that value's formatting: + +:::code language="csharp" source="~/snippets/csharp/System/FormatException/Overview/starting2.cs" id="Snippet36"::: +:::code language="fsharp" source="~/snippets/fsharp/System/FormatException/Overview/starting2.fs" id="Snippet36"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Format/starting2.vb" id="Snippet36"::: + +Besides formatting, you can also control alignment and spacing. + +### Insert a string + + starts with a format string, followed by one or more objects or expressions that will be converted to strings and inserted at a specified place in the format string. For example: + +:::code language="csharp" source="~/snippets/csharp/System/FormatException/Overview/starting1.cs" id="Snippet30"::: +:::code language="fsharp" source="~/snippets/fsharp/System/FormatException/Overview/starting1.fs" id="Snippet30"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Format/starting1.vb" id="Snippet30"::: + +The `{0}` in the format string is a format item. `0` is the index of the object whose string value will be inserted at that position. (Indexes start at 0.) If the object to be inserted is not a string, its `ToString` method is called to convert it to one before inserting it in the result string. + +Here's another example that uses two format items and two objects in the object list: + +:::code language="csharp" source="~/snippets/csharp/System/FormatException/Overview/starting1.cs" id="Snippet31"::: +:::code language="fsharp" source="~/snippets/fsharp/System/FormatException/Overview/starting1.fs" id="Snippet31"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Format/starting1.vb" id="Snippet31"::: + +You can have as many format items and as many objects in the object list as you want, as long as the index of every format item has a matching object in the object list. You also don't have to worry about which overload you call; the compiler will select the appropriate one for you. + +### Control formatting + +You can follow the index in a format item with a format string to control how an object is formatted. For example, `{0:d}` applies the "d" format string to the first object in the object list. Here is an example with a single object and two format items: + +:::code language="csharp" source="~/snippets/csharp/System/FormatException/Overview/starting1.cs" id="Snippet32"::: +:::code language="fsharp" source="~/snippets/fsharp/System/FormatException/Overview/starting1.fs" id="Snippet32"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Format/starting1.vb" id="Snippet32"::: + +Numerous types support format strings, including all numeric types (both [standard](/dotnet/standard/base-types/standard-numeric-format-strings) and [custom](/dotnet/standard/base-types/custom-numeric-format-strings) format strings), all dates and times (both [standard](/dotnet/standard/base-types/standard-date-and-time-format-strings) and [custom](/dotnet/standard/base-types/custom-date-and-time-format-strings) format strings) and time intervals (both [standard](/dotnet/standard/base-types/standard-timespan-format-strings) and [custom](/dotnet/standard/base-types/custom-timespan-format-strings) format strings), all enumeration types [enumeration types](/dotnet/standard/base-types/enumeration-format-strings), and [GUIDs](xref:System.Guid.ToString(System.String)). You can also add support for format strings to your own types. + +### Control spacing + +You can define the width of the string that's inserted into the result string by using syntax such as `{0,12}`, which inserts a 12-character string. In this case, the string representation of the first object is right-aligned in the 12-character field. (If the string representation of the first object is more than 12 characters in length, though, the preferred field width is ignored, and the entire string is inserted into the result string.) + +The following example defines a 6-character field to hold the string "Year" and some year strings, as well as an 15-character field to hold the string "Population" and some population data. Note that the characters are right-aligned in the field. + +:::code language="csharp" source="~/snippets/csharp/System/FormatException/Overview/starting3.cs" id="Snippet33"::: +:::code language="fsharp" source="~/snippets/fsharp/System/FormatException/Overview/starting3.fs" id="Snippet33"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Format/starting1.vb" id="Snippet33"::: + +### Control alignment + +By default, strings are right-aligned within their field if you specify a field width. To left-align strings in a field, you preface the field width with a negative sign, such as `{0,-12}` to define a 12-character left-aligned field. + +The following example is similar to the previous one, except that it left-aligns both labels and data. + +:::code language="csharp" source="~/snippets/csharp/System/FormatException/Overview/starting1.cs" id="Snippet34"::: +:::code language="fsharp" source="~/snippets/fsharp/System/FormatException/Overview/starting1.fs" id="Snippet34"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Format/starting1.vb" id="Snippet34"::: + + makes use of the composite formatting feature. For more information, see [Composite Formatting](/dotnet/standard/base-types/composite-formatting). + +## Which method do I call? + +| Objective | Method to call | +|-----------|----------------| +|Format one or more objects by using the conventions of the current culture.|Except for the overloads that include a `provider` parameter, the remaining overloads include a parameter followed by one or more object parameters. Because of this, you don't have to determine which overload you intend to call. Your language compiler selects the appropriate overload from among the overloads that don't have a `provider` parameter, based on your argument list. For example, if your argument list has five arguments, the compiler calls the method.| +|Format one or more objects by using the conventions of a specific culture.|Each overload that begins with a `provider` parameter is followed by a parameter and one or more object parameters. Because of this, you don't have to determine which specific overload you intend to call. Your language compiler selects the appropriate overload from among the overloads that have a `provider` parameter, based on your argument list. For example, if your argument list has five arguments, the compiler calls the method.| +|Perform a custom formatting operation either with an implementation or an implementation.|Any of the four overloads with a `provider` parameter. The compiler selects the appropriate overload from among the overloads that have a `provider` parameter, based on your argument list.| + +## The Format method in brief + +Each overload of the method uses the [composite formatting feature](/dotnet/standard/base-types/composite-formatting) to include zero-based indexed placeholders, called *format items*, in a composite format string. At runtime, each format item is replaced with the string representation of the corresponding argument in a parameter list. If the value of the argument is `null`, the format item is replaced with . For example, the following call to the method includes a format string with three format items, {0}, {1}, and {2}, and an argument list with three items. + +:::code language="csharp" source="~/snippets/csharp/System/FormatException/Overview/formatoverload1.cs" id="Snippet8"::: +:::code language="fsharp" source="~/snippets/fsharp/System/FormatException/Overview/formatoverload1.fs" id="Snippet8"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Format/formatoverload1.vb" id="Snippet8"::: + +## The format item + +A format item has this syntax: + +```txt +{index[,width][:formatString]} +``` + +Brackets denote optional elements. The opening and closing braces are required. (To include a literal opening or closing brace in the format string, see the [Escaping Braces](/dotnet/standard/base-types/composite-formatting.md#escaping-braces) section in the [Composite Formatting](/dotnet/standard/base-types/composite-formatting) article.) + +For example, a format item to format a currency value might appear like this: + +:::code language="csharp" source="~/snippets/csharp/System/FormatException/Overview/formatsyntax1.cs" id="Snippet12"::: +:::code language="fsharp" source="~/snippets/fsharp/System/FormatException/Overview/formatsyntax1.fs" id="Snippet12"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Format/formatsyntax1.vb" id="Snippet12"::: + +A format item has the following elements: + +`index`\ +The zero-based index of the argument whose string representation is to be included at this position in the string. If this argument is `null`, an empty string will be included at this position in the string. + +`width`\ +Optional. A signed integer that indicates the total length of the field into which the argument is inserted and whether it is right-aligned (a positive integer) or left-aligned (a negative integer). If you omit `width`, the string representation of the corresponding argument is inserted in a field with no leading or trailing spaces. + +If the value of `width` is less than the length of the argument to be inserted, `width` is ignored and the length of the string representation of the argument is used as the field width. + +`formatString`\ +Optional. A string that specifies the format of the corresponding argument's result string. If you omit `formatString`, the corresponding argument's parameterless `ToString` method is called to produce its string representation. If you specify `formatString`, the argument referenced by the format item must implement the interface. Types that support format strings include: + +- All integral and floating-point types. (See [Standard Numeric Format Strings](/dotnet/standard/base-types/standard-numeric-format-strings) and [Custom Numeric Format Strings](/dotnet/standard/base-types/custom-numeric-format-strings).) + +- and . (See [Standard Date and Time Format Strings](/dotnet/standard/base-types/standard-date-and-time-format-strings) and [Custom Date and Time Format Strings](/dotnet/standard/base-types/custom-date-and-time-format-strings).) + +- All enumeration types. (See [Enumeration Format Strings](/dotnet/standard/base-types/enumeration-format-strings).) + +- values. (See [Standard TimeSpan Format Strings](/dotnet/standard/base-types/standard-timespan-format-strings) and [Custom TimeSpan Format Strings](/dotnet/standard/base-types/custom-timespan-format-strings).) + +- GUIDs. (See the method.) + +However, any custom type can implement or extend an existing type's implementation. + +The following example uses the `width` and `formatString` arguments to produce formatted output. + +:::code language="csharp" source="~/snippets/csharp/System/FormatException/Overview/formatoverload2.cs" id="Snippet9"::: +:::code language="fsharp" source="~/snippets/fsharp/System/FormatException/Overview/formatoverload2.fs" id="Snippet9"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Format/formatoverload2.vb" id="Snippet9"::: + +## How arguments are formatted + +Format items are processed sequentially from the beginning of the string. Each format item has an index that corresponds to an object in the method's argument list. The method retrieves the argument and derives its string representation as follows: + +- If the argument is `null`, the method inserts into the result string. You don't have to be concerned with handling a for null arguments. + +- If you call the overload and the `provider` object's implementation returns a non-null implementation, the argument is passed to its method. If the format item includes a `formatString` argument, it is passed as the first argument to the method. If the implementation is available and produces a non-null string, that string is returned as the string representation of the argument; otherwise, the next step executes. + +- If the argument implements the interface, its implementation is called. + +- The argument's parameterless `ToString` method, which either overrides or inherits from a base class implementation, is called. + +For an example that intercepts calls to the method and allows you to see what information the method passes to a formatting method for each format item in a composite format string, see [Example: An intercept provider and Roman numeral formatter](#example-an-intercept-provider-and-roman-numeral-formatter). + +For more information, see [Processing order](/dotnet/standard/base-types/composite-formatting.md#processing-order). + +## Format items that have the same index + +The method throws a exception if the index of an index item is greater than or equal to the number of arguments in the argument list. However, `format` can include more format items than there are arguments, as long as multiple format items have the same index. In the call to the method in following example, the argument list has a single argument, but the format string includes two format items: one displays the decimal value of a number, and the other displays its hexadecimal value. + +:::code language="csharp" source="~/snippets/csharp/System/String/Format/Example1.cs" id="Snippet1"::: +:::code language="fsharp" source="~/snippets/fsharp/System/String/Format/Example1.fs" id="Snippet1"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Format/Example1.vb" id="Snippet1"::: + +## Format and culture + +Generally, objects in the argument list are converted to their string representations by using the conventions of the current culture, which is returned by the property. You can control this behavior by calling one of the overloads of that includes a `provider` parameter. The `provider` parameter is an implementation that supplies custom and culture-specific formatting information that is used to moderate the formatting process. + +The interface has a single member, , which is responsible for returning the object that provides formatting information. .NET has three implementations that provide culture-specific formatting: + +- . Its method returns a culture-specific object for formatting numeric values and a culture-specific object for formatting date and time values. +- , which is used for culture-specific formatting of date and time values. Its method returns itself. +- , which is used for culture-specific formatting of numeric values. Its method returns itself. + +## Custom formatting operations + +You can also call the any of the overloads of the method that have a `provider` parameter of type to perform custom formatting operations. For example, you could format an integer as an identification number or as a telephone number. To perform custom formatting, your `provider` argument must implement both the and interfaces. When the method is passed an implementation as the `provider` argument, the method calls its implementation and requests an object of type . It then calls the returned object's method to format each format item in the composite string passed to it. + +For more information about providing custom formatting solutions, see [How to: Define and Use Custom Numeric Format Providers](/dotnet/standard/base-types/how-to-define-and-use-custom-numeric-format-providers) and . For an example that converts integers to formatted custom numbers, see [Example: A custom formatting operation](#example-a-custom-formatting-operation). For an example that converts unsigned bytes to Roman numerals, see [Example: An intercept provider and Roman numeral formatter](#example-an-intercept-provider-and-roman-numeral-formatter). + +### Example: A custom formatting operation + +This example defines a format provider that formats an integer value as a customer account number in the form x-xxxxx-xx. + +:::code language="csharp" source="~/snippets/csharp/System/FormatException/Overview/FormatExample2.cs" id="Snippet2"::: +:::code language="fsharp" source="~/snippets/fsharp/System/FormatException/Overview/FormatExample2.fs" id="Snippet2"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Format/FormatExample2.vb" id="Snippet2"::: + +### Example: An intercept provider and Roman numeral formatter + +This example defines a custom format provider that implements the and interfaces to do two things: + +- It displays the parameters passed to its implementation. This enables us to see what parameters the method is passing to the custom formatting implementation for each object that it tries to format. This can be useful when you're debugging your application. +- If the object to be formatted is an unsigned byte value that is to be formatted by using the "R" standard format string, the custom formatter formats the numeric value as a Roman numeral. + +:::code language="csharp" source="~/snippets/csharp/System/FormatException/Overview/interceptor2.cs" id="Snippet11"::: +:::code language="fsharp" source="~/snippets/fsharp/System/FormatException/Overview/interceptor2.fs" id="Snippet11"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Format/interceptor2.vb" id="Snippet11"::: + +## FAQ + +### Why do you recommend string interpolation over calls to the `String.Format` method? + +String interpolation is: + +- More flexible. It can be used in any string without requiring a call to a method that supports composite formatting. Otherwise, you have to call the method or another method that supports composite formatting, such as or . +- More readable. Because the expression to insert into a string appears in the interpolated expression rather than in a argument list, interpolated strings are easier to code and to read. Interpolated strings can also be used in string concatenation operations to produce more concise, clearer code. + +A comparison of the following two code examples illustrates the superiority of interpolated strings over string concatenation and calls to composite formatting methods. The use of multiple string concatenation operations in the following example produces verbose and hard-to-read code. + +:::code language="csharp" source="~/snippets/csharp/System/FormatException/Overview/qa-interpolated1.cs" id="SnippetQAInterpolated"::: +:::code language="fsharp" source="~/snippets/fsharp/System/FormatException/Overview/qa-interpolated1.fs" id="SnippetQAInterpolated"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Format/qa-interpolated1.vb"::: + +In contrast, the use of interpolated strings in the following example produces much clearer, more concise code than the string concatenation statement and the call to the method in the previous example. + +:::code language="csharp" source="~/snippets/csharp/System/FormatException/Overview/qa-interpolated2.cs" id="SnippetQAInterpolated2"::: +:::code language="fsharp" source="~/snippets/fsharp/System/FormatException/Overview/qa-interpolated2.fs" id="SnippetQAInterpolated2"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Format/qa-interpolated2.vb"::: + +### Where can I find the predefined format strings? + +- For all integral and floating-point types, see [Standard Numeric Format Strings](/dotnet/standard/base-types/standard-numeric-format-strings) and [Custom Numeric Format Strings](/dotnet/standard/base-types/custom-numeric-format-strings). +- For date and time values, see [Standard Date and Time Format Strings](/dotnet/standard/base-types/standard-date-and-time-format-strings) and [Custom Date and Time Format Strings](/dotnet/standard/base-types/custom-date-and-time-format-strings). +- For enumeration values, see [Enumeration Format Strings](/dotnet/standard/base-types/enumeration-format-strings). +- For values, see [Standard TimeSpan Format Strings](/dotnet/standard/base-types/standard-timespan-format-strings) and [Custom TimeSpan Format Strings](/dotnet/standard/base-types/custom-timespan-format-strings). +- For values, see the Remarks section of the reference page. + +### How do I control the alignment of the result strings that replace format items? + +The general syntax of a format item is: + +```txt +{index[,width][: formatString]} +``` + +`width` is a signed integer that defines the field width. If this value is negative, text in the field is left-aligned. If it is positive, text is right-aligned. + +### How do I control the number of digits after the decimal separator? + +All [standard numeric format strings](/dotnet/standard/base-types/standard-numeric-format-strings) except "D" (which is used with integers only), "G", "R", and "X" allow a precision specifier that defines the number of decimal digits in the result string. The following example uses standard numeric format strings to control the number of decimal digits in the result string. + +:::code language="csharp" source="~/snippets/csharp/System/FormatException/Overview/qa26.cs" id="Snippet26"::: +:::code language="fsharp" source="~/snippets/fsharp/System/FormatException/Overview/qa26.fs" id="Snippet26"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Format/qa26.vb" id="Snippet26"::: + +If you're using a [custom numeric format string](/dotnet/standard/base-types/custom-numeric-format-strings), use the "0" format specifier to control the number of decimal digits in the result string, as the following example shows. + +:::code language="csharp" source="~/snippets/csharp/System/FormatException/Overview/qa27.cs" id="Snippet27"::: +:::code language="fsharp" source="~/snippets/fsharp/System/FormatException/Overview/qa27.fs" id="Snippet27"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Format/qa27.vb" id="Snippet27"::: + +### How do I control the number of integral digits? + +By default, formatting operations only display non-zero integral digits. If you're formatting integers, you can use a precision specifier with the "D" and "X" standard format strings to control the number of digits. + +:::code language="csharp" source="~/snippets/csharp/System/FormatException/Overview/qa29.cs" id="Snippet29"::: +:::code language="fsharp" source="~/snippets/fsharp/System/FormatException/Overview/qa29.fs" id="Snippet29"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Format/qa29.vb" id="Snippet29"::: + +You can pad an integer or floating-point number with leading zeros to produce a result string with a specified number of integral digits by using the "0" [custom numeric format specifier](/dotnet/standard/base-types/custom-numeric-format-strings), as the following example shows. + +:::code language="csharp" source="~/snippets/csharp/System/FormatException/Overview/qa28.cs" id="Snippet28"::: +:::code language="fsharp" source="~/snippets/fsharp/System/FormatException/Overview/qa28.fs" id="Snippet28"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Format/qa28.vb" id="Snippet28"::: + +### How many items can I include in the format list? + +There is no practical limit. The second parameter of the method is tagged with the attribute, which allows you to include either a delimited list or an object array as your format list. + +### How do I include literal braces ("{" and "}") in the result string? + +For example, how do you prevent the following method call from throwing a exception? + +:::code language="csharp" source="~/snippets/csharp/System/FormatException/Overview/qa3.cs" id="Snippet23"::: +:::code language="fsharp" source="~/snippets/fsharp/System/FormatException/Overview/qa3.fs" id="Snippet23"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Format/qa3.vb" id="Snippet23"::: + +A single opening or closing brace is always interpreted as the beginning or end of a format item. To be interpreted literally, it must be escaped. You escape a brace by adding another brace ("{{" and "}}" instead of "{" and "}"), as in the following method call: + +:::code language="csharp" source="~/snippets/csharp/System/FormatException/Overview/qa3.cs" id="Snippet24"::: +:::code language="fsharp" source="~/snippets/fsharp/System/FormatException/Overview/qa3.fs" id="Snippet24"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Format/qa3.vb" id="Snippet24"::: + +However, even escaped braces are easily misinterpreted. We recommend that you include braces in the format list and use format items to insert them in the result string, as the following example shows. + +:::code language="csharp" source="~/snippets/csharp/System/FormatException/Overview/qa3.cs" id="Snippet25"::: +:::code language="fsharp" source="~/snippets/fsharp/System/FormatException/Overview/qa3.fs" id="Snippet25"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Format/qa3.vb" id="Snippet25"::: + +### Why does my call to the String.Format method throw a FormatException? + +The most common cause of the exception is that the index of a format item doesn't correspond to an object in the format list. Usually this indicates that you've misnumbered the indexes of format items or you've forgotten to include an object in the format list. Attempting to include an unescaped left or right brace character also throws a . Occasionally, the exception is the result of a typo; for example, a typical mistake is to mistype "[" (the left bracket) instead of "{" (the left brace). + +### If the Format(System.IFormatProvider,System.String,System.Object[]) method supports parameter arrays, why does my code throw an exception when I use an array? + +For example, the following code throws a exception: + +:::code language="csharp" source="~/snippets/csharp/System/FormatException/Overview/qa11.cs" id="Snippet21"::: +:::code language="fsharp" source="~/snippets/fsharp/System/FormatException/Overview/qa11.fs" id="Snippet21"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Format/qa1.vb" id="Snippet21"::: + +This is a problem of compiler overload resolution. Because the compiler cannot convert an array of integers to an object array, it treats the integer array as a single argument, so it calls the method. The exception is thrown because there are four format items but only a single item in the format list. + +Because neither Visual Basic nor C# can convert an integer array to an object array, you have to perform the conversion yourself before calling the method. The following example provides one implementation. + +:::code language="csharp" source="~/snippets/csharp/System/FormatException/Overview/qa21.cs" id="Snippet22"::: +:::code language="fsharp" source="~/snippets/fsharp/System/FormatException/Overview/qa21.fs" id="Snippet22"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Format/qa2.vb" id="Snippet22"::: + + ]]> + Formatting Types in .NET Composite Formatting Standard Date and Time Format Strings @@ -8143,8 +9093,24 @@ The following console application prompts the users to enter one or more adjecti > ![NOTE] > While `String.Intern` guarantees that two strings with equal values return the same interned reference, it doesn't guarantee that the returned reference is the same as a string literal. - For more information about this API, see [Supplemental API remarks for String.Intern](/dotnet/fundamentals/runtime-libraries/system-string-intern). - ]]>
+ The common language runtime maintains a table, called the *intern pool*, that holds a single reference for each unique string value. The method uses the intern pool to search for a string equal to the value of `str`. If no such string exists, a reference to `str` is added to the pool, and that reference is returned. (In contrast, the method returns a null reference if the requested string doesn't exist in the intern pool.) + +The intern pool can be used by the runtime to conserve string storage. However, automatic interning of string literals isn't guaranteed—depending on how the assembly was compiled and executed, some literals might not be added to the pool. + +In the following example, the string `s1` has a value of "MyTest". The class generates a new string object that has the same value as `s1`. A reference to that string is assigned to `s2`. The method searches for a string that has the same value as `s2`. If `s1` was already interned (for example, because the assembly requires string-literal interning), the method returns the same reference as `s1`, which is then assigned to `s3`, and `s1` and `s3` compare equal. Otherwise, a new interned entry is created for `s2` and assigned to `s3`, and `s1` and `s3` compare unequal. In either case, `s1` and `s2` compare unequal because they refer to different objects. + +:::code language="csharp" source="~/snippets/csharp/System/String/Intern/Intern1.cs" id="Snippet1"::: +:::code language="fsharp" source="~/snippets/fsharp/System/String/Intern/Intern1.fs" id="Snippet1"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/Intern/Intern1.vb" id="Snippet1"::: + +## Performance considerations + +If you're trying to reduce the total amount of memory your application allocates, keep in mind that interning a string has two unwanted side effects. First, the memory allocated for interned objects is not likely to be released until the common language runtime (CLR) terminates. The reason is that the CLR's reference to the interned object can persist after your application, or even your application domain, terminates. Second, to intern a string, you must first create the string. The memory used by the object must still be allocated, even though the memory will eventually be garbage collected. + +The enumeration member marks an assembly as not requiring string-literal interning. By default, the C# compiler emits a with the flag on each assembly for better performance, which means string literals are not guaranteed to be added to the intern pool. You can customize on an assembly using the attribute. + +When you publish an app using [native AOT](/dotnet/core/deploying/native-aot/index), turning off is not supported. With native AOT, string literals aren't guaranteed to be added to the intern pool, so might not find a match for a string that appears to be a literal in source code. +]]>
Indicates whether the specified string is or an empty string (""). if the parameter is or an empty string (""); otherwise, . - For more information about this API, see Supplemental API remarks for String.IsNullOrEmpty. + + is a convenience method that enables you to simultaneously test whether a is `null` or its value is . It is equivalent to the following code: + +:::code language="csharp" source="~/snippets/csharp/System/String/IsNullOrEmpty/isnullorempty1.cs" id="Snippet1"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/IsNullOrEmpty/isnullorempty1.vb" id="Snippet1"::: +:::code language="fsharp" source="~/snippets/fsharp/System/String/IsNullOrEmpty/isnullorempty1.fs" id="Snippet1"::: + +You can use the method to test whether a string is `null`, its value is , or it consists only of white-space characters. + +## What is a null string? + +A string is `null` if it has not been assigned a value (in C++ and Visual Basic) or if it has explicitly been assigned a value of `null`. Although the [composite formatting](/dotnet/standard/base-types/composite-formatting) feature can gracefully handle a null string, as the following example shows, attempting to call one if its members throws a . + +:::code language="csharp" source="~/snippets/csharp/System/String/IsNullOrEmpty/NullString1.cs" id="Snippet2"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/IsNullOrEmpty/NullString1.vb" id="Snippet2"::: +:::code language="fsharp" source="~/snippets/fsharp/System/String/IsNullOrEmpty/NullString1.fs" id="Snippet2"::: + +## What is an empty string? + +A string is empty if it's explicitly assigned an empty string ("") or . An empty string has a of 0. The following example creates an empty string and displays its value and its length. + +:::code language="csharp" source="~/snippets/csharp/System/String/IsNullOrEmpty/NullString1.cs" id="Snippet3"::: +:::code language="vb" source="~/snippets/visualbasic/System/String/IsNullOrEmpty/NullString1.vb" id="Snippet3"::: +:::code language="fsharp" source="~/snippets/fsharp/System/String/IsNullOrEmpty/NullString2.fs" id="Snippet3"::: + + ]]> + Represents a string comparison operation that uses specific case and culture-based or ordinal comparison rules. - For more information about this API, see Supplemental API remarks for StringComparer. + + class embodies string-based comparison, equality, and hash code operations that take into account both case and culture-specific comparison rules. You can use the class to create a type-specific comparison to sort the elements in a generic collection. Classes such as , , , and use the class for sorting purposes. + +A comparison operation that is represented by the class is defined to be either case-sensitive or case-insensitive, and use either word (culture-sensitive) or ordinal (culture-insensitive) comparison rules. For more information about word and ordinal comparison rules, see . + +> [!NOTE] +> You can download the [Default Unicode Collation Element Table](https://www.unicode.org/Public/UCA/latest/allkeys.txt), the latest version of the sort weight table. The specific version of the sort weight table depends on the version of the [International Components for Unicode](https://icu.unicode.org/) libraries installed on the system. For information on ICU versions and the Unicode versions that they implement, see [Downloading ICU](https://icu.unicode.org/download). + +## Implemented properties + +You might be confused about how to use the class properties because of a seeming contradiction. The class is declared `abstract` (`MustInherit` in Visual Basic), which means its members can be invoked only on an object of a class derived from the class. The contradiction is that each property of the class is declared `static` (`Shared` in Visual Basic), which means the property can be invoked without first creating a derived class. + +You can call a property directly because each property actually returns an instance of an anonymous class that is derived from the class. Consequently, the type of each property value is , which is the base class of the anonymous class, not the type of the anonymous class itself. Each class property returns a object that supports predefined case and comparison rules. + + ]]> + method of the class. The example illustrates how different objects sort three versions of the Latin letter I. diff --git a/xml/System/TimeSpan.xml b/xml/System/TimeSpan.xml index 11d92838e49..d6f34f5ab73 100644 --- a/xml/System/TimeSpan.xml +++ b/xml/System/TimeSpan.xml @@ -99,7 +99,70 @@ Represents a time interval. - For more information about this API, see Supplemental API remarks for TimeSpan. + + object represents a time interval (duration of time or elapsed time) that is measured as a positive or negative number of days, hours, minutes, seconds, and fractions of a second. The structure can also be used to represent the time of day, but only if the time is unrelated to a particular date. Otherwise, the or structure should be used instead. (For more information about using the structure to reflect the time of day, see [Choosing Between DateTime, DateTimeOffset, TimeSpan, and TimeZoneInfo](/dotnet/standard/datetime/choosing-between-datetime).) + +> [!NOTE] +> A value represents a time interval and can be expressed as a particular number of days, hours, minutes, seconds, and milliseconds. Because it represents a general interval without reference to a particular start or end point, it cannot be expressed in terms of years and months, both of which have a variable number of days. It differs from a value, which represents a date and time without reference to a particular time zone, or a value, which represents a specific moment of time. + +The largest unit of time that the structure uses to measure duration is a day. Time intervals are measured in days for consistency, because the number of days in larger units of time, such as months and years, varies. + +The value of a object is the number of ticks that equal the represented time interval. A tick is equal to 100 nanoseconds, or one ten-millionth of a second. The value of a object can range from to . + +## Instantiate a TimeSpan value + +You can instantiate a value in a number of ways: + +- By calling its implicit parameterless constructor. This creates an object whose value is , as the following example shows. + + :::code language="csharp" source="~/snippets/csharp/System/TimeSpan/Overview/instantiate1.cs" id="Snippet2"::: + :::code language="fsharp" source="~/snippets/fsharp/System/TimeSpan/Overview/instantiate1.fs" id="Snippet2"::: + :::code language="vb" source="~/snippets/visualbasic/System/TimeSpan/Overview/instantiate1.vb" id="Snippet2"::: + +- By calling one of its explicit constructors. The following example initializes a value to a specified number of hours, minutes, and seconds. + + :::code language="csharp" source="~/snippets/csharp/System/TimeSpan/Overview/instantiate1.cs" id="Snippet3"::: + :::code language="fsharp" source="~/snippets/fsharp/System/TimeSpan/Overview/instantiate1.fs" id="Snippet3"::: + :::code language="vb" source="~/snippets/visualbasic/System/TimeSpan/Overview/instantiate1.vb" id="Snippet3"::: + +- By calling a method or performing an operation that returns a value. For example, you can instantiate a value that represents the interval between two date and time values, as the following example shows. + + :::code language="csharp" source="~/snippets/csharp/System/TimeSpan/Overview/instantiate1.cs" id="Snippet4"::: + :::code language="fsharp" source="~/snippets/fsharp/System/TimeSpan/Overview/instantiate1.fs" id="Snippet4"::: + :::code language="vb" source="~/snippets/visualbasic/System/TimeSpan/Overview/instantiate1.vb" id="Snippet4"::: + + You can also initialize a object to a zero time value in this way, as the following example shows. + + :::code language="csharp" source="~/snippets/csharp/System/TimeSpan/Overview/zero1.cs" id="Snippet6"::: + :::code language="fsharp" source="~/snippets/fsharp/System/TimeSpan/Overview/zero1.fs" id="Snippet6"::: + :::code language="vb" source="~/snippets/visualbasic/System/TimeSpan/Overview/zero1.vb" id="Snippet6"::: + + values are returned by arithmetic operators and methods of the , , and structures. + +- By parsing the string representation of a value. You can use the and methods to convert strings that contain time intervals to values. The following example uses the method to convert an array of strings to values. + + :::code language="csharp" source="~/snippets/csharp/System/TimeSpan/Overview/instantiate1.cs" id="Snippet5"::: + :::code language="fsharp" source="~/snippets/fsharp/System/TimeSpan/Overview/instantiate1.fs" id="Snippet5"::: + :::code language="vb" source="~/snippets/visualbasic/System/TimeSpan/Overview/instantiate1.vb" id="Snippet5"::: + + In addition, you can define the precise format of the input string to be parsed and converted to a value by calling the or method. + +## Perform operations on TimeSpan values + +You can add and subtract time durations either by using the and operators, or by calling the and methods. You can also compare two time durations by calling the , , and methods. The structure also includes the and methods, which convert time intervals to positive and negative values, + +The range of values is to . + +## Format a TimeSpan value + +A value can be represented as [*-*]*d*.*hh*:*mm*:*ss*.*ff*, where the optional minus sign indicates a negative time interval, the *d* component is days, *hh* is hours as measured on a 24-hour clock, *mm* is minutes, *ss* is seconds, and *ff* is fractions of a second. That is, a time interval consists of a positive or negative number of days without a time of day, or a number of days with a time of day, or only a time of day. + +The structure supports culture-sensitive formatting through the overloads of its method, which converts a value to its string representation. The overload lets you specify a format string that defines the string representation of the time interval. The overload lets you specify a format string and the culture whose formatting conventions are used to create the string representation of the time interval. supports both standard and custom format strings. (For more information, see [Standard TimeSpan Format Strings](/dotnet/standard/base-types/standard-timespan-format-strings) and [Custom TimeSpan Format Strings](/dotnet/standard/base-types/custom-timespan-format-strings).) However, only standard format strings are culture-sensitive. + + ]]> + object that represents the difference between two dates. It then displays the object's properties. @@ -3851,7 +3914,36 @@ The value of this constant is 100. A string that specifies the time interval to convert. Converts the string representation of a time interval to its equivalent. A time interval that corresponds to . - For more information about this API, see Supplemental API remarks for TimeSpan.Parse. + + methods contains a time interval specification in the form: + +`[ws][-]{ d | [d.]hh:mm[:ss[.ff]] }[ws]` + +Elements in square brackets (`[` and `]`) are optional. One selection from the list of alternatives enclosed in braces (`{` and `}`) and separated by vertical bars (|) is required. The following table describes each element. + +| Element | Description | +|---------|----------------------------------------------------------------------------------------------------------------| +| *ws* | Optional white space. | +| - | An optional minus sign, which indicates a negative . | +| *d* | Days, ranging from 0 to 10675199. | +| . | A culture-sensitive symbol that separates days from hours. The invariant format uses a period (".") character. | +| *hh* | Hours, ranging from 0 to 23. | +| : | The culture-sensitive time separator symbol. The invariant format uses a colon (":") character. | +| *mm* | Minutes, ranging from 0 to 59. | +| *ss* | Optional seconds, ranging from 0 to 59. | +| *.* | A culture-sensitive symbol that separates seconds from fractions of a second. The invariant format uses a period (".") character. | +| *ff* | Optional fractional seconds, consisting of one to seven decimal digits. | + +If the input string is not a day value only, it must include an hours and a minutes component; other components are optional. If they are present, the values of each time component must fall within a specified range. For example, the value of *hh*, the hours component, must be between 0 and 23. Because of this, passing "23:00:00" to the method returns a time interval of 23 hours. On the other hand, passing "24:00:00" returns a time interval of 24 days. Because "24" is outside the range of the hours component, it is interpreted as the days component. + +The components of the input string must collectively specify a time interval that is greater than or equal to and less than or equal to . + +The method tries to parse the input string by using each of the culture-specific formats for the current culture. + + ]]> + method to convert each element in a string array to a value. It changes the current system culture to Croatian - Croatia ("hr-HR") and English - United States ("en-US") to illustrate how the current system culture affects the parsing operation. @@ -3990,8 +4082,32 @@ The `formatProvider` parameter is an implementatio If `formatProvider` is `null`, the object that is associated with the current culture is used. -For more information about this API, see [Supplemental API remarks for System.TimeSpan.Parse](/dotnet/fundamentals/runtime-libraries/system-timespan-parse). - ]]> +The input string to the methods contains a time interval specification in the form: + +`[ws][-]{ d | [d.]hh:mm[:ss[.ff]] }[ws]` + +Elements in square brackets (`[` and `]`) are optional. One selection from the list of alternatives enclosed in braces (`{` and `}`) and separated by vertical bars (|) is required. The following table describes each element. + +| Element | Description | +|---------|----------------------------------------------------------------------------------------------------------------| +| *ws* | Optional white space. | +| - | An optional minus sign, which indicates a negative . | +| *d* | Days, ranging from 0 to 10675199. | +| . | A culture-sensitive symbol that separates days from hours. The invariant format uses a period (".") character. | +| *hh* | Hours, ranging from 0 to 23. | +| : | The culture-sensitive time separator symbol. The invariant format uses a colon (":") character. | +| *mm* | Minutes, ranging from 0 to 59. | +| *ss* | Optional seconds, ranging from 0 to 59. | +| *.* | A culture-sensitive symbol that separates seconds from fractions of a second. The invariant format uses a period (".") character. | +| *ff* | Optional fractional seconds, consisting of one to seven decimal digits. | + +If the input string is not a day value only, it must include an hours and a minutes component; other components are optional. If they are present, the values of each time component must fall within a specified range. For example, the value of *hh*, the hours component, must be between 0 and 23. Because of this, passing "23:00:00" to the method returns a time interval of 23 hours. On the other hand, passing "24:00:00" returns a time interval of 24 days. Because "24" is outside the range of the hours component, it is interpreted as the days component. + +The components of the input string must collectively specify a time interval that is greater than or equal to and less than or equal to . + +The method tries to parse the input string by using each of the culture-specific formats for the current culture. + +]]> property represents whole and fracti Converts the string representation of a time interval to its equivalent and returns a value that indicates whether the conversion succeeded. if was converted successfully; otherwise, . This operation returns if the parameter is or , has an invalid format, represents a time interval that is less than TimeSpan.MinValue or greater than TimeSpan.MaxValue, or has at least one days, hours, minutes, or seconds component outside its valid range. - For more information about this API, see Supplemental API remarks for TimeSpan.TryParse. + + method is like the method, except that it doesn't throw an exception if the conversion fails. + +The `s` parameter contains a time interval specification in the form: + +`[ws][-]{ d | d.hh:mm[:ss[.ff]] | hh:mm[:ss[.ff]] }[ws]` + +Elements in square brackets ([ and ]) are optional. One selection from the list of alternatives enclosed in braces ({ and }) and separated by vertical bars (|) is required. The following table describes each element. + +| Element | Description | +|---------|-------------------------------------------------------------------------------------------------| +| *ws* | Optional white space. | +| - | An optional minus sign, which indicates a negative . | +| *d* | Days, ranging from 0 to 10675199. | +| . | A culture-sensitive symbol that separates days from hours. The invariant format uses a period (".") character.| +| *hh* | Hours, ranging from 0 to 23. | +| : | The culture-sensitive time separator symbol. The invariant format uses a colon (":") character. | +| *mm* | Minutes, ranging from 0 to 59. | +| *ss* | Optional seconds, ranging from 0 to 59. | +| . | A culture-sensitive symbol that separates seconds from fractions of a second. The invariant format uses a period (".") character.| +| *ff* | Optional fractional seconds, consisting of one to seven decimal digits. | + +The components of `s` must collectively specify a time interval that's greater than or equal to and less than or equal to . + +The method tries to parse `s` by using each of the culture-specific formats for the current culture. + +## method + +The method is like the method, except that it does not throw an exception if the conversion fails. + +The `input` parameter contains a time interval specification in the form: + +`[ws][-]{ d | d.hh:mm[:ss[.ff]] | hh:mm[:ss[.ff]] }[ws]` + +Elements in square brackets ([ and ]) are optional. One selection from the list of alternatives enclosed in braces ({ and }) and separated by vertical bars (|) is required. The following table describes each element. + +| Element | Description | +|---------|----------------------------------------------------------------------------------------------------------------| +| *ws* | Optional white space. | +| - | An optional minus sign, which indicates a negative . | +| *d* | Days, ranging from 0 to 10675199. | +| . | A culture-sensitive symbol that separates days from hours. The invariant format uses a period (".") character. | +| *hh* | Hours, ranging from 0 to 23. | +| : | The culture-sensitive time separator symbol. The invariant format uses a colon (":") character. | +| *mm* | Minutes, ranging from 0 to 59. | +| *ss* | Optional seconds, ranging from 0 to 59. | +| . | A culture-sensitive symbol that separates seconds from fractions of a second. The invariant format uses a period (".") character. | +| *ff* | Optional fractional seconds, consisting of one to seven decimal digits. | + +The components of `input` must collectively specify a time interval that is greater than or equal to and less than or equal to . + +The method tries to parse `input` by using each of the culture-specific formats for the culture specified by `formatProvider`. + +The `formatProvider` parameter is an implementation that provides culture-specific information about the format of the returned string. The `formatProvider` parameter can be any of the following: + +- A object that represents the culture whose formatting conventions are to be reflected in the returned string. The object returned by the property defines the formatting of the returned string. +- A object that defines the formatting of the returned string. +- A custom object that implements the interface. Its method returns a object that provides formatting information. + +If `formatProvider` is `null`, the object that is associated with the current culture is used. + + ]]> + method to create objects from valid strings and to indicate when the parse operation has failed because the time span string is invalid. @@ -6303,7 +6485,73 @@ The following example uses the method to create Converts the string representation of a time interval to its equivalent by using the specified culture-specific formatting information, and returns a value that indicates whether the conversion succeeded. if was converted successfully; otherwise, . This operation returns if the parameter is or , has an invalid format, represents a time interval that is less than TimeSpan.MinValue or greater than TimeSpan.MaxValue, or has at least one days, hours, minutes, or seconds component outside its valid range. - For more information about this API, see Supplemental API remarks for TimeSpan.TryParse. + + method is like the method, except that it doesn't throw an exception if the conversion fails. + +The `s` parameter contains a time interval specification in the form: + +`[ws][-]{ d | d.hh:mm[:ss[.ff]] | hh:mm[:ss[.ff]] }[ws]` + +Elements in square brackets ([ and ]) are optional. One selection from the list of alternatives enclosed in braces ({ and }) and separated by vertical bars (|) is required. The following table describes each element. + +| Element | Description | +|---------|-------------------------------------------------------------------------------------------------| +| *ws* | Optional white space. | +| - | An optional minus sign, which indicates a negative . | +| *d* | Days, ranging from 0 to 10675199. | +| . | A culture-sensitive symbol that separates days from hours. The invariant format uses a period (".") character.| +| *hh* | Hours, ranging from 0 to 23. | +| : | The culture-sensitive time separator symbol. The invariant format uses a colon (":") character. | +| *mm* | Minutes, ranging from 0 to 59. | +| *ss* | Optional seconds, ranging from 0 to 59. | +| . | A culture-sensitive symbol that separates seconds from fractions of a second. The invariant format uses a period (".") character.| +| *ff* | Optional fractional seconds, consisting of one to seven decimal digits. | + +The components of `s` must collectively specify a time interval that's greater than or equal to and less than or equal to . + +The method tries to parse `s` by using each of the culture-specific formats for the current culture. + +## method + +The method is like the method, except that it does not throw an exception if the conversion fails. + +The `input` parameter contains a time interval specification in the form: + +`[ws][-]{ d | d.hh:mm[:ss[.ff]] | hh:mm[:ss[.ff]] }[ws]` + +Elements in square brackets ([ and ]) are optional. One selection from the list of alternatives enclosed in braces ({ and }) and separated by vertical bars (|) is required. The following table describes each element. + +| Element | Description | +|---------|----------------------------------------------------------------------------------------------------------------| +| *ws* | Optional white space. | +| - | An optional minus sign, which indicates a negative . | +| *d* | Days, ranging from 0 to 10675199. | +| . | A culture-sensitive symbol that separates days from hours. The invariant format uses a period (".") character. | +| *hh* | Hours, ranging from 0 to 23. | +| : | The culture-sensitive time separator symbol. The invariant format uses a colon (":") character. | +| *mm* | Minutes, ranging from 0 to 59. | +| *ss* | Optional seconds, ranging from 0 to 59. | +| . | A culture-sensitive symbol that separates seconds from fractions of a second. The invariant format uses a period (".") character. | +| *ff* | Optional fractional seconds, consisting of one to seven decimal digits. | + +The components of `input` must collectively specify a time interval that is greater than or equal to and less than or equal to . + +The method tries to parse `input` by using each of the culture-specific formats for the culture specified by `formatProvider`. + +The `formatProvider` parameter is an implementation that provides culture-specific information about the format of the returned string. The `formatProvider` parameter can be any of the following: + +- A object that represents the culture whose formatting conventions are to be reflected in the returned string. The object returned by the property defines the formatting of the returned string. +- A object that defines the formatting of the returned string. +- A custom object that implements the interface. Its method returns a object that provides formatting information. + +If `formatProvider` is `null`, the object that is associated with the current culture is used. + + ]]> + objects, and uses each object in calls to the method to parse the elements in a string array. The example illustrates how the conventions of a specific culture influence the formatting operation. diff --git a/xml/System/Type.xml b/xml/System/Type.xml index 4330e0d6f85..24048c5e1eb 100644 --- a/xml/System/Type.xml +++ b/xml/System/Type.xml @@ -65,7 +65,83 @@ Represents type declarations: class types, interface types, array types, value types, enumeration types, type parameters, generic type definitions, and open or closed constructed generic types. - For more information about this API, see Supplemental API remarks for Type. + + class is the root of the functionality and is the primary way to access metadata. Use the members of to get information about a type declaration, about the members of a type (such as the constructors, methods, fields, properties, and events of a class), as well as the module and the assembly in which the class is deployed. + +No permissions are required for code to use reflection to get information about types and their members, regardless of their access levels. No permissions are required for code to use reflection to access public members, or other members whose access levels would make them visible during normal compilation. However, in order for your code to use reflection to access members that would normally be inaccessible, such as private or internal methods, or protected fields of a type your class does not inherit, your code must have . See [Security Considerations for Reflection](/dotnet/framework/reflection-and-codedom/security-considerations-for-reflection). + +`Type` is an abstract base class that allows multiple implementations. The system will always provide the derived class `RuntimeType`. In reflection, all classes beginning with the word Runtime are created only once per object in the system and support comparison operations. + +> [!NOTE] +> In multithreading scenarios, do not lock objects in order to synchronize access to `static` data. Other code, over which you have no control, might also lock your class type. This might result in a deadlock. Instead, synchronize access to static data by locking a private `static` object. + +> [!NOTE] +> A derived class can access protected members of the calling code's base classes. Also, access is allowed to assembly members of the calling code's assembly. As a rule, if you are allowed access in early-bound code, then you are also allowed access in late-bound code. + +> [!NOTE] +> Interfaces that extend other interfaces do not inherit the methods defined in the extended interfaces. + +## What types does a Type object represent? + +This class is thread safe; multiple threads can concurrently read from an instance of this type. An instance of the class can represent any of the following types: + +- Classes +- Value types +- Arrays +- Interfaces +- Enumerations +- Delegates +- Constructed generic types and generic type definitions +- Type arguments and type parameters of constructed generic types, generic type definitions, and generic method definitions + +## Retrieve a Type object + +The object associated with a particular type can be obtained in the following ways: + +- The instance method returns a object that represents the type of an instance. Because all managed types derive from , the method can be called on an instance of any type. + + The following example calls the method to determine the runtime type of each object in an object array. + + :::code language="csharp" source="~/snippets/csharp/System/Type/Overview/GetType1.cs" id="Snippet2"::: + :::code language="fsharp" source="~/snippets/fsharp/System/Type/Overview/GetType1.fs" id="Snippet2"::: + :::code language="vb" source="~/snippets/visualbasic/System/Type/Overview/GetType1.vb" id="Snippet2"::: + +- The static methods return a object that represents a type specified by its fully qualified name. + +- The , , and methods return `Type` objects that represent the types defined in a module. The first method can be used to obtain an array of objects for all the public and private types defined in a module. (You can obtain an instance of `Module` through the or method, or through the property.) + +- The object contains a number of methods to retrieve the classes defined in an assembly, including , , and . + +- The method returns a filtered list of interface types supported by a type. + +- The method returns a `Type` object that represents the element. + +- The and methods return objects representing the interface types supported by a type. + +- The method returns an array of objects representing the types specified by an arbitrary set of objects. The objects are specified with an array of type . + +- The and methods are provided for COM interoperability. They return a object that represents the type specified by a `ProgID` or `CLSID`. + +- The method is provided for interoperability. It returns a `Type` object that represents the type specified by a class handle. + +- The C# `typeof` operator, the C++ `typeid` operator, and the Visual Basic `GetType` operator obtain the `Type` object for a type. + +- The method returns a object representing a constructed generic type, which is an open constructed type if its property returns `true`, and a closed constructed type otherwise. A generic type can be instantiated only if it is closed. + +- The , , and methods return objects that represent, respectively, an array of a specified type, a pointer to a specified type, and the type of a reference parameter (`ref` in C#, 'byref' in F#, `ByRef` in Visual Basic). + +## Compare type objects for equality + +A object that represents a type is unique; that is, two object references refer to the same object if and only if they represent the same type. This allows for comparison of objects using reference equality. The following example compares the objects that represent a number of integer values to determine whether they are of the same type. + +:::code language="csharp" source="~/snippets/csharp/System/Type/Overview/Equals1.cs" id="Snippet3"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Type/Overview/Equals1.fs" id="Snippet3"::: +:::code language="vb" source="~/snippets/visualbasic/System/Type/Overview/Equals1.vb" id="Snippet3"::: + + ]]> + . The C# `typeof` operator (`GetType` operator in Visual Basic) is used to get a object representing . From this object, the method is used to get a representing the overload that takes a starting location and a length. @@ -7782,7 +7858,86 @@ In .NET 6 and earlier versions, the method doe The string containing the name of the public property to get. Searches for the public property with the specified name. An object representing the public property with the specified name, if found; otherwise, . - For more information about this API, see Supplemental API remarks for Type.GetProperty. + + | | (in Visual Basic, combine the values using ` Or `) to get it. +- If the current represents a constructed generic type, this method returns the with the type parameters replaced by the appropriate type arguments. +- If the current represents a type parameter in the definition of a generic type or generic method, this method searches the properties of the class constraint. + +## method + +The search for `name` is case-sensitive. The search includes public static and public instance properties. + +Situations in which occurs include the following: + +- A type contains two indexed properties that have the same name but different numbers of parameters. To resolve the ambiguity, use an overload of the method that specifies parameter types. +- A derived type declares a property that hides an inherited property with the same name, by using the `new` modifier (`Shadows` in Visual Basic). To resolve the ambiguity, use the method overload and add the flag to restrict the search to members that aren't inherited. + +## method + +The following filter flags can be used to define which properties to include in the search: + +- You must specify either `BindingFlags.Instance` or `BindingFlags.Static` in order to get a return. +- Specify `BindingFlags.Public` to include public properties in the search. +- Specify `BindingFlags.NonPublic` to include non-public properties (that is, private, internal, and protected properties) in the search. +- Specify `BindingFlags.FlattenHierarchy` to include `public` and `protected` static members up the hierarchy; `private` static members in inherited classes are not included. + +The following modifier flags can be used to change how the search works: + +- `BindingFlags.IgnoreCase` to ignore the case of `name`. +- `BindingFlags.DeclaredOnly` to search only the properties declared on the , not properties that were simply inherited. + +Situations in which occurs include the following: + +- A type contains two indexed properties that have the same name but different numbers of parameters. To resolve the ambiguity, use an overload of the method that specifies parameter types. +- A derived type declares a property that hides an inherited property with the same name, using the `new` modifier (`Shadows` in Visual Basic). To resolve the ambiguity, include to restrict the search to members that are not inherited. + +## [GetProperty(System.String, System.Reflection.BindingFlags, System.Reflection.Binder, System.Type, System.Type[], System.Reflection.ParameterModifier[])](xref:System.Type.GetProperty(System.String,System.Reflection.BindingFlags,System.Reflection.Binder,System.Type,System.Type[],System.Reflection.ParameterModifier[])) method + +Although the default binder does not process (the `modifiers` parameter), you can use the abstract class to write a custom binder that does process `modifiers`. `ParameterModifier` is only used when calling through COM interop, and only parameters that are passed by reference are handled. + +The following table shows what members of a base class are returned by the `Get` methods when reflecting on a type. + +| Member Type | Static | Non-Static | +|-------------|--------|----------------------------------------------------| +| Constructor | No | No | +| Field | No | Yes. A field is always hide-by-name-and-signature. | +| Event | Not applicable | The common type system rule is that the inheritance is the same as that of the methods that implement the property. Reflection treats properties as hide-by-name-and-signature.2 | +| Method | No | Yes. A method (both virtual and non-virtual) can be hide-by-name or hide-by-name-and-signature.| +| Nested Type | No | No | +| Property | Not applicable | The common type system rule is that the inheritance is the same as that of the methods that implement the property. Reflection treats properties as hide-by-name-and-signature.2 | + +Notes: + +- Hide-by-name-and-signature considers all of the parts of the signature, including custom modifiers, return types, parameter types, sentinels, and unmanaged calling conventions. This is a binary comparison. +- For reflection, properties and events are hide-by-name-and-signature. If you have a property with both a get and a set accessor in the base class, but the derived class has only a get accessor, the derived class property hides the base class property, and you will not be able to access the setter on the base class. +- Custom attributes are not part of the common type system. + +The following filter flags can be used to define which properties to include in the search: + +- You must specify either `BindingFlags.Instance` or `BindingFlags.Static` in order to get a return. +- Specify `BindingFlags.Public` to include public properties in the search. +- Specify `BindingFlags.NonPublic` to include non-public properties (that is, private, internal, and protected properties) in the search. +- Specify `BindingFlags.FlattenHierarchy` to include `public` and `protected` static members up the hierarchy; `private` static members in inherited classes are not included. + +The following modifier flags can be used to change how the search works: + +- `BindingFlags.IgnoreCase` to ignore the case of `name`. +- `BindingFlags.DeclaredOnly` to search only the properties declared on the , not properties that were simply inherited. + +## Indexers and default properties + +Visual Basic, C#, and C++ have simplified syntax for accessing indexed properties and allow one indexed property to be a default for its type. For example, if the variable `myList` refers to an , the syntax `myList[3]` (`myList(3)` in Visual Basic) retrieves the element with the index of 3. You can overload the property. + +In C#, this feature is called an indexer and cannot be referred to by name. By default, a C# indexer appears in metadata as an indexed property named `Item`. However, a class library developer can use the attribute to change the name of the indexer in the metadata. For example, the class has an indexer named . Indexed properties created using languages other than C# can have names other than `Item`, as well. + +To determine whether a type has a default property, use the method to test for the attribute. If the type has , the property returns the name of the default property. + + ]]> + An array of objects representing the attributes associated with the corresponding element in the array. The default binder does not process this parameter. Searches for the specified property whose parameters match the specified argument types and modifiers, using the specified binding constraints. An object representing the property that matches the specified requirements, if found; otherwise, . - For more information about this API, see Supplemental API remarks for Type.GetProperty. + + | | (in Visual Basic, combine the values using ` Or `) to get it. +- If the current represents a constructed generic type, this method returns the with the type parameters replaced by the appropriate type arguments. +- If the current represents a type parameter in the definition of a generic type or generic method, this method searches the properties of the class constraint. + +## method + +The search for `name` is case-sensitive. The search includes public static and public instance properties. + +Situations in which occurs include the following: + +- A type contains two indexed properties that have the same name but different numbers of parameters. To resolve the ambiguity, use an overload of the method that specifies parameter types. +- A derived type declares a property that hides an inherited property with the same name, by using the `new` modifier (`Shadows` in Visual Basic). To resolve the ambiguity, use the method overload and add the flag to restrict the search to members that aren't inherited. + +## method + +The following filter flags can be used to define which properties to include in the search: + +- You must specify either `BindingFlags.Instance` or `BindingFlags.Static` in order to get a return. +- Specify `BindingFlags.Public` to include public properties in the search. +- Specify `BindingFlags.NonPublic` to include non-public properties (that is, private, internal, and protected properties) in the search. +- Specify `BindingFlags.FlattenHierarchy` to include `public` and `protected` static members up the hierarchy; `private` static members in inherited classes are not included. + +The following modifier flags can be used to change how the search works: + +- `BindingFlags.IgnoreCase` to ignore the case of `name`. +- `BindingFlags.DeclaredOnly` to search only the properties declared on the , not properties that were simply inherited. + +Situations in which occurs include the following: + +- A type contains two indexed properties that have the same name but different numbers of parameters. To resolve the ambiguity, use an overload of the method that specifies parameter types. +- A derived type declares a property that hides an inherited property with the same name, using the `new` modifier (`Shadows` in Visual Basic). To resolve the ambiguity, include to restrict the search to members that are not inherited. + +## [GetProperty(System.String, System.Reflection.BindingFlags, System.Reflection.Binder, System.Type, System.Type[], System.Reflection.ParameterModifier[])](xref:System.Type.GetProperty(System.String,System.Reflection.BindingFlags,System.Reflection.Binder,System.Type,System.Type[],System.Reflection.ParameterModifier[])) method + +Although the default binder does not process (the `modifiers` parameter), you can use the abstract class to write a custom binder that does process `modifiers`. `ParameterModifier` is only used when calling through COM interop, and only parameters that are passed by reference are handled. + +The following table shows what members of a base class are returned by the `Get` methods when reflecting on a type. + +| Member Type | Static | Non-Static | +|-------------|--------|----------------------------------------------------| +| Constructor | No | No | +| Field | No | Yes. A field is always hide-by-name-and-signature. | +| Event | Not applicable | The common type system rule is that the inheritance is the same as that of the methods that implement the property. Reflection treats properties as hide-by-name-and-signature.2 | +| Method | No | Yes. A method (both virtual and non-virtual) can be hide-by-name or hide-by-name-and-signature.| +| Nested Type | No | No | +| Property | Not applicable | The common type system rule is that the inheritance is the same as that of the methods that implement the property. Reflection treats properties as hide-by-name-and-signature.2 | + +Notes: + +- Hide-by-name-and-signature considers all of the parts of the signature, including custom modifiers, return types, parameter types, sentinels, and unmanaged calling conventions. This is a binary comparison. +- For reflection, properties and events are hide-by-name-and-signature. If you have a property with both a get and a set accessor in the base class, but the derived class has only a get accessor, the derived class property hides the base class property, and you will not be able to access the setter on the base class. +- Custom attributes are not part of the common type system. + +The following filter flags can be used to define which properties to include in the search: + +- You must specify either `BindingFlags.Instance` or `BindingFlags.Static` in order to get a return. +- Specify `BindingFlags.Public` to include public properties in the search. +- Specify `BindingFlags.NonPublic` to include non-public properties (that is, private, internal, and protected properties) in the search. +- Specify `BindingFlags.FlattenHierarchy` to include `public` and `protected` static members up the hierarchy; `private` static members in inherited classes are not included. + +The following modifier flags can be used to change how the search works: + +- `BindingFlags.IgnoreCase` to ignore the case of `name`. +- `BindingFlags.DeclaredOnly` to search only the properties declared on the , not properties that were simply inherited. + +## Indexers and default properties + +Visual Basic, C#, and C++ have simplified syntax for accessing indexed properties and allow one indexed property to be a default for its type. For example, if the variable `myList` refers to an , the syntax `myList[3]` (`myList(3)` in Visual Basic) retrieves the element with the index of 3. You can overload the property. + +In C#, this feature is called an indexer and cannot be referred to by name. By default, a C# indexer appears in metadata as an indexed property named `Item`. However, a class library developer can use the attribute to change the name of the indexer in the metadata. For example, the class has an indexer named . Indexed properties created using languages other than C# can have names other than `Item`, as well. + +To determine whether a type has a default property, use the method to test for the attribute. If the type has , the property returns the name of the default property. + + ]]> + More than one property is found with the specified name and matching the specified binding constraints. is . @@ -9671,8 +9905,131 @@ Calling this method overload is the same as calling the . - For more information about this API, see [Supplemental API remarks for Type.GetType](/dotnet/fundamentals/runtime-libraries/system-type-gettype). - ]]> + Use the method overload and its associated overloads ( and ) to replace the default implementation of the method with more flexible implementations. By providing your own methods that resolve type names and the names of the assemblies that contain them, you can do the following: + +- Control which version of an assembly a type is loaded from. +- Provide another place to look for a type name that does not include an assembly name. +- Load assemblies using partial assembly names. +- Return subclasses of that are not created by the common language runtime (CLR). + +For example, in version-tolerant serialization this method enables you to search for a "best fit" assembly by using a partial name. Other overloads of the method require an assembly-qualified type name, which includes the version number. + +Alternate implementations of the type system may need to return subclasses of that are not created by the CLR; all types that are returned by other overloads of the method are runtime types. + +## Usage notes + +This method overload and its associated overloads parse `typeName` into the name of a type and the name of an assembly, and then resolve the names. Resolution of the assembly name occurs before resolution of the type name, because a type name must be resolved in the context of an assembly. + +> [!NOTE] +> If you are unfamiliar with the concept of assembly-qualified type names, see the property. + +If `typeName` is not an assembly-qualified name, assembly resolution is skipped. Unqualified type names can be resolved in the context of mscorlib.dll/System.Private.CoreLib.dll or the currently executing assembly, or you can optionally provide an assembly in the `typeResolver` parameter. The effects of including or omitting the assembly name for different kinds of name resolution are displayed as a table in the [Mixed name resolution](#mixed-name-resolution) section. + +General usage notes: + +- Do not pass methods to `assemblyResolver` or `typeResolver` if they come from unknown or untrusted callers. Use only methods that you provide or that you are familiar with. + + > [!CAUTION] + > Using methods from unknown or untrusted callers could result in elevation of privilege for malicious code. + +- If you omit the `assemblyResolver` and/or `typeResolver` parameters, the value of the `throwOnError` parameter is passed to the methods that perform the default resolution. + +- If `throwOnError` is `true`, this method throws a when `typeResolver` returns `null`, and a when `assemblyResolver` returns `null`. + +- This method does not catch exceptions thrown by `assemblyResolver` and `typeResolver`. You are responsible for any exceptions that are thrown by the resolver methods. + +### Resolve assemblies + +The `assemblyResolver` method receives an object, which is produced by parsing the string assembly name that is included in `typeName`. If `typeName` does not contain an assembly name, `assemblyResolver` is not called and `null` is passed to `typeResolver`. + +If `assemblyResolver` is not supplied, standard assembly probing is used to locate the assembly. If `assemblyResolver` is provided, the method does not do standard probing; in that case you must ensure that your `assemblyResolver` can handle all the assemblies you pass to it. + +The `assemblyResolver` method should return `null` if the assembly cannot be resolved. If `assemblyResolver` returns `null`, `typeResolver` is not called and no further processing occurs; additionally, if `throwOnError` is `true`, a is thrown. + +If the that is passed to `assemblyResolver` is a partial name, one or more of its parts are `null`. For example, if it has no version, the property is `null`. If the property, the property, and the method all return `null`, then only the simple name of the assembly was supplied. The `assemblyResolver` method can use or ignore all parts of the assembly name. + +The effects of different assembly resolution options are displayed as a table in the [Mixed name resolution](#mixed-name-resolution) section, for simple and assembly-qualified type names. + +### Resolve types + +If `typeName` does not specify an assembly name, `typeResolver` is always called. If `typeName` specifies an assembly name, `typeResolver` is called only when the assembly name is successfully resolved. If `assemblyResolver` or standard assembly probing returns `null`, `typeResolver` is not called. + +The `typeResolver` method receives three arguments: + +- The assembly to search or `null` if `typeName` does not contain an assembly name. +- The simple name of the type. In the case of a nested type, this is the outermost containing type. In the case of a generic type, this is the simple name of the generic type. +- A Boolean value that's `true` if the case of type names is to be ignored. + +The implementation determines the way these arguments are used. The `typeResolver` method should return `null` if it cannot resolve the type. If `typeResolver` returns `null` and `throwOnError` is `true`, this overload of throws a . + +The effects of different type resolution options are displayed as a table in the [Mixed name resolution](#mixed-name-resolution) section, for simple and assembly-qualified type names. + +#### Resolve nested types + +If `typeName` is a nested type, only the name of the outermost containing type is passed to `typeResolver`. When `typeResolver` returns this type, the method is called recursively until the innermost nested type has been resolved. + +#### Resolve generic types + +The is called recursively to resolve generic types: First to resolve the generic type itself, and then to resolve its type arguments. If a type argument is generic, is called recursively to resolve its type arguments, and so on. + +The combination of `assemblyResolver` and `typeResolver` that you provide must be capable of resolving all levels of this recursion. For example, suppose you supply an `assemblyResolver` that controls the loading of `MyAssembly`. Suppose you want to resolve the generic type `Dictionary` (`Dictionary(Of String, MyType)` in Visual Basic). You might pass the following generic type name: + +``` +"System.Collections.Generic.Dictionary`2[System.String,[MyNamespace.MyType, MyAssembly]]" +``` + +Notice that `MyType` is the only assembly-qualified type argument. The names of the and classes are not assembly-qualified. Your `typeResolver` must be able to handle either an assembly or `null`, because it will receive `null` for and . It can handle that case by calling an overload of the method that takes a string, because both of the unqualified type names are in mscorlib.dll/System.Private.CoreLib.dll: + +:::code language="csharp" source="~/snippets/csharp/System/Type/GetType/source.cs" id="Snippet1"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Type/GetType/source.fs" id="Snippet1"::: + +The `assemblyResolver` method is not called for the dictionary type and the string type, because those type names are not assembly-qualified. + +Now suppose that instead of `System.String`, the first generic argument type is `YourType`, from `YourAssembly`: + +``` +"System.Collections.Generic.Dictionary`2[[YourNamespace.YourType, YourAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null], [MyNamespace.MyType, MyAssembly]]" +``` + +Because this assembly is neither mscorlib.dll/System.Private.CoreLib.dll nor the currently executing assembly, you cannot resolve `YourType` without an assembly-qualified name. Because your `assemblyResolve` will be called recursively, it must be able to handle this case. Instead of returning `null` for assemblies other than `MyAssembly`, it now performs an assembly load using the supplied object. + +:::code language="csharp" source="~/snippets/csharp/System/Type/GetType/source.cs" id="Snippet2"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Type/GetType/source.fs" id="Snippet2"::: + +#### Resolve type names with special characters + +Certain characters have special meanings in assembly-qualified names. If a simple type name contains these characters, the characters cause parsing errors when the simple name is part of an assembly-qualified name. To avoid the parsing errors, you must escape the special characters with a backslash before you can pass the assembly-qualified name to the method. For example, if a type is named `Strange]Type`, the escape character must be added ahead of the square bracket as follows: `Strange\]Type`. + +> [!NOTE] +> Names with such special characters cannot be created in Visual Basic or C#, but can be created by using common intermediate language (CIL) or by emitting dynamic assemblies. + +The following table shows the special characters for type names. + +|Character|Meaning| +|---------------|-------------| +|`,` (comma)|Delimiter for assembly-qualified names.| +|`[]` (square brackets)|As a suffix pair, indicates an array type; as a delimiter pair, encloses generic argument lists and assembly-qualified names.| +|`&` (ampersand)|As a suffix, indicates that a type is a reference type.| +|`*` (asterisk)|As a suffix, indicates that a type is a pointer type.| +|`+` (plus)|Delimiter for nested types.| +|`\` (backslash)|Escape character.| + +Properties such as return correctly escaped strings. You must pass correctly escaped strings to the method. In turn, the method passes correctly escaped names to `typeResolver` and to the default type resolution methods. If you need to compare a name to an unescaped name in `typeResolver`, you must remove the escape characters. + +## Mixed name resolution + +The following table summarizes the interactions between `assemblyResolver`, `typeResolver`, and default name resolution, for all combinations of type name and assembly name in `typeName`: + +|Contents of type name|Assembly resolver method|Type resolver method|Result| +|---------------------------|------------------------------|--------------------------|------------| +|type, assembly|null|null|Equivalent to calling the method overload.| +|type, assembly|provided|null|`assemblyResolver` returns the assembly or returns `null` if it cannot resolve the assembly. If the assembly is resolved, the method overload is used to load the type from the assembly; otherwise, there is no attempt to resolve the type.| +|type, assembly|null|provided|Equivalent to converting the assembly name to an object and calling the method overload to get the assembly. If the assembly is resolved, it is passed to `typeResolver`; otherwise, `typeResolver` is not called and there is no further attempt to resolve the type.| +|type, assembly|provided|provided|`assemblyResolver` returns the assembly or returns `null` if it cannot resolve the assembly. If the assembly is resolved, it is passed to `typeResolver`; otherwise, `typeResolver` is not called and there is no further attempt to resolve the type.| +|type|null, provided|null|Equivalent to calling the method overload. Because the assembly name is not provided, only mscorlib.dll/System.Private.CoreLib.dll and the currently executing assembly are searched. If `assemblyResolver` is provided, it is ignored.| +|type|null, provided|provided|`typeResolver` is called, and `null` is passed for the assembly. `typeResolver` can provide a type from any assembly, including assemblies it loads for the purpose. If `assemblyResolver` is provided, it is ignored.| +|assembly|null, provided|null, provided|A is thrown, because the assembly name is parsed as if it were an assembly-qualified type name. This results in an invalid assembly name.| +]]> is . @@ -15922,7 +16279,68 @@ If the value of this property is `true` for an array type, it can be used to cre An array of types to be substituted for the type parameters of the current generic type. Substitutes the elements of an array of types for the type parameters of the current generic type definition and returns a object representing the resulting constructed type. A representing the constructed type formed by substituting the elements of for the type parameters of the current generic type. - For more information about this API, see Supplemental API remarks for Type.MakeGenericType. + + method allows you to write code that assigns specific types to the type parameters of a generic type definition, thus creating a object that represents a particular constructed type. You can use this object to create runtime instances of the constructed type. + +Types constructed with can be open, that is, some of their type arguments can be type parameters of enclosing generic methods or types. You might use such open constructed types when you emit dynamic assemblies. For example, consider the classes `Base` and `Derived` in the following code. + +:::code language="csharp" source="~/snippets/csharp/System/Type/MakeGenericType/remarks.cs" id="Snippet1"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Type/MakeGenericType/remarks.fs" id="Snippet1"::: +:::code language="vb" source="~/snippets/visualbasic/System/Type/MakeGenericType/remarks.vb" id="Snippet1"::: + +To generate `Derived` in a dynamic assembly, it is necessary to construct its base type. To do this, call the method on a object representing the class `Base`, using the generic type arguments and the type parameter `V` from `Derived`. Because types and generic type parameters are both represented by objects, an array containing both can be passed to the method. + +> [!NOTE] +> A constructed type such as `Base` is useful when emitting code, but you cannot call the method on this type because it is not a generic type definition. To create a closed constructed type that can be instantiated, first call the method to get a object representing the generic type definition and then call with the desired type arguments. + +The object returned by is the same as the obtained by calling the method of the resulting constructed type, or the method of any constructed type that was created from the same generic type definition using the same type arguments. + +> [!NOTE] +> An array of generic types is not itself a generic type. You cannot call on an array type such as `C[]` (`Dim ac() As C(Of T)` in Visual Basic). To construct a closed generic type from `C[]`, call to obtain the generic type definition `C`; call on the generic type definition to create the constructed type; and finally call the method on the constructed type to create the array type. The same is true of pointer types and `ref` types (`ByRef` in Visual Basic). + +For a list of the invariant conditions for terms used in generic reflection, see the property remarks. + +## Nested types + +If a generic type is defined using C#, C++, or Visual Basic, then its nested types are all generic. This is true even if the nested types have no type parameters of their own, because all three languages include the type parameters of enclosing types in the type parameter lists of nested types. Consider the following classes: + +:::code language="csharp" source="~/snippets/csharp/System/Type/MakeGenericType/remarks.cs" id="Snippet2"::: +:::code language="vb" source="~/snippets/visualbasic/System/Type/MakeGenericType/remarks.vb" id="Snippet2"::: + +The type parameter list of the nested class `Inner` has two type parameters, `T` and `U`, the first of which is the type parameter of its enclosing class. Similarly, the type parameter list of the nested class `Innermost1` has three type parameters, `T`, `U`, and `V`, with `T` and `U` coming from its enclosing classes. The nested class `Innermost2` has two type parameters, `T` and `U`, which come from its enclosing classes. + +If the parameter list of the enclosing type has more than one type parameter, all the type parameters in order are included in the type parameter list of the nested type. + +To construct a generic type from the generic type definition for a nested type, call the method with the array formed by concatenating the type argument arrays of all the enclosing types, beginning with the outermost generic type, and ending with the type argument array of the nested type itself, if it has type parameters of its own. To create an instance of `Innermost1`, call the method with an array containing three types, to be assigned to T, U, and V. To create an instance of `Innermost2`, call the method with an array containing two types, to be assigned to T and U. + +The languages propagate the type parameters of enclosing types in this fashion so you can use the type parameters of an enclosing type to define fields of nested types. Otherwise, the type parameters would not be in scope within the bodies of the nested types. It is possible to define nested types without propagating the type parameters of enclosing types, by emitting code in dynamic assemblies or by using the [Ilasm.exe (IL Assembler)](/dotnet/framework/tools/ilasm-exe-il-assembler). Consider the following code for the CIL assembler: + +```msil +.class public Outer { + .class nested public Inner { + .class nested public Innermost { + } + } +} +``` + +In this example, it is not possible to define a field of type `T` or `U` in class `Innermost`, because those type parameters are not in scope. The following assembler code defines nested classes that behave the way they would if defined in C++, Visual Basic, and C#: + +```msil +.class public Outer { + .class nested public Inner { + .class nested public Innermost { + } + } +} +``` + +You can use the [Ildasm.exe (IL Disassembler)](/dotnet/framework/tools/ildasm-exe-il-disassembler) to examine nested classes defined in the high-level languages and observe this naming scheme. + + ]]> + method to create a constructed type from the generic type definition for the type. The constructed type represents a of `Test` objects with string keys. diff --git a/xml/System/TypeInitializationException.xml b/xml/System/TypeInitializationException.xml index db33546c046..fe0d550654f 100644 --- a/xml/System/TypeInitializationException.xml +++ b/xml/System/TypeInitializationException.xml @@ -61,7 +61,116 @@ The exception that is thrown as a wrapper around the exception thrown by the class initializer. This class cannot be inherited. - For more information about this API, see Supplemental API remarks for TypeInitializationException. + + is created and passed a reference to the exception thrown by the type's class initializer. The property of holds the underlying exception. + +Typically, the exception reflects a catastrophic condition (the runtime is unable to instantiate a type) that prevents an application from continuing. Most commonly, the is thrown in response to some change in the executing environment of the application. Consequently, other than possibly for troubleshooting debug code, the exception should not be handled in a `try`/`catch` block. Instead, the cause of the exception should be investigated and eliminated. + + uses the HRESULT `COR_E_TYPEINITIALIZATION`, which has the value 0x80131534. + +For a list of initial property values for an instance of , see the constructors. + +The following sections describe some of the situations in which a exception is thrown. + +## Static constructors + +A static constructor, if one exists, is called automatically by the runtime before creating a new instance of a type. Static constructors can be explicitly defined by a developer. If a static constructor is not explicitly defined, compilers automatically create one to initialize any `static` (in C# or F#) or `Shared` (in Visual Basic) members of the type. For more information on static constructors, see [Static Constructors](/dotnet/csharp/programming-guide/classes-and-structs/static-constructors). + +Most commonly, a exception is thrown when a static constructor is unable to instantiate a type. The property indicates why the static constructor was unable to instantiate the type. Some of the more common causes of a exception are: + +- An unhandled exception in a static constructor + + If an exception is thrown in a static constructor, that exception is wrapped in a exception, and the type cannot be instantiated. + + What often makes this exception difficult to troubleshoot is that static constructors are not always explicitly defined in source code. A static constructor exists in a type if: + + - It has been explicitly defined as a member of a type. + + - The type has `static` (in C# or F#) or `Shared` (in Visual Basic) variables that are declared and initialized in a single statement. In this case, the language compiler generates a static constructor for the type. For instance, when the C# and VB compilers compile the following example, they generate the IL for a static constructor that is similar to this: + + ```il + .method private specialname rtspecialname static + void .cctor() cil managed + { + // Code size 12 (0xc) + .maxstack 8 + IL_0000: ldc.i4.3 + IL_0001: newobj instance void TestClass::.ctor(int32) + IL_0006: stsfld class TestClass Example::test + IL_000b: ret + } // end of method Example::.cctor + ``` + + The following example shows a exception thrown by a compiler-generated static constructor. The `Example` class includes a `static` (in C#) or `Shared` (in Visual Basic) field of type `TestClass` that is instantiated by passing a value of 3 to its class constructor. That value, however, is illegal; only values of 0 or 1 are permitted. As a result, the `TestClass` class constructor throws an . Since this exception is not handled, it is wrapped in a exception. + + :::code language="csharp" source="~/snippets/csharp/System/TypeInitializationException/Overview/ctorException1.cs" id="Snippet3"::: + :::code language="vb" source="~/snippets/visualbasic/System/TypeInitializationException/Overview/CtorException1.vb" id="Snippet3"::: + + The exception message displays information about the property. + +- A missing assembly or data file + + A common cause of a exception is that an assembly or data file that was present in an application's development and test environments is missing from its runtime environment. For example, you can compile the following example to an assembly named Missing1a.dll by using this command-line syntax: + + ```csharp + csc -t:library Missing1a.cs + ``` + + ```fsharp + fsc --target:library Missing1a.fs + ``` + + ```vb + vbc Missing1a.vb -t:library + ``` + + :::code language="csharp" source="~/snippets/csharp/System/TypeInitializationException/Overview/Missing1a.cs" id="Snippet1"::: + :::code language="fsharp" source="~/snippets/fsharp/System/TypeInitializationException/Overview/Missing1a.fs" id="Snippet1"::: + :::code language="vb" source="~/snippets/visualbasic/System/TypeInitializationException/Overview/Missing1a.vb" id="Snippet1"::: + + You can then compile the following example to an executable named Missing1.exe by including a reference to Missing1a.dll: + + ```csharp + csc Missing1.cs /r:Missing1a.dll + ``` + + ```vb + vbc Missing1.vb /r:Missing1a.dll + ``` + + However, if you rename, move, or delete Missing1a.dll and run the example, it throws a exception and displays the output shown in the example. Note that the exception message includes information about the property. In this case, the inner exception is a that is thrown because the runtime cannot find the dependent assembly. + + :::code language="csharp" source="~/snippets/csharp/System/TypeInitializationException/Overview/Missing1.cs" id="Snippet2"::: + :::code language="fsharp" source="~/snippets/fsharp/System/TypeInitializationException/Overview/Missing1.fs" id="Snippet2"::: + :::code language="vb" source="~/snippets/visualbasic/System/TypeInitializationException/Overview/Missing1.vb" id="Snippet2"::: + + > [!NOTE] + > In this example, a exception was thrown because an assembly could not be loaded. The exception can also be thrown if a static constructor attempts to open a data file, such as a configuration file, an XML file, or a file containing serialized data, that it cannot find. + +## Regular expression match timeout values + +You can set the default timeout value for a regular expression pattern matching operation on a per-application domain basis. The timeout is defined by a specifying a value for the "REGEX_DEFAULT_MATCH_TIMEOUT" property to the method. The time interval must be a valid object that is greater than zero and less than approximately 24 days. If these requirements are not met, the attempt to set the default timeout value throws an , which in turn is wrapped in a exception. + +The following example shows the that is thrown when the value assigned to the "REGEX_DEFAULT_MATCH_TIMEOUT" property is invalid. To eliminate the exception, set the"REGEX_DEFAULT_MATCH_TIMEOUT" property to a value that is greater than zero and less than approximately 24 days. + +:::code language="csharp" source="~/snippets/csharp/System/TypeInitializationException/Overview/Regex1.cs" id="Snippet4"::: +:::code language="fsharp" source="~/snippets/fsharp/System/TypeInitializationException/Overview/Regex1.fs" id="Snippet4"::: +:::code language="vb" source="~/snippets/visualbasic/System/TypeInitializationException/Overview/Regex1.vb" id="Snippet4"::: + +## Calendars and cultural data + +If you attempt to instantiate a calendar but the runtime is unable to instantiate the object that corresponds to that calendar, it throws a exception. This exception can be thrown by the following calendar class constructors: + +- The parameterless constructor of the class. +- The parameterless constructor of the class. +- The parameterless constructor of the class. + +Since cultural data for these cultures should be available on all systems, you should rarely, if ever, encounter this exception. + + ]]> + Handling and throwing exceptions in .NET diff --git a/xml/System/Uri.xml b/xml/System/Uri.xml index dcd4428aa3d..3bcf5e86f49 100644 --- a/xml/System/Uri.xml +++ b/xml/System/Uri.xml @@ -84,7 +84,127 @@ Provides an object representation of a uniform resource identifier (URI) and easy access to the parts of the URI. - For more information about this API, see Supplemental API remarks for Uri. + + class defines the properties and methods for handling URIs, including parsing, comparing, and combining. The class properties are read-only; to create a modifiable object, use the class. + +Relative URIs (for example, "/new/index.htm") must be expanded with respect to a base URI so that they are absolute. The method is provided to convert absolute URIs to relative URIs when necessary. + +The constructors do not escape URI strings if the string is a well-formed URI including a scheme identifier. + +The properties return a canonical data representation in escaped encoding, with all characters with Unicode values greater than 127 replaced with their hexadecimal equivalents. To put the URI in canonical form, the constructor performs the following steps: + +- Converts the URI scheme to lowercase. +- Converts the host name to lowercase. +- If the host name is an IPv6 address, the canonical IPv6 address is used. ScopeId and other optional IPv6 data are removed. +- Removes default and empty port numbers. +- Converts implicit file paths without the file:// scheme (for example, "C:\my\file") to explicit file paths with the file:// scheme. +- Escaped characters (also known as percent-encoded octets) that don't have a reserved purpose are decoded (also known as being unescaped). These unreserved characters include uppercase and lowercase letters (%41-%5A and %61-%7A), decimal digits (%30-%39), hyphen (%2D), period (%2E), underscore (%5F), and tilde (%7E). +- Canonicalizes the path for hierarchical URIs by compacting sequences such as `/./` and `/../` (whether or not the sequence is escaped). Note that there are some schemes for which these sequences are not compacted. +- For hierarchical URIs, if the host is not terminated with a forward slash (/), one is added. +- By default, any reserved characters in the URI are escaped in accordance with RFC 2396. This behavior changes if International Resource Identifiers or International Domain Name parsing is enabled in which case reserved characters in the URI are escaped in accordance with RFC 3986 and RFC 3987. + +As part of canonicalization in the constructor for some schemes, dot-segments (`/./` and `/../`) are compacted (in other words, they're removed). The schemes for which compacts segments include http, https, tcp, net.pipe, and net.tcp. For some other schemes, these sequences are not compacted. The following code snippet shows how compacting looks in practice. The escaped sequences are unescaped, if necessary, and then compacted. + +```csharp +var uri = new Uri("http://myUrl/../.."); // http scheme, unescaped +OR +var uri = new Uri("http://myUrl/%2E%2E/%2E%2E"); // http scheme, escaped +OR +var uri = new Uri("ftp://myUrl/../.."); // ftp scheme, unescaped +OR +var uri = new Uri("ftp://myUrl/%2E%2E/%2E%2E"); // ftp scheme, escaped + +Console.WriteLine($"AbsoluteUri: {uri.AbsoluteUri}"); +Console.WriteLine($"PathAndQuery: {uri.PathAndQuery}"); +``` + +When this code executes, it returns output similar to the following text. + +```output +AbsoluteUri: http://myurl/ +PathAndQuery: / +``` + +You can transform the contents of the class from an escape encoded URI reference to a readable URI reference by using the method. Note that some reserved characters might still be escaped in the output of the method. This is to support unambiguous reconstruction of a URI from the value returned by . + +Some URIs include a fragment identifier or a query or both. A fragment identifier is any text that follows a number sign (#), not including the number sign; the fragment text is stored in the property. Query information is any text that follows a question mark (?) in the URI; the query text is stored in the property. + +> [!NOTE] +> The URI class supports the use of IP addresses in both quad-notation for IPv4 protocol and colon-hexadecimal for IPv6 protocol. Remember to enclose the IPv6 address in square brackets, as in http://[::1]. + +## International resource identifier support + +Web addresses are typically expressed using URIs that consist of a very restricted set of characters: + +- Upper and lower case ASCII letters from the English alphabet. +- Digits from 0 to 9. +- A small number of other ASCII symbols. + +The specifications for URIs are documented in RFC 2396, RFC 2732, RFC 3986, and RFC 3987 published by the Internet Engineering Task Force (IETF). + +Identifiers that facilitate the need to identify resources using languages other than English and allow non-ASCII characters (characters in the Unicode/ISO 10646 character set) are known as International Resource Identifiers (IRIs). The specifications for IRIs are documented in RFC 3987 published by IETF. Using IRIs allows a URL to contain Unicode characters. Normalization and character checking are done according to the latest IRI rules in RFC 3986 and RFC 3987. + +IRI and IDN processing in the class can be controlled using the , , and configuration setting classes. The setting enables or disables IRI processing in the class. The setting enables or disables IDN processing in the class. + +The configuration setting for the and are read once when the first class is constructed. Changes to configuration settings after that time are ignored. + +The class has also been extended to allow creating a customizable parser that supports IRI and IDN. The behavior of a object is specified by passing a bitwise combination of the values available in the enumeration to the constructor. The type indicates the parser supports the parsing rules specified in RFC 3987 for International Resource Identifiers (IRI). + +The type indicates that the parser supports Internationalized Domain Name (IDN) parsing of host names. In .NET (Core) and .NET Framework 4.5+, IDN is always used. In previous versions, a configuration option determines whether IDN is used. + +## Implicit file path support + + can also be used to represent local file system paths. These paths can be represented *explicitly* in URIs that begin with the file:// scheme, and *implicitly* in URIs that do not have the file:// scheme. As a concrete example, the following two URIs are both valid, and represent the same file path: + +```csharp +Uri uri1 = new Uri("C:/test/path/file.txt") // Implicit file path. +Uri uri2 = new Uri("file:///C:/test/path/file.txt") // Explicit file path. +``` + +These implicit file paths are not compliant with the URI specification and should be avoided when possible. When using .NET Core on Unix-based systems, implicit file paths can be especially problematic, because an absolute implicit file path is *indistinguishable* from a relative path. When such ambiguity is present, default to interpreting the path as an absolute URI. + +## Security considerations + +Because of security concerns, your application should use caution when accepting instances from untrusted sources and with `dontEscape` set to `true` in the [constructor](xref:System.Uri.%23ctor(System.String,System.Boolean)). You can check a URI string for validity by calling the method. + +When dealing with untrusted user input, confirm assumptions about the newly created `Uri` instance before trusting its properties. +This can be done in the following way: + +```csharp +string userInput = ...; + +Uri baseUri = new Uri("https://myWebsite/files/"); + +if (!Uri.TryCreate(baseUri, userInput, out Uri newUri)) +{ + // Fail: invalid input. +} + +if (!baseUri.IsBaseOf(newUri)) +{ + // Fail: the Uri base has been modified - the created Uri is not rooted in the original directory. +} +``` + +This validation can be used in other cases, like when dealing with UNC paths, by simply changing the `baseUri`: + +```csharp +Uri baseUri = new Uri(@"\\host\share\some\directory\name\"); +``` + +For more details about the design and security considerations of and , review the following threat model documents: + +- [System.Uri threat model](https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.Uri/docs/System.Uri%20Threat%20Model.md) +- [System.UriBuilder threat model](https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.Uri/docs/System.UriBuilder%20Threat%20Model.md) + +## Performance considerations + +If you use a *Web.config* file that contains URIs to initialize your application, additional time is required to process the URIs if their scheme identifiers are nonstandard. In such a case, initialize the affected parts of your application when the URIs are needed, not at start time. + + ]]> + class and uses it to perform a GET request with . diff --git a/xml/System/Version.xml b/xml/System/Version.xml index 138e0cfaa80..3b515c50461 100644 --- a/xml/System/Version.xml +++ b/xml/System/Version.xml @@ -96,7 +96,78 @@ Represents the version number of an assembly, operating system, or the common language runtime. This class cannot be inherited. - For more information about this API, see Supplemental API remarks for Version. + + class represents the version number of an assembly, operating system, or the common language runtime. Version numbers consist of two to four components: major, minor, build, and revision. The major and minor components are required; the build and revision components are optional, but the build component is required if the revision component is defined. All defined components must be integers greater than or equal to 0. The format of the version number is as follows (optional components are shown in square brackets): + +*major*.*minor*[.*build*[.*revision*]] + +The components are used by convention as follows: + +- *Major*: Assemblies with the same name but different major versions are not interchangeable. A higher version number might indicate a major rewrite of a product where backward compatibility cannot be assumed. + +- *Minor*: If the name and major version number on two assemblies are the same, but the minor version number is different, this indicates significant enhancement with the intention of backward compatibility. This higher minor version number might indicate a point release of a product or a fully backward-compatible new version of a product. + +- *Build*: A difference in build number represents a recompilation of the same source. Different build numbers might be used when the processor, platform, or compiler changes. + +- *Revision*: Assemblies with the same name, major, and minor version numbers but different revisions are intended to be fully interchangeable. A higher revision number might be used in a build that fixes a security hole in a previously released assembly. + +Subsequent versions of an assembly that differ only by build or revision numbers are considered to be Hotfix updates of the prior version. + +> [!IMPORTANT] +> The value of properties that have not been explicitly assigned a value is undefined (-1). + +The and properties enable you to identify a temporary version of your application that, for example, corrects a problem until you can release a permanent solution. Furthermore, the Windows NT operating system uses the property to encode the service pack number. + +## Assign version information to assemblies + +Ordinarily, the class is not used to assign a version number to an assembly. Instead, the class is used to define an assembly's version, as illustrated by the example in this article. + +## Retrieve version information + + objects are most frequently used to store version information about some system or application component (such as the operating system), the common language runtime, the current application's executable, or a particular assembly. The following examples illustrate some of the most common scenarios: + +- Retrieving the operating system version. The following example uses the property to retrieve the version number of the operating system. + + :::code language="csharp" source="~/snippets/csharp/System/Version/Overview/GettingVersions1.cs" id="Snippet1"::: + :::code language="fsharp" source="~/snippets/fsharp/System/Version/Overview/GettingVersions1.fs" id="Snippet1"::: + :::code language="vb" source="~/snippets/visualbasic/System/Version/Overview/GettingVersions1.vb" id="Snippet1"::: + +- Retrieving the version of the common language runtime. The following example uses the property to retrieve version information about the common language runtime. + + :::code language="csharp" source="~/snippets/csharp/System/Version/Overview/GettingVersions1.cs" id="Snippet2"::: + :::code language="fsharp" source="~/snippets/fsharp/System/Version/Overview/GettingVersions1.fs" id="Snippet2"::: + :::code language="vb" source="~/snippets/visualbasic/System/Version/Overview/GettingVersions1.vb" id="Snippet2"::: + +- Retrieving the current application's assembly version. The following example uses the method to obtain a reference to an object that represents the application executable and then retrieves its assembly version number. + + :::code language="csharp" source="~/snippets/csharp/System/Version/Overview/currentapp.cs" id="Snippet5"::: + :::code language="fsharp" source="~/snippets/fsharp/System/Version/Overview/currentapp.fs" id="Snippet5"::: + :::code language="vb" source="~/snippets/visualbasic/System/Version/Overview/currentapp.vb" id="Snippet5"::: + +- Retrieving the current assembly's assembly version. The following example uses the property to obtain a reference to an object that represents the assembly that contains the application entry point, and then retrieves its version information. + + :::code language="csharp" source="~/snippets/csharp/System/Version/Overview/currentassem.cs" id="Snippet4"::: + :::code language="fsharp" source="~/snippets/fsharp/System/Version/Overview/currentassem.fs" id="Snippet4"::: + :::code language="vb" source="~/snippets/visualbasic/System/Version/Overview/currentassem.vb" id="Snippet4"::: + +## Compare version objects + +You can use the method to determine whether one object is earlier than, the same as, or later than a second object. The following example indicates that Version 2.1 is later than Version 2.0. + +:::code language="csharp" source="~/snippets/csharp/System/Version/Overview/comparisons1.cs" id="Snippet1"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Version/Overview/comparisons1.fs" id="Snippet1"::: +:::code language="vb" source="~/snippets/visualbasic/System/Version/Overview/comparisons1.vb" id="Snippet1"::: + +For two versions to be equal, the major, minor, build, and revision numbers of the first object must be identical to those of the second object. If the build or revision number of a object is undefined, that object is considered to be earlier than a object whose build or revision number is equal to zero. The following example illustrates this by comparing three objects that have undefined version components. + +:::code language="csharp" source="~/snippets/csharp/System/Version/Overview/comparisons2.cs" id="Snippet2"::: +:::code language="fsharp" source="~/snippets/fsharp/System/Version/Overview/comparisons2.fs" id="Snippet2"::: +:::code language="vb" source="~/snippets/visualbasic/System/Version/Overview/comparisons2.vb" id="Snippet2"::: + + ]]> + attribute to assign a version number to an assembly. At compile time, this version information is stored with the assembly's metadata. At run time, the example retrieves the value of the property on a type found in the assembly to get a reference to the executing assembly, and it retrieves the assembly's version information from the property of the object returned by the method.