Formatting is the process of converting an instance of a class or structure, or an enumeration value, to a string representation. The purpose is to display the resulting string to users or to deserialize it later to restore the original data type. This article introduces the formatting mechanisms that .NET provides.
The basic mechanism for formatting is the default implementation of the System.Object.ToString method, which is discussed in the Default Formatting Using the ToString Method section later in this article. However, .NET provides several ways to modify and extend its default formatting support. These include the following:
Overriding the System.Object.ToString method to define a custom string representation of an object's value. For more information, see the Override the ToString Method section later in this article.
Defining format specifiers that enable the string representation of an object's value to take multiple forms. For example, the "X" format specifier in the following statement converts an integer to the string representation of a hexadecimal value.
sample · csharpsamples/snippets/csharp/VS_Snippets_CLR/conceptual.formatting.overview/cs/specifier1.cs3
using System; public class Example15 { public static void Main() { // <Snippet3> int integerValue = 60312; Console.WriteLine(integerValue.ToString("X")); // Displays EB98. // </Snippet3> // <Snippet10> double cost = 1632.54; Console.WriteLine(cost.ToString("C", new System.Globalization.CultureInfo("en-US"))); // The example displays the following output: // $1,632.54 // </Snippet10> } }sample · vbsamples/snippets/visualbasic/VS_Snippets_CLR/conceptual.formatting.overview/vb/specifier1.vb3
' Visual Basic .NET Document Option Strict On Module Example16 Public Sub Main16() ' <Snippet3> Dim integerValue As Integer = 60312 Console.WriteLine(integerValue.ToString("X")) ' Displays EB98. ' </Snippet3> ' <Snippet10> Dim cost As Double = 1632.54 Console.WriteLine(cost.ToString("C", New System.Globalization.CultureInfo("en-US"))) ' The example displays the following output: ' $1,632.54 ' </Snippet10> End Sub End ModuleFor more information about format specifiers, see the ToString Method and Format Strings section.
Using format providers to implement the formatting conventions of a specific culture. For example, the following statement displays a currency value by using the formatting conventions of the en-US culture.
sample · csharpsamples/snippets/csharp/VS_Snippets_CLR/conceptual.formatting.overview/cs/specifier1.cs10
using System; public class Example15 { public static void Main() { // <Snippet3> int integerValue = 60312; Console.WriteLine(integerValue.ToString("X")); // Displays EB98. // </Snippet3> // <Snippet10> double cost = 1632.54; Console.WriteLine(cost.ToString("C", new System.Globalization.CultureInfo("en-US"))); // The example displays the following output: // $1,632.54 // </Snippet10> } }sample · vbsamples/snippets/visualbasic/VS_Snippets_CLR/conceptual.formatting.overview/vb/specifier1.vb10
' Visual Basic .NET Document Option Strict On Module Example16 Public Sub Main16() ' <Snippet3> Dim integerValue As Integer = 60312 Console.WriteLine(integerValue.ToString("X")) ' Displays EB98. ' </Snippet3> ' <Snippet10> Dim cost As Double = 1632.54 Console.WriteLine(cost.ToString("C", New System.Globalization.CultureInfo("en-US"))) ' The example displays the following output: ' $1,632.54 ' </Snippet10> End Sub End ModuleFor more information about formatting with format providers, see the Format Providers section.
Implementing the System.IFormattable interface to support both string conversion with the System.Convert class and composite formatting. For more information, see the IFormattable Interface section.
Using composite formatting to embed the string representation of a value in a larger string. For more information, see the Composite Formatting section.
Using string interpolation, a more readable syntax to embed the string representation of a value in a larger string. For more information, see String interpolation.
Implementing System.ICustomFormatter and System.IFormatProvider to provide a complete custom formatting solution. For more information, see the Custom Formatting with ICustomFormatter section.
The following sections examine these methods for converting an object to its string representation.
Default formatting using the ToString method
Every type that is derived from System.Object automatically inherits a parameterless ToString method, which returns the name of the type by default. The following example illustrates the default ToString method. It defines a class named Automobile that has no implementation. When the class is instantiated and its ToString method is called, it displays its type name. The ToString method isn't explicitly called in the example. The System.Console.WriteLine%28System.Object%29 method implicitly calls the ToString method of the object passed to it as an argument.
sample · csharpsamples/snippets/csharp/VS_Snippets_CLR/conceptual.formatting.overview/cs/default1.cs1
// <Snippet1>
using System;
public class Automobile
{
// No implementation. All members are inherited from Object.
}
public class Example9
{
public static void Main()
{
Automobile firstAuto = new Automobile();
Console.WriteLine(firstAuto);
}
}
// The example displays the following output:
// Automobile
// </Snippet1>sample · vbsamples/snippets/visualbasic/VS_Snippets_CLR/conceptual.formatting.overview/vb/default1.vb1
' Visual Basic .NET Document
Option Strict On
' <Snippet1>
Public Class Automobile
' No implementation. All members are inherited from Object.
End Class
Module Example9
Public Sub Main9()
Dim firstAuto As New Automobile()
Console.WriteLine(firstAuto)
End Sub
End Module
' The example displays the following output:
' Automobile
' </Snippet1>Because all types other than interfaces are derived from System.Object, this functionality is automatically provided to your custom classes or structures. However, the functionality offered by the default ToString method, is limited: Although it identifies the type, it fails to provide any information about an instance of the type. To provide a string representation of an object that provides information about that object, you must override the ToString method.
Override the ToString method
Displaying the name of a type is often of limited use and doesn't allow consumers of your types to differentiate one instance from another. However, you can override the ToString method to provide a more useful representation of an object's value. The following example defines a Temperature object and overrides its ToString method to display the temperature in degrees Celsius.
sample · csharpsamples/snippets/csharp/VS_Snippets_CLR/conceptual.formatting.overview/cs/overrides1.cs2
namespace HotAndCold2
{
// <Snippet2>
public class Temperature
{
private decimal temp;
public Temperature(decimal temperature)
{
this.temp = temperature;
}
public override string ToString()
{
return this.temp.ToString("N1") + "°C";
}
}
public class Example12
{
public static void Main()
{
Temperature currentTemperature = new Temperature(23.6m);
Console.WriteLine($"The current temperature is {currentTemperature}");
}
}
// The example displays the following output:
// The current temperature is 23.6°C.
// </Snippet2>
}sample · vbsamples/snippets/visualbasic/VS_Snippets_CLR/conceptual.formatting.overview/vb/overrides1.vb2
' Visual Basic .NET Document
Option Strict On
' <Snippet2>
Public Class Temperature
Private temp As Decimal
Public Sub New(temperature As Decimal)
Me.temp = temperature
End Sub
Public Overrides Function ToString() As String
Return Me.temp.ToString("N1") + "°C"
End Function
End Class
Module Example13
Public Sub Main13()
Dim currentTemperature As New Temperature(23.6D)
Console.WriteLine("The current temperature is " +
currentTemperature.ToString())
End Sub
End Module
' The example displays the following output:
' The current temperature is 23.6°C.
' </Snippet2>In .NET, the ToString method of each primitive value type has been overridden to display the object's value instead of its name. The following table shows the override for each primitive type. Most of the overridden methods call another overload of the ToString method and pass it the "G" format specifier, which defines the general format for its type, and an System.IFormatProvider object that represents the current culture.
| Type | ToString override |
|---|---|
| System.Boolean | Returns either System.Boolean.TrueString or System.Boolean.FalseString. |
| System.Byte | Calls Byte.ToString("G", NumberFormatInfo.CurrentInfo) to format the System.Byte value for the current culture. |
| System.Char | Returns the character as a string. |
| System.DateTime | Calls DateTime.ToString("G", DatetimeFormatInfo.CurrentInfo) to format the date and time value for the current culture. |
| System.Decimal | Calls Decimal.ToString("G", NumberFormatInfo.CurrentInfo) to format the System.Decimal value for the current culture. |
| System.Double | Calls Double.ToString("G", NumberFormatInfo.CurrentInfo) to format the System.Double value for the current culture. |
| System.Int16 | Calls Int16.ToString("G", NumberFormatInfo.CurrentInfo) to format the System.Int16 value for the current culture. |
| System.Int32 | Calls Int32.ToString("G", NumberFormatInfo.CurrentInfo) to format the System.Int32 value for the current culture. |
| System.Int64 | Calls Int64.ToString("G", NumberFormatInfo.CurrentInfo) to format the System.Int64 value for the current culture. |
| System.SByte | Calls SByte.ToString("G", NumberFormatInfo.CurrentInfo) to format the System.SByte value for the current culture. |
| System.Single | Calls Single.ToString("G", NumberFormatInfo.CurrentInfo) to format the System.Single value for the current culture. |
| System.UInt16 | Calls UInt16.ToString("G", NumberFormatInfo.CurrentInfo) to format the System.UInt16 value for the current culture. |
| System.UInt32 | Calls UInt32.ToString("G", NumberFormatInfo.CurrentInfo) to format the System.UInt32 value for the current culture. |
| System.UInt64 | Calls UInt64.ToString("G", NumberFormatInfo.CurrentInfo) to format the System.UInt64 value for the current culture. |
The ToString method and format strings
Relying on the default ToString method or overriding ToString is appropriate when an object has a single string representation. However, the value of an object often has multiple representations. For example, a temperature can be expressed in degrees Fahrenheit, degrees Celsius, or kelvins. Similarly, the integer value 10 can be represented in numerous ways, including 10, 10.0, 1.0e01, or $10.00.
To enable a single value to have multiple string representations, .NET uses format strings. A format string is a string that contains one or more predefined format specifiers, which are single characters or groups of characters that define how the ToString method should format its output. The format string is then passed as a parameter to the object's ToString method and determines how the string representation of that object's value should appear.
All numeric types, date and time types, and enumeration types in .NET support a predefined set of format specifiers. You can also use format strings to define multiple string representations of your application-defined data types.
Standard format strings
A standard format string contains a single format specifier, which is an alphabetic character that defines the string representation of the object to which it's applied, along with an optional precision specifier that affects how many digits are displayed in the result string. If the precision specifier is omitted or isn't supported, a standard format specifier is equivalent to a standard format string.
.NET defines a set of standard format specifiers for all numeric types, all date and time types, and all enumeration types. For example, each of these categories supports a "G" standard format specifier, which defines a general string representation of a value of that type.
Standard format strings for enumeration types directly control the string representation of a value. The format strings passed to an enumeration value's ToString method determine whether the value is displayed using its string name (the "G" and "F" format specifiers), its underlying integral value (the "D" format specifier), or its hexadecimal value (the "X" format specifier). The following example illustrates the use of standard format strings to format a System.DayOfWeek enumeration value.
sample · csharpsamples/snippets/csharp/VS_Snippets_CLR/conceptual.formatting.overview/cs/standard1.cs4
using System;
public class Example16
{
public static void Main()
{
// <Snippet4>
DayOfWeek thisDay = DayOfWeek.Monday;
string[] formatStrings = {"G", "F", "D", "X"};
foreach (string formatString in formatStrings)
Console.WriteLine(thisDay.ToString(formatString));
// The example displays the following output:
// Monday
// Monday
// 1
// 00000001
// </Snippet4>
}
}sample · vbsamples/snippets/visualbasic/VS_Snippets_CLR/conceptual.formatting.overview/vb/standard1.vb4
' Visual Basic .NET Document
Option Strict On
Module Example17
Public Sub Main17()
' <Snippet4>
Dim thisDay As DayOfWeek = DayOfWeek.Monday
Dim formatStrings() As String = {"G", "F", "D", "X"}
For Each formatString As String In formatStrings
Console.WriteLine(thisDay.ToString(formatString))
Next
' The example displays the following output:
' Monday
' Monday
' 1
' 00000001
' </Snippet4>
End Sub
End ModuleFor information about enumeration format strings, see Enumeration Format Strings.
Standard format strings for numeric types usually define a result string whose precise appearance is controlled by one or more property values. For example, the "C" format specifier formats a number as a currency value. When you call the ToString method with the "C" format specifier as the only parameter, the following property values from the current culture's System.Globalization.NumberFormatInfo object are used to define the string representation of the numeric value:
The System.Globalization.NumberFormatInfo.CurrencySymbol property, which specifies the current culture's currency symbol.
The System.Globalization.NumberFormatInfo.CurrencyNegativePattern or System.Globalization.NumberFormatInfo.CurrencyPositivePattern property, which returns an integer that determines the following:
The placement of the currency symbol.
Whether negative values are indicated by a leading negative sign, a trailing negative sign, or parentheses.
Whether a space appears between the numeric value and the currency symbol.
The System.Globalization.NumberFormatInfo.CurrencyDecimalDigits property, which defines the number of fractional digits in the result string.
The System.Globalization.NumberFormatInfo.CurrencyDecimalSeparator property, which defines the decimal separator symbol in the result string.
The System.Globalization.NumberFormatInfo.CurrencyGroupSeparator property, which defines the group separator symbol.
The System.Globalization.NumberFormatInfo.CurrencyGroupSizes property, which defines the number of digits in each group to the left of the decimal.
The System.Globalization.NumberFormatInfo.NegativeSign property, which determines the negative sign used in the result string if parentheses aren't used to indicate negative values.
In addition, numeric format strings can include a precision specifier. The meaning of this specifier depends on the format string with which it's used, but it typically indicates either the total number of digits or the number of fractional digits that should appear in the result string. For example, the following example uses the "X4" standard numeric string and a precision specifier to create a string value that has four hexadecimal digits.
sample · csharpsamples/snippets/csharp/VS_Snippets_CLR/conceptual.formatting.overview/cs/precisionspecifier1.cs6
using System;
public class Example13
{
public static void Main()
{
// <Snippet6>
byte[] byteValues = { 12, 163, 255 };
foreach (byte byteValue in byteValues)
Console.WriteLine(byteValue.ToString("X4"));
// The example displays the following output:
// 000C
// 00A3
// 00FF
// </Snippet6>
}
}sample · vbsamples/snippets/visualbasic/VS_Snippets_CLR/conceptual.formatting.overview/vb/precisionspecifier1.vb6
' Visual Basic .NET Document
Option Strict On
Module Example14
Public Sub Main14()
' <Snippet6>
Dim byteValues() As Byte = {12, 163, 255}
For Each byteValue As Byte In byteValues
Console.WriteLine(byteValue.ToString("X4"))
Next
' The example displays the following output:
' 000C
' 00A3
' 00FF
' </Snippet6>
End Sub
End ModuleFor more information about standard numeric formatting strings, see Standard Numeric Format Strings.
Standard format strings for date and time values are aliases for custom format strings stored by a particular System.Globalization.DateTimeFormatInfo property. For example, calling the ToString method of a date and time value with the "D" format specifier displays the date and time by using the custom format string stored in the current culture's System.Globalization.DateTimeFormatInfo.LongDatePattern property. (For more information about custom format strings, see the next section.) The following example illustrates this relationship.
sample · csharpsamples/snippets/csharp/VS_Snippets_CLR/conceptual.formatting.overview/cs/alias1.cs5
// <Snippet5>
using System;
using System.Globalization;
public class Example
{
public static void Main()
{
DateTime date1 = new DateTime(2009, 6, 30);
Console.WriteLine($"D Format Specifier: {date1:D}");
string longPattern = CultureInfo.CurrentCulture.DateTimeFormat.LongDatePattern;
Console.WriteLine($"'{longPattern}' custom format string: {date1.ToString(longPattern)}");
}
}
// The example displays the following output when run on a system whose
// current culture is en-US:
// D Format Specifier: Tuesday, June 30, 2009
// 'dddd, MMMM dd, yyyy' custom format string: Tuesday, June 30, 2009
// </Snippet5>sample · vbsamples/snippets/visualbasic/VS_Snippets_CLR/conceptual.formatting.overview/vb/alias1.vb5
' Visual Basic .NET Document
Option Strict On
' <Snippet5>
Imports System.Globalization
Module Example
Public Sub Main0()
Dim date1 As Date = #6/30/2009#
Console.WriteLine("D Format Specifier: {0:D}", date1)
Dim longPattern As String = CultureInfo.CurrentCulture.DateTimeFormat.LongDatePattern
Console.WriteLine("'{0}' custom format string: {1}",
longPattern, date1.ToString(longPattern))
End Sub
End Module
' The example displays the following output when run on a system whose
' current culture is en-US:
' D Format Specifier: Tuesday, June 30, 2009
' 'dddd, MMMM dd, yyyy' custom format string: Tuesday, June 30, 2009
' </Snippet5>For more information about standard date and time format strings, see Standard Date and Time Format Strings.
You can also use standard format strings to define the string representation of an application-defined object that is produced by the object's ToString(String) method. You can define the specific standard format specifiers that your object supports, and you can determine whether they're case-sensitive or case-insensitive. Your implementation of the ToString(String) method should support the following:
A "G" format specifier that represents a customary or common format of the object. The parameterless overload of your object's
ToStringmethod should call itsToString(String)overload and pass it the "G" standard format string.Support for a format specifier that's equal to a null reference (
Nothingin Visual Basic). A format specifier that's equal to a null reference should be considered equivalent to the "G" format specifier.
For example, a Temperature class can internally store the temperature in degrees Celsius and use format specifiers to represent the value of the Temperature object in degrees Celsius, degrees Fahrenheit, and kelvins. The following example provides an illustration.
sample · csharpsamples/snippets/csharp/VS_Snippets_CLR/conceptual.formatting.overview/cs/appstandard1.cs7
// <Snippet7>
using System;
public class Temperature
{
private decimal m_Temp;
public Temperature(decimal temperature)
{
this.m_Temp = temperature;
}
public decimal Celsius
{
get { return this.m_Temp; }
}
public decimal Kelvin
{
get { return this.m_Temp + 273.15m; }
}
public decimal Fahrenheit
{
get { return Math.Round(((decimal) (this.m_Temp * 9 / 5 + 32)), 2); }
}
public override string ToString()
{
return this.ToString("C");
}
public string ToString(string format)
{
// Handle null or empty string.
if (String.IsNullOrEmpty(format)) format = "C";
// Remove spaces and convert to uppercase.
format = format.Trim().ToUpperInvariant();
// Convert temperature to Fahrenheit and return string.
switch (format)
{
// Convert temperature to Fahrenheit and return string.
case "F":
return this.Fahrenheit.ToString("N2") + " °F";
// Convert temperature to Kelvin and return string.
case "K":
return this.Kelvin.ToString("N2") + " K";
// return temperature in Celsius.
case "G":
case "C":
return this.Celsius.ToString("N2") + " °C";
default:
throw new FormatException(String.Format("The '{0}' format string is not supported.", format));
}
}
}
public class Example1
{
public static void Main()
{
Temperature temp1 = new Temperature(0m);
Console.WriteLine(temp1.ToString());
Console.WriteLine(temp1.ToString("G"));
Console.WriteLine(temp1.ToString("C"));
Console.WriteLine(temp1.ToString("F"));
Console.WriteLine(temp1.ToString("K"));
Temperature temp2 = new Temperature(-40m);
Console.WriteLine(temp2.ToString());
Console.WriteLine(temp2.ToString("G"));
Console.WriteLine(temp2.ToString("C"));
Console.WriteLine(temp2.ToString("F"));
Console.WriteLine(temp2.ToString("K"));
Temperature temp3 = new Temperature(16m);
Console.WriteLine(temp3.ToString());
Console.WriteLine(temp3.ToString("G"));
Console.WriteLine(temp3.ToString("C"));
Console.WriteLine(temp3.ToString("F"));
Console.WriteLine(temp3.ToString("K"));
Console.WriteLine(String.Format("The temperature is now {0:F}.", temp3));
}
}
// The example displays the following output:
// 0.00 °C
// 0.00 °C
// 0.00 °C
// 32.00 °F
// 273.15 K
// -40.00 °C
// -40.00 °C
// -40.00 °C
// -40.00 °F
// 233.15 K
// 16.00 °C
// 16.00 °C
// 16.00 °C
// 60.80 °F
// 289.15 K
// The temperature is now 16.00 °C.
// </Snippet7>sample · vbsamples/snippets/visualbasic/VS_Snippets_CLR/conceptual.formatting.overview/vb/appstandard1.vb7
Option Strict On
Namespace HotAndCold
' <Snippet7>
Public Class Temperature
Private m_Temp As Decimal
Public Sub New(temperature As Decimal)
Me.m_Temp = temperature
End Sub
Public ReadOnly Property Celsius() As Decimal
Get
Return Me.m_Temp
End Get
End Property
Public ReadOnly Property Kelvin() As Decimal
Get
Return Me.m_Temp + 273.15D
End Get
End Property
Public ReadOnly Property Fahrenheit() As Decimal
Get
Return Math.Round(CDec(Me.m_Temp * 9 / 5 + 32), 2)
End Get
End Property
Public Overrides Function ToString() As String
Return Me.ToString("C")
End Function
Public Overloads Function ToString(format As String) As String
' Handle null or empty string.
If String.IsNullOrEmpty(format) Then format = "C"
' Remove spaces and convert to uppercase.
format = format.Trim().ToUpperInvariant()
Select Case format
Case "F"
' Convert temperature to Fahrenheit and return string.
Return Me.Fahrenheit.ToString("N2") & " °F"
Case "K"
' Convert temperature to Kelvin and return string.
Return Me.Kelvin.ToString("N2") & " K"
Case "C", "G"
' Return temperature in Celsius.
Return Me.Celsius.ToString("N2") & " °C"
Case Else
Throw New FormatException(String.Format("The '{0}' format string is not supported.", format))
End Select
End Function
End Class
Public Module Example1
Public Sub Main1()
Dim temp1 As New Temperature(0D)
Console.WriteLine(temp1.ToString())
Console.WriteLine(temp1.ToString("G"))
Console.WriteLine(temp1.ToString("C"))
Console.WriteLine(temp1.ToString("F"))
Console.WriteLine(temp1.ToString("K"))
Dim temp2 As New Temperature(-40D)
Console.WriteLine(temp2.ToString())
Console.WriteLine(temp2.ToString("G"))
Console.WriteLine(temp2.ToString("C"))
Console.WriteLine(temp2.ToString("F"))
Console.WriteLine(temp2.ToString("K"))
Dim temp3 As New Temperature(16D)
Console.WriteLine(temp3.ToString())
Console.WriteLine(temp3.ToString("G"))
Console.WriteLine(temp3.ToString("C"))
Console.WriteLine(temp3.ToString("F"))
Console.WriteLine(temp3.ToString("K"))
Console.WriteLine(String.Format("The temperature is now {0:F}.", temp3))
End Sub
End Module
' The example displays the following output:
' 0.00 °C
' 0.00 °C
' 0.00 °C
' 32.00 °F
' 273.15 K
' -40.00 °C
' -40.00 °C
' -40.00 °C
' -40.00 °F
' 233.15 K
' 16.00 °C
' 16.00 °C
' 16.00 °C
' 60.80 °F
' 289.15 K
' The temperature is now 16.00 °C.
' </Snippet7>
End NamespaceCustom format strings
In addition to the standard format strings, .NET defines custom format strings for both numeric values and date and time values. A custom format string consists of one or more custom format specifiers that define the string representation of a value. For example, the custom date and time format string "yyyy/mm/dd hh:mm:ss.ffff t zzz" converts a date to its string representation in the form "2008/11/15 07:45:00.0000 P -08:00" for the en-US culture. Similarly, the custom format string "0000" converts the integer value 12 to "0012". For a complete list of custom format strings, see Custom Date and Time Format Strings and Custom Numeric Format Strings.
If a format string consists of a single custom format specifier, the format specifier should be preceded by the percent (%) symbol to avoid confusion with a standard format specifier. The following example uses the "M" custom format specifier to display a one-digit or two-digit number of the month of a particular date.
sample · csharpsamples/snippets/csharp/VS_Snippets_CLR/conceptual.formatting.overview/cs/singlecustom1.cs8
using System;
public class Example14
{
public static void Main()
{
// <Snippet8>
DateTime date1 = new DateTime(2009, 9, 8);
Console.WriteLine(date1.ToString("%M")); // Displays 9
// </Snippet8>
}
}sample · vbsamples/snippets/visualbasic/VS_Snippets_CLR/conceptual.formatting.overview/vb/singlecustom1.vb8
' Visual Basic .NET Document
Option Strict On
Module Example15
Public Sub Main15()
' <Snippet8>
Dim date1 As Date = #09/08/2009#
Console.WriteLine(date1.ToString("%M")) ' Displays 9
' </Snippet8>
End Sub
End ModuleMany standard format strings for date and time values are aliases for custom format strings that are defined by properties of the System.Globalization.DateTimeFormatInfo object. Custom format strings also offer considerable flexibility in providing application-defined formatting for numeric values or date and time values. You can define your own custom result strings for both numeric values and date and time values by combining multiple custom format specifiers into a single custom format string. The following example defines a custom format string that displays the day of the week in parentheses after the month name, day, and year.
sample · csharpsamples/snippets/csharp/VS_Snippets_CLR/conceptual.formatting.overview/cs/custom1.cs9
using System;
public class Example8
{
public static void Main()
{
// <Snippet9>
string customFormat = "MMMM dd, yyyy (dddd)";
DateTime date1 = new DateTime(2009, 8, 28);
Console.WriteLine(date1.ToString(customFormat));
// The example displays the following output if run on a system
// whose language is English:
// August 28, 2009 (Friday)
// </Snippet9>
}
}sample · vbsamples/snippets/visualbasic/VS_Snippets_CLR/conceptual.formatting.overview/vb/custom1.vb9
' Visual Basic .NET Document
Option Strict On
Module Example8
Public Sub Main8()
' <Snippet9>
Dim customFormat As String = "MMMM dd, yyyy (dddd)"
Dim date1 As Date = #8/28/2009#
Console.WriteLine(date1.ToString(customFormat))
' The example displays the following output if run on a system
' whose language is English:
' August 28, 2009 (Friday)
' </Snippet9>
End Sub
End ModuleThe following example defines a custom format string that displays an System.Int64 value as a standard, seven-digit U.S. telephone number along with its area code.
sample · csharpsamples/snippets/csharp/VS_Snippets_CLR/conceptual.formatting.overview/cs/telnumber1.cs21
// <Snippet21>
using System;
public class Example17
{
public static void Main()
{
long number = 8009999999;
string fmt = "000-000-0000";
Console.WriteLine(number.ToString(fmt));
}
}
// The example displays the following output:
// 800-999-9999
// </Snippet21>sample · vbsamples/snippets/visualbasic/VS_Snippets_CLR/conceptual.formatting.overview/vb/telnumber1.vb21
' Visual Basic .NET Document
Option Strict On
' <Snippet21>
Module Example18
Public Sub Main18()
Dim number As Long = 8009999999
Dim fmt As String = "000-000-0000"
Console.WriteLine(number.ToString(fmt))
End Sub
End Module
' The example displays the following output:
' The example displays the following output:
' 800-999-9999
' </Snippet21>Although standard format strings can generally handle most of the formatting needs for your application-defined types, you can also define custom format specifiers to format your types.
Format strings and .NET types
All numeric types (that is, the System.Byte, System.Decimal, System.Double, System.Int16, System.Int32, System.Int64, System.SByte, System.Single, System.UInt16, System.UInt32, System.UInt64, and System.Numerics.BigInteger types), as well as the System.DateTime, System.DateTimeOffset, System.TimeSpan, System.Guid, and all enumeration types, support formatting with format strings. For information on the specific format strings supported by each type, see the following articles:
| Title | Definition |
|---|---|
| Standard Numeric Format Strings | Describes standard format strings that create commonly used string representations of numeric values. |
| Custom Numeric Format Strings | Describes custom format strings that create application-specific formats for numeric values. |
| Standard Date and Time Format Strings | Describes standard format strings that create commonly used string representations of System.DateTime and System.DateTimeOffset values. |
| Custom Date and Time Format Strings | Describes custom format strings that create application-specific formats for System.DateTime and System.DateTimeOffset values. |
| Standard TimeSpan Format Strings | Describes standard format strings that create commonly used string representations of time intervals. |
| Custom TimeSpan Format Strings | Describes custom format strings that create application-specific formats for time intervals. |
| Enumeration Format Strings | Describes standard format strings that are used to create string representations of enumeration values. |
| System.Guid.ToString%28System.String%29 | Describes standard format strings for System.Guid values. |
Culture-sensitive formatting with format providers
Although format specifiers let you customize the formatting of objects, producing a meaningful string representation of objects often requires additional formatting information. For example, formatting a number as a currency value by using either the "C" standard format string or a custom format string such as "$ #,#.00" requires, at a minimum, information about the correct currency symbol, group separator, and decimal separator to be available to include in the formatted string. In .NET, this extra formatting information is made available through the System.IFormatProvider interface, which is provided as a parameter to one or more overloads of the ToString method of numeric types and date and time types. System.IFormatProvider implementations are used in .NET to support culture-specific formatting. The following example illustrates how the string representation of an object changes when it's formatted with three System.IFormatProvider objects that represent different cultures.
sample · csharpsamples/snippets/csharp/VS_Snippets_CLR/conceptual.formatting.overview/cs/iformatprovider1.cs11
// <Snippet11>
using System;
using System.Globalization;
public class Example18
{
public static void Main()
{
decimal value = 1603.42m;
Console.WriteLine(value.ToString("C3", new CultureInfo("en-US")));
Console.WriteLine(value.ToString("C3", new CultureInfo("fr-FR")));
Console.WriteLine(value.ToString("C3", new CultureInfo("de-DE")));
}
}
// The example displays the following output:
// $1,603.420
// 1 603,420 €
// 1.603,420 €
// </Snippet11>sample · vbsamples/snippets/visualbasic/VS_Snippets_CLR/conceptual.formatting.overview/vb/iformatprovider1.vb11
Option Strict On
' <Snippet11>
Imports System.Globalization
Public Module Example11
Public Sub Main11()
Dim value As Decimal = 1603.42D
Console.WriteLine(value.ToString("C3", New CultureInfo("en-US")))
Console.WriteLine(value.ToString("C3", New CultureInfo("fr-FR")))
Console.WriteLine(value.ToString("C3", New CultureInfo("de-DE")))
End Sub
End Module
' The example displays the following output:
' $1,603.420
' 1 603,420 €
' 1.603,420 €
' </Snippet11>The System.IFormatProvider interface includes one method, System.IFormatProvider.GetFormat%28System.Type%29, which has a single parameter that specifies the type of object that provides formatting information. If the method can provide an object of that type, it returns it. Otherwise, it returns a null reference (Nothing in Visual Basic).
System.IFormatProvider.GetFormat is a callback method. When you call a ToString method overload that includes an System.IFormatProvider parameter, it calls the System.IFormatProvider.GetFormat method of that System.IFormatProvider object. The System.IFormatProvider.GetFormat method is responsible for returning an object that provides the necessary formatting information, as specified by its formatType parameter, to the ToString method.
Several formatting or string conversion methods include a parameter of type System.IFormatProvider, but in many cases the value of the parameter is ignored when the method is called. The following table lists some of the formatting methods that use the parameter and the type of the System.Type object that they pass to the System.IFormatProvider.GetFormat method.
| Method | Type of formatType parameter |
|---|---|
ToString method of numeric types |
System.Globalization.NumberFormatInfo |
ToString method of date and time types |
System.Globalization.DateTimeFormatInfo |
| System.String.Format | System.ICustomFormatter |
| System.Text.StringBuilder.AppendFormat | System.ICustomFormatter |
.NET provides three classes that implement System.IFormatProvider:
System.Globalization.DateTimeFormatInfo, a class that provides formatting information for date and time values for a specific culture. Its System.IFormatProvider.GetFormat implementation returns an instance of itself.
System.Globalization.NumberFormatInfo, a class that provides numeric formatting information for a specific culture. Its System.IFormatProvider.GetFormat implementation returns an instance of itself.
System.Globalization.CultureInfo. Its System.IFormatProvider.GetFormat implementation can return either a System.Globalization.NumberFormatInfo object to provide numeric formatting information or a System.Globalization.DateTimeFormatInfo object to provide formatting information for date and time values.
You can also implement your own format provider to replace any one of these classes. However, your implementation's System.IFormatProvider.GetFormat method must return an object of the type listed in the previous table if it has to provide formatting information to the ToString method.
Culture-sensitive formatting of numeric values
By default, the formatting of numeric values is culture-sensitive. If you don't specify a culture when you call a formatting method, the formatting conventions of the current culture are used. This is illustrated in the following example, which changes the current culture four times and then calls the System.Decimal.ToString%28System.String%29 method. In each case, the result string reflects the formatting conventions of the current culture. This is because the ToString and ToString(String) methods wrap calls to each numeric type's ToString(String, IFormatProvider) method.
sample · csharpsamples/snippets/csharp/VS_Snippets_CLR/conceptual.formatting.overview/cs/culturespecific3.cs19
// <Snippet19>
using System.Globalization;
public class Example6
{
public static void Main()
{
string[] cultureNames = { "en-US", "fr-FR", "es-MX", "de-DE" };
Decimal value = 1043.17m;
foreach (var cultureName in cultureNames) {
// Change the current culture.
CultureInfo.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureName);
Console.WriteLine($"The current culture is {CultureInfo.CurrentCulture.Name}");
Console.WriteLine(value.ToString("C2"));
Console.WriteLine();
}
}
}
// The example displays the following output:
// The current culture is en-US
// $1,043.17
//
// The current culture is fr-FR
// 1 043,17 €
//
// The current culture is es-MX
// $1,043.17
//
// The current culture is de-DE
// 1.043,17 €
// </Snippet19>sample · vbsamples/snippets/visualbasic/VS_Snippets_CLR/conceptual.formatting.overview/vb/culturespecific3.vb19
' Visual Basic .NET Document
Option Strict On
' <Snippet19>
Imports System.Globalization
Module Example6
Public Sub Main6()
Dim cultureNames() As String = {"en-US", "fr-FR", "es-MX", "de-DE"}
Dim value As Decimal = 1043.17D
For Each cultureName In cultureNames
' Change the current culture.
CultureInfo.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureName)
Console.WriteLine($"The current culture is {CultureInfo.CurrentCulture.Name}")
Console.WriteLine(value.ToString("C2"))
Console.WriteLine()
Next
End Sub
End Module
' The example displays the following output:
' The current culture is en-US
' $1,043.17
'
' The current culture is fr-FR
' 1 043,17 €
'
' The current culture is es-MX
' $1,043.17
'
' The current culture is de-DE
' 1.043,17 €
' </Snippet19>You can also format a numeric value for a specific culture by calling a ToString overload that has a provider parameter and passing it either of the following:
A System.Globalization.CultureInfo object that represents the culture whose formatting conventions are to be used. Its System.Globalization.CultureInfo.GetFormat method returns the value of the System.Globalization.CultureInfo.NumberFormat property, which is the System.Globalization.NumberFormatInfo object that provides culture-specific formatting information for numeric values.
A System.Globalization.NumberFormatInfo object that defines the culture-specific formatting conventions to be used. Its System.Globalization.NumberFormatInfo.GetFormat method returns an instance of itself.
The following example uses System.Globalization.NumberFormatInfo objects that represent the English (United States) and English (United Kingdom) cultures and the French and Russian neutral cultures to format a floating-point number.
sample · csharpsamples/snippets/csharp/VS_Snippets_CLR/conceptual.formatting.overview/cs/culturespecific4.cs20
// <Snippet20>
using System.Globalization;
public class Example7
{
public static void Main()
{
double value = 1043.62957;
string[] cultureNames = { "en-US", "en-GB", "ru", "fr" };
foreach (string? name in cultureNames)
{
NumberFormatInfo nfi = CultureInfo.CreateSpecificCulture(name).NumberFormat;
Console.WriteLine("{0,-6} {1}", name + ":", value.ToString("N3", nfi));
}
}
}
// The example displays the following output:
// en-US: 1,043.630
// en-GB: 1,043.630
// ru: 1 043,630
// fr: 1 043,630
// </Snippet20>sample · vbsamples/snippets/visualbasic/VS_Snippets_CLR/conceptual.formatting.overview/vb/culturespecific4.vb20
' Visual Basic .NET Document
Option Strict On
' <Snippet20>
Imports System.Globalization
Module Example7
Public Sub Main7()
Dim value As Double = 1043.62957
Dim cultureNames() As String = {"en-US", "en-GB", "ru", "fr"}
For Each name In cultureNames
Dim nfi As NumberFormatInfo = CultureInfo.CreateSpecificCulture(name).NumberFormat
Console.WriteLine("{0,-6} {1}", name + ":", value.ToString("N3", nfi))
Next
End Sub
End Module
' The example displays the following output:
' en-US: 1,043.630
' en-GB: 1,043.630
' ru: 1 043,630
' fr: 1 043,630
' </Snippet20>Culture-sensitive formatting of date and time values
By default, the formatting of date and time values is culture-sensitive. If you don't specify a culture when you call a formatting method, the formatting conventions of the current culture are used. This is illustrated in the following example, which changes the current culture four times and then calls the System.DateTime.ToString%28System.String%29 method. In each case, the result string reflects the formatting conventions of the current culture. This is because the System.DateTime.ToString, System.DateTime.ToString%28System.String%29, System.DateTimeOffset.ToString, and System.DateTimeOffset.ToString%28System.String%29 methods wrap calls to the System.DateTime.ToString%28System.String%2CSystem.IFormatProvider%29 and System.DateTimeOffset.ToString%28System.String%2CSystem.IFormatProvider%29 methods.
sample · csharpsamples/snippets/csharp/VS_Snippets_CLR/conceptual.formatting.overview/cs/culturespecific1.cs17
// <Snippet17>
using System.Globalization;
public class Example4
{
public static void Main()
{
string[] cultureNames = { "en-US", "fr-FR", "es-MX", "de-DE" };
DateTime dateToFormat = new DateTime(2012, 5, 28, 11, 30, 0);
foreach (var cultureName in cultureNames) {
// Change the current culture.
CultureInfo.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureName);
Console.WriteLine($"The current culture is {CultureInfo.CurrentCulture.Name}");
Console.WriteLine(dateToFormat.ToString("F"));
Console.WriteLine();
}
}
}
// The example displays the following output:
// The current culture is en-US
// Monday, May 28, 2012 11:30:00 AM
//
// The current culture is fr-FR
// lundi 28 mai 2012 11:30:00
//
// The current culture is es-MX
// lunes, 28 de mayo de 2012 11:30:00 a.m.
//
// The current culture is de-DE
// Montag, 28. Mai 2012 11:30:00
// </Snippet17>sample · vbsamples/snippets/visualbasic/VS_Snippets_CLR/conceptual.formatting.overview/vb/culturespecific1.vb17
' Visual Basic .NET Document
Option Strict On
' <Snippet17>
Imports System.Globalization
Imports System.Threading
Module Example4
Public Sub Main4()
Dim cultureNames() As String = {"en-US", "fr-FR", "es-MX", "de-DE"}
Dim dateToFormat As Date = #5/28/2012 11:30AM#
For Each cultureName In cultureNames
' Change the current culture.
CultureInfo.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureName)
Console.WriteLine($"The current culture is {CultureInfo.CurrentCulture.Name}")
Console.WriteLine(dateToFormat.ToString("F"))
Console.WriteLine()
Next
End Sub
End Module
' The example displays the following output:
' The current culture is en-US
' Monday, May 28, 2012 11:30:00 AM
'
' The current culture is fr-FR
' lundi 28 mai 2012 11:30:00
'
' The current culture is es-MX
' lunes, 28 de mayo de 2012 11:30:00 a.m.
'
' The current culture is de-DE
' Montag, 28. Mai 2012 11:30:00
' </Snippet17>You can also format a date and time value for a specific culture by calling a System.DateTime.ToString or System.DateTimeOffset.ToString overload that has a provider parameter and passing it either of the following:
A System.Globalization.CultureInfo object that represents the culture whose formatting conventions are to be used. Its System.Globalization.CultureInfo.GetFormat method returns the value of the System.Globalization.CultureInfo.DateTimeFormat property, which is the System.Globalization.DateTimeFormatInfo object that provides culture-specific formatting information for date and time values.
A System.Globalization.DateTimeFormatInfo object that defines the culture-specific formatting conventions to be used. Its System.Globalization.DateTimeFormatInfo.GetFormat method returns an instance of itself.
The following example uses System.Globalization.DateTimeFormatInfo objects that represent the English (United States) and English (United Kingdom) cultures and the French and Russian neutral cultures to format a date.
sample · csharpsamples/snippets/csharp/VS_Snippets_CLR/conceptual.formatting.overview/cs/culturespecific2.cs18
// <Snippet18>
using System.Globalization;
public class Example5
{
public static void Main()
{
DateTime dat1 = new(2012, 5, 28, 11, 30, 0);
string[] cultureNames = { "en-US", "en-GB", "ru", "fr" };
foreach (var name in cultureNames) {
DateTimeFormatInfo dtfi = CultureInfo.CreateSpecificCulture(name).DateTimeFormat;
Console.WriteLine($"{name}: {dat1.ToString(dtfi)}");
}
}
}
// The example displays the following output:
// en-US: 5/28/2012 11:30:00 AM
// en-GB: 28/05/2012 11:30:00
// ru: 28.05.2012 11:30:00
// fr: 28/05/2012 11:30:00
// </Snippet18>sample · vbsamples/snippets/visualbasic/VS_Snippets_CLR/conceptual.formatting.overview/vb/culturespecific2.vb18
' Visual Basic .NET Document
Option Strict On
' <Snippet18>
Imports System.Globalization
Module Example5
Public Sub Main5()
Dim dat1 As Date = #5/28/2012 11:30AM#
Dim cultureNames() As String = {"en-US", "en-GB", "ru", "fr"}
For Each name In cultureNames
Dim dtfi As DateTimeFormatInfo = CultureInfo.CreateSpecificCulture(name).DateTimeFormat
Console.WriteLine($"{name}: {dat1.ToString(dtfi)}")
Next
End Sub
End Module
' The example displays the following output:
' en-US: 5/28/2012 11:30:00 AM
' en-GB: 28/05/2012 11:30:00
' ru: 28.05.2012 11:30:00
' fr: 28/05/2012 11:30:00
' </Snippet18>The IFormattable interface
Typically, types that overload the ToString method with a format string and an System.IFormatProvider parameter also implement the System.IFormattable interface. This interface has a single member, System.IFormattable.ToString%28System.String%2CSystem.IFormatProvider%29, that includes both a format string and a format provider as parameters.
Implementing the System.IFormattable interface for your application-defined class offers two advantages:
Support for string conversion by the System.Convert class. Calls to the System.Convert.ToString%28System.Object%29 and System.Convert.ToString%28System.Object%2CSystem.IFormatProvider%29 methods call your System.IFormattable implementation automatically.
Support for composite formatting. If a format item that includes a format string is used to format your custom type, the common language runtime automatically calls your System.IFormattable implementation and passes it the format string. For more information about composite formatting with methods such as System.String.Format or System.Console.WriteLine, see the Composite Formatting section.
The following example defines a Temperature class that implements the System.IFormattable interface. It supports the "C" or "G" format specifiers to display the temperature in Celsius, the "F" format specifier to display the temperature in Fahrenheit, and the "K" format specifier to display the temperature in Kelvin.
sample · csharpsamples/snippets/csharp/VS_Snippets_CLR/conceptual.formatting.overview/cs/iformattable.cs12
// <Snippet12>
using System;
using System.Globalization;
namespace HotAndCold
{
public class Temperature : IFormattable
{
private decimal m_Temp;
public Temperature(decimal temperature)
{
this.m_Temp = temperature;
}
public decimal Celsius
{
get { return this.m_Temp; }
}
public decimal Kelvin
{
get { return this.m_Temp + 273.15m; }
}
public decimal Fahrenheit
{
get { return Math.Round((decimal)this.m_Temp * 9 / 5 + 32, 2); }
}
public override string ToString()
{
return this.ToString("G", null);
}
public string ToString(string format)
{
return this.ToString(format, null);
}
public string ToString(string format, IFormatProvider provider)
{
// Handle null or empty arguments.
if (String.IsNullOrEmpty(format))
format = "G";
// Remove any white space and covert to uppercase.
format = format.Trim().ToUpperInvariant();
if (provider == null)
provider = NumberFormatInfo.CurrentInfo;
switch (format)
{
// Convert temperature to Fahrenheit and return string.
case "F":
return this.Fahrenheit.ToString("N2", provider) + "°F";
// Convert temperature to Kelvin and return string.
case "K":
return this.Kelvin.ToString("N2", provider) + "K";
// Return temperature in Celsius.
case "C":
case "G":
return this.Celsius.ToString("N2", provider) + "°C";
default:
throw new FormatException(String.Format("The '{0}' format string is not supported.", format));
}
}
}
// </Snippet12>
// <Snippet13>
public class Example11
{
public static void Main()
{
CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("en-US");
Temperature temp = new Temperature(22m);
Console.WriteLine(Convert.ToString(temp, new CultureInfo("ja-JP")));
Console.WriteLine($"Temperature: {temp:K}");
Console.WriteLine($"Temperature: {temp:F}");
Console.WriteLine(String.Format(new CultureInfo("fr-FR"), "Temperature: {0:F}", temp));
}
}
// The example displays the following output:
// 22.00°C
// Temperature: 295.15K
// Temperature: 71.60°F
// Temperature: 71,60°F
// </Snippet13>
}sample · vbsamples/snippets/visualbasic/VS_Snippets_CLR/conceptual.formatting.overview/vb/iformattable.vb12
Option Strict On
Imports System.Globalization
Namespace HotAndCold2
' <Snippet12>
Public Class Temperature : Implements IFormattable
Private m_Temp As Decimal
Public Sub New(temperature As Decimal)
Me.m_Temp = temperature
End Sub
Public ReadOnly Property Celsius() As Decimal
Get
Return Me.m_Temp
End Get
End Property
Public ReadOnly Property Kelvin() As Decimal
Get
Return Me.m_Temp + 273.15D
End Get
End Property
Public ReadOnly Property Fahrenheit() As Decimal
Get
Return Math.Round(CDec(Me.m_Temp * 9 / 5 + 32), 2)
End Get
End Property
Public Overrides Function ToString() As String
Return Me.ToString("G", Nothing)
End Function
Public Overloads Function ToString(format As String) As String
Return Me.ToString(format, Nothing)
End Function
Public Overloads Function ToString(format As String, provider As IFormatProvider) As String _
Implements IFormattable.ToString
' Handle null or empty arguments.
If String.IsNullOrEmpty(format) Then format = "G"
' Remove any white space and convert to uppercase.
format = format.Trim().ToUpperInvariant()
If provider Is Nothing Then provider = NumberFormatInfo.CurrentInfo
Select Case format
' Convert temperature to Fahrenheit and return string.
Case "F"
Return Me.Fahrenheit.ToString("N2", provider) & "°F"
' Convert temperature to Kelvin and return string.
Case "K"
Return Me.Kelvin.ToString("N2", provider) & "K"
' Return temperature in Celsius.
Case "C", "G"
Return Me.Celsius.ToString("N2", provider) & "°C"
Case Else
Throw New FormatException(String.Format($"The '{format}' format string is not supported."))
End Select
End Function
End Class
' </Snippet12>
' <Snippet13>
Public Module Example12
Public Sub Main12()
Dim temp As New Temperature(22D)
CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("en-US")
Console.WriteLine(Convert.ToString(temp, New CultureInfo("ja-JP")))
Console.WriteLine($"Temperature: {temp:K}")
Console.WriteLine($"Temperature: {temp:F}")
Console.WriteLine(String.Format(New CultureInfo("fr-FR"), $"Temperature: {temp:F}"))
End Sub
End Module
' The example displays the following output:
' 22.00°C
' Temperature: 295.15K
' Temperature: 71.60°F
' Temperature: 71,60°F
' </Snippet13>
End NamespaceThe following example instantiates a Temperature object. It then calls the System.Convert.ToString method and uses several composite format strings to obtain different string representations of a Temperature object. Each of these method calls, in turn, calls the System.IFormattable implementation of the Temperature class.
sample · csharpsamples/snippets/csharp/VS_Snippets_CLR/conceptual.formatting.overview/cs/iformattable.cs13
// <Snippet12>
using System;
using System.Globalization;
namespace HotAndCold
{
public class Temperature : IFormattable
{
private decimal m_Temp;
public Temperature(decimal temperature)
{
this.m_Temp = temperature;
}
public decimal Celsius
{
get { return this.m_Temp; }
}
public decimal Kelvin
{
get { return this.m_Temp + 273.15m; }
}
public decimal Fahrenheit
{
get { return Math.Round((decimal)this.m_Temp * 9 / 5 + 32, 2); }
}
public override string ToString()
{
return this.ToString("G", null);
}
public string ToString(string format)
{
return this.ToString(format, null);
}
public string ToString(string format, IFormatProvider provider)
{
// Handle null or empty arguments.
if (String.IsNullOrEmpty(format))
format = "G";
// Remove any white space and covert to uppercase.
format = format.Trim().ToUpperInvariant();
if (provider == null)
provider = NumberFormatInfo.CurrentInfo;
switch (format)
{
// Convert temperature to Fahrenheit and return string.
case "F":
return this.Fahrenheit.ToString("N2", provider) + "°F";
// Convert temperature to Kelvin and return string.
case "K":
return this.Kelvin.ToString("N2", provider) + "K";
// Return temperature in Celsius.
case "C":
case "G":
return this.Celsius.ToString("N2", provider) + "°C";
default:
throw new FormatException(String.Format("The '{0}' format string is not supported.", format));
}
}
}
// </Snippet12>
// <Snippet13>
public class Example11
{
public static void Main()
{
CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("en-US");
Temperature temp = new Temperature(22m);
Console.WriteLine(Convert.ToString(temp, new CultureInfo("ja-JP")));
Console.WriteLine($"Temperature: {temp:K}");
Console.WriteLine($"Temperature: {temp:F}");
Console.WriteLine(String.Format(new CultureInfo("fr-FR"), "Temperature: {0:F}", temp));
}
}
// The example displays the following output:
// 22.00°C
// Temperature: 295.15K
// Temperature: 71.60°F
// Temperature: 71,60°F
// </Snippet13>
}sample · vbsamples/snippets/visualbasic/VS_Snippets_CLR/conceptual.formatting.overview/vb/iformattable.vb13
Option Strict On
Imports System.Globalization
Namespace HotAndCold2
' <Snippet12>
Public Class Temperature : Implements IFormattable
Private m_Temp As Decimal
Public Sub New(temperature As Decimal)
Me.m_Temp = temperature
End Sub
Public ReadOnly Property Celsius() As Decimal
Get
Return Me.m_Temp
End Get
End Property
Public ReadOnly Property Kelvin() As Decimal
Get
Return Me.m_Temp + 273.15D
End Get
End Property
Public ReadOnly Property Fahrenheit() As Decimal
Get
Return Math.Round(CDec(Me.m_Temp * 9 / 5 + 32), 2)
End Get
End Property
Public Overrides Function ToString() As String
Return Me.ToString("G", Nothing)
End Function
Public Overloads Function ToString(format As String) As String
Return Me.ToString(format, Nothing)
End Function
Public Overloads Function ToString(format As String, provider As IFormatProvider) As String _
Implements IFormattable.ToString
' Handle null or empty arguments.
If String.IsNullOrEmpty(format) Then format = "G"
' Remove any white space and convert to uppercase.
format = format.Trim().ToUpperInvariant()
If provider Is Nothing Then provider = NumberFormatInfo.CurrentInfo
Select Case format
' Convert temperature to Fahrenheit and return string.
Case "F"
Return Me.Fahrenheit.ToString("N2", provider) & "°F"
' Convert temperature to Kelvin and return string.
Case "K"
Return Me.Kelvin.ToString("N2", provider) & "K"
' Return temperature in Celsius.
Case "C", "G"
Return Me.Celsius.ToString("N2", provider) & "°C"
Case Else
Throw New FormatException(String.Format($"The '{format}' format string is not supported."))
End Select
End Function
End Class
' </Snippet12>
' <Snippet13>
Public Module Example12
Public Sub Main12()
Dim temp As New Temperature(22D)
CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("en-US")
Console.WriteLine(Convert.ToString(temp, New CultureInfo("ja-JP")))
Console.WriteLine($"Temperature: {temp:K}")
Console.WriteLine($"Temperature: {temp:F}")
Console.WriteLine(String.Format(New CultureInfo("fr-FR"), $"Temperature: {temp:F}"))
End Sub
End Module
' The example displays the following output:
' 22.00°C
' Temperature: 295.15K
' Temperature: 71.60°F
' Temperature: 71,60°F
' </Snippet13>
End NamespaceComposite formatting
Some methods, such as System.String.Format and System.Text.StringBuilder.AppendFormat, support composite formatting. A composite format string is a kind of template that returns a single string that incorporates the string representation of zero, one, or more objects. Each object is represented in the composite format string by an indexed format item. The index of the format item corresponds to the position of the object that it represents in the method's parameter list. Indexes are zero-based. For example, in the following call to the System.String.Format method, the first format item, {0:D}, is replaced by the string representation of thatDate; the second format item, {1}, is replaced by the string representation of item1; and the third format item, {2:C2}, is replaced by the string representation of item1.Value.
sample · csharpsamples/snippets/csharp/VS_Snippets_CLR/conceptual.formatting.overview/cs/composite1.cs14
using System;
public class Product
{
private string productName;
private int onHand;
private decimal cost;
public Product(string name)
{
this.productName = name;
}
public int Quantity
{
get { return this.onHand; }
set { this.onHand = value; }
}
public decimal Price
{
get { return this.cost; }
set { this.cost = value; }
}
public decimal Value
{
get { return this.cost * this.onHand; }
}
public string Name
{
get { return this.productName; }
}
public override string ToString()
{
return this.productName;
}
}
public class Example2
{
public static void Main()
{
Product item1 = new Product("WidgetA");
item1.Quantity = 17;
item1.Price = 6.32m;
DateTime thatDate = new DateTime(2009, 5, 1);
string result;
// <Snippet14>
result = String.Format("On {0:d}, the inventory of {1} was worth {2:C2}.",
thatDate, item1, item1.Value);
Console.WriteLine(result);
// The example displays output like the following if run on a system
// whose current culture is en-US:
// On 5/1/2009, the inventory of WidgetA was worth $107.44.
// </Snippet14>
}
}sample · vbsamples/snippets/visualbasic/VS_Snippets_CLR/conceptual.formatting.overview/vb/composite1.vb14
' Visual Basic .NET Document
Option Strict On
Public Class Product
Private productName As String
Private onHand As Integer
Private cost As Decimal
Public Sub New(name As String)
Me.productName = name
End Sub
Public Property Quantity As Integer
Get
Return Me.onHand
End Get
Set
Me.onHand = value
End Set
End Property
Public Property Price As Decimal
Get
Return Me.cost
End Get
Set
Me.cost = value
End Set
End Property
Public ReadOnly Property Value As Decimal
Get
Return Me.cost * Me.onHand
End Get
End Property
Public ReadOnly Property Name As String
Get
Return Me.productName
End Get
End Property
Public Overrides Function ToString() As String
Return Me.productName
End Function
End Class
Module Example2
Public Sub Main2()
Dim item1 As New Product("WidgetA")
item1.Quantity = 17
item1.Price = 6.32D
Dim thatDate As DateTime = #5/1/2009#
Dim result As String
' <Snippet14>
result = String.Format("On {0:d}, the inventory of {1} was worth {2:C2}.",
thatDate, item1, item1.Value)
Console.WriteLine(result)
' The example displays output like the following if run on a system
' whose current culture is en-US:
' On 5/1/2009, the inventory of WidgetA was worth $107.44.
' </Snippet14>
End Sub
End ModuleIn addition to replacing a format item with the string representation of its corresponding object, format items also let you control the following:
The specific way in which an object is represented as a string, if the object implements the System.IFormattable interface and supports format strings. You do this by following the format item's index with a
:(colon) followed by a valid format string. The previous example did this by formatting a date value with the "d" (short date pattern) format string (for example,{0:d}) and by formatting a numeric value with the "C2" format string (for example,{2:C2}) to represent the number as a currency value with two fractional decimal digits.The width of the field that contains the object's string representation, and the alignment of the string representation in that field. You do this by following the format item's index with a
,(comma) followed the field width. The string is right-aligned in the field if the field width is a positive value, and it's left-aligned if the field width is a negative value. The following example left-aligns date values in a 20-character field, and it right-aligns decimal values with one fractional digit in an 11-character field.sample · csharpsamples/snippets/csharp/VS_Snippets_CLR/conceptual.formatting.overview/cs/composite2.cs22
using System; public class Example3 { public static void Main() { // <Snippet22> DateTime startDate = new DateTime(2015, 8, 28, 6, 0, 0); decimal[] temps = { 73.452m, 68.98m, 72.6m, 69.24563m, 74.1m, 72.156m, 72.228m }; Console.WriteLine("{0,-20} {1,11}\n", "Date", "Temperature"); for (int ctr = 0; ctr < temps.Length; ctr++) Console.WriteLine("{0,-20:g} {1,11:N1}", startDate.AddDays(ctr), temps[ctr]); // The example displays the following output: // Date Temperature // // 8/28/2015 6:00 AM 73.5 // 8/29/2015 6:00 AM 69.0 // 8/30/2015 6:00 AM 72.6 // 8/31/2015 6:00 AM 69.2 // 9/1/2015 6:00 AM 74.1 // 9/2/2015 6:00 AM 72.2 // 9/3/2015 6:00 AM 72.2 // </Snippet22> } }sample · vbsamples/snippets/visualbasic/VS_Snippets_CLR/conceptual.formatting.overview/vb/composite2.vb22
Public Module Example3 Public Sub Main3() ' <Snippet22> Dim startDate As New Date(2015, 8, 28, 6, 0, 0) Dim temps() As Decimal = {73.452, 68.98, 72.6, 69.24563, 74.1, 72.156, 72.228} Console.WriteLine("{0,-20} {1,11}", "Date", "Temperature") Console.WriteLine() For ctr As Integer = 0 To temps.Length - 1 Console.WriteLine("{0,-20:g} {1,11:N1}", startDate.AddDays(ctr), temps(ctr)) Next ' The example displays the following output: ' Date Temperature ' ' 8/28/2015 6:00 AM 73.5 ' 8/29/2015 6:00 AM 69.0 ' 8/30/2015 6:00 AM 72.6 ' 8/31/2015 6:00 AM 69.2 ' 9/1/2015 6:00 AM 74.1 ' 9/2/2015 6:00 AM 72.2 ' 9/3/2015 6:00 AM 72.2 ' </Snippet22> End Sub End ModuleIf both the alignment string component and the format string component are present, the former precedes the latter (for example,
{0,-20:g}).
For more information about composite formatting, see Composite Formatting.
Custom formatting with ICustomFormatter
Two composite formatting methods, System.String.Format%28System.IFormatProvider%2CSystem.String%2CSystem.Object%5B%5D%29 and System.Text.StringBuilder.AppendFormat%28System.IFormatProvider%2CSystem.String%2CSystem.Object%5B%5D%29, include a format provider parameter that supports custom formatting. When either of these formatting methods is called, it passes a System.Type object that represents an System.ICustomFormatter interface to the format provider's System.IFormatProvider.GetFormat method. The System.IFormatProvider.GetFormat method is then responsible for returning the System.ICustomFormatter implementation that provides custom formatting.
The System.ICustomFormatter interface has a single method, System.ICustomFormatter.Format%28System.String%2CSystem.Object%2CSystem.IFormatProvider%29, that is called automatically by a composite formatting method, once for each format item in a composite format string. The System.ICustomFormatter.Format%28System.String%2CSystem.Object%2CSystem.IFormatProvider%29 method has three parameters: a format string, which represents the formatString argument in a format item, an object to format, and an System.IFormatProvider object that provides formatting services. Typically, the class that implements System.ICustomFormatter also implements System.IFormatProvider, so this last parameter is a reference to the custom formatting class itself. The method returns a custom formatted string representation of the object to be formatted. If the method can't format the object, it should return a null reference (Nothing in Visual Basic).
The following example provides an System.ICustomFormatter implementation named ByteByByteFormatter that displays integer values as a sequence of two-digit hexadecimal values followed by a space.
sample · csharpsamples/snippets/csharp/VS_Snippets_CLR/conceptual.formatting.overview/cs/icustomformatter1.cs15
// <Snippet15>
public class ByteByByteFormatter : 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 ((formatProvider is not null) && !formatProvider.Equals(this)) return "";
// Handle only hexadecimal format string.
if ((format is not null) && !format.StartsWith("X")) return "";
byte[] bytes;
// Handle only integral types.
if (arg is Int16)
bytes = BitConverter.GetBytes((Int16)arg);
else if (arg is Int32)
bytes = BitConverter.GetBytes((Int32)arg);
else if (arg is Int64)
bytes = BitConverter.GetBytes((Int64)arg);
else if (arg is UInt16)
bytes = BitConverter.GetBytes((UInt16)arg);
else if (arg is UInt32)
bytes = BitConverter.GetBytes((UInt32)arg);
else if (arg is UInt64)
bytes = BitConverter.GetBytes((UInt64)arg);
else
return "";
string output= "";
for (int ctr = bytes.Length - 1; ctr >= 0; ctr--)
output += string.Format("{0:X2} ", bytes[ctr]);
return output.Trim();
}
}
// </Snippet15>
// <Snippet16>
public class Example10
{
public static void Main()
{
long value = 3210662321;
byte value1 = 214;
byte value2 = 19;
Console.WriteLine(string.Format(new ByteByByteFormatter(), "{0:X}", value));
Console.WriteLine(string.Format(new ByteByByteFormatter(), "{0:X} And {1:X} = {2:X} ({2:000})",
value1, value2, value1 & value2));
Console.WriteLine(string.Format(new ByteByByteFormatter(), "{0,10:N0}", value));
}
}
// The example displays the following output:
// 00 00 00 00 BF 5E D1 B1
// 00 D6 And 00 13 = 00 12 (018)
// 3,210,662,321
// </Snippet16>sample · vbsamples/snippets/visualbasic/VS_Snippets_CLR/conceptual.formatting.overview/vb/icustomformatter1.vb15
' <Snippet15>
Public Class ByteByByteFormatter : 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, arg As Object,
formatProvider As IFormatProvider) As String _
Implements ICustomFormatter.Format
If Not formatProvider.Equals(Me) Then Return Nothing
' Handle only hexadecimal format string.
If Not fmt.StartsWith("X") Then
Return Nothing
End If
' Handle only integral types.
If Not typeof arg Is Byte AndAlso
Not typeof arg Is Int16 AndAlso
Not typeof arg Is Int32 AndAlso
Not typeof arg Is Int64 AndAlso
Not typeof arg Is SByte AndAlso
Not typeof arg Is UInt16 AndAlso
Not typeof arg Is UInt32 AndAlso
Not typeof arg Is UInt64 Then _
Return Nothing
Dim bytes() As Byte = BitConverter.GetBytes(arg)
Dim output As String = Nothing
For ctr As Integer = bytes.Length - 1 To 0 Step -1
output += String.Format("{0:X2} ", bytes(ctr))
Next
Return output.Trim()
End Function
End Class
' </Snippet15>
' <Snippet16>
Public Module Example10
Public Sub Main10()
Dim value As Long = 3210662321
Dim value1 As Byte = 214
Dim value2 As Byte = 19
Console.WriteLine((String.Format(New ByteByByteFormatter(), "{0:X}", value)))
Console.WriteLine((String.Format(New ByteByByteFormatter(), "{0:X} And {1:X} = {2:X} ({2:000})",
value1, value2, value1 And value2)))
Console.WriteLine(String.Format(New ByteByByteFormatter(), "{0,10:N0}", value))
End Sub
End Module
' The example displays the following output:
' 00 00 00 00 BF 5E D1 B1
' 00 D6 And 00 13 = 00 12 (018)
' 3,210,662,321
' </Snippet16>The following example uses the ByteByByteFormatter class to format integer values. The System.ICustomFormatter.Format method is called more than once in the second System.String.Format%28System.IFormatProvider%2CSystem.String%2CSystem.Object%5B%5D%29 method call, and that the default System.Globalization.NumberFormatInfo provider is used in the third method call because the .ByteByByteFormatter.Format method doesn't recognize the "N0" format string and returns a null reference (Nothing in Visual Basic).
sample · csharpsamples/snippets/csharp/VS_Snippets_CLR/conceptual.formatting.overview/cs/icustomformatter1.cs16
// <Snippet15>
public class ByteByByteFormatter : 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 ((formatProvider is not null) && !formatProvider.Equals(this)) return "";
// Handle only hexadecimal format string.
if ((format is not null) && !format.StartsWith("X")) return "";
byte[] bytes;
// Handle only integral types.
if (arg is Int16)
bytes = BitConverter.GetBytes((Int16)arg);
else if (arg is Int32)
bytes = BitConverter.GetBytes((Int32)arg);
else if (arg is Int64)
bytes = BitConverter.GetBytes((Int64)arg);
else if (arg is UInt16)
bytes = BitConverter.GetBytes((UInt16)arg);
else if (arg is UInt32)
bytes = BitConverter.GetBytes((UInt32)arg);
else if (arg is UInt64)
bytes = BitConverter.GetBytes((UInt64)arg);
else
return "";
string output= "";
for (int ctr = bytes.Length - 1; ctr >= 0; ctr--)
output += string.Format("{0:X2} ", bytes[ctr]);
return output.Trim();
}
}
// </Snippet15>
// <Snippet16>
public class Example10
{
public static void Main()
{
long value = 3210662321;
byte value1 = 214;
byte value2 = 19;
Console.WriteLine(string.Format(new ByteByByteFormatter(), "{0:X}", value));
Console.WriteLine(string.Format(new ByteByByteFormatter(), "{0:X} And {1:X} = {2:X} ({2:000})",
value1, value2, value1 & value2));
Console.WriteLine(string.Format(new ByteByByteFormatter(), "{0,10:N0}", value));
}
}
// The example displays the following output:
// 00 00 00 00 BF 5E D1 B1
// 00 D6 And 00 13 = 00 12 (018)
// 3,210,662,321
// </Snippet16>sample · vbsamples/snippets/visualbasic/VS_Snippets_CLR/conceptual.formatting.overview/vb/icustomformatter1.vb16
' <Snippet15>
Public Class ByteByByteFormatter : 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, arg As Object,
formatProvider As IFormatProvider) As String _
Implements ICustomFormatter.Format
If Not formatProvider.Equals(Me) Then Return Nothing
' Handle only hexadecimal format string.
If Not fmt.StartsWith("X") Then
Return Nothing
End If
' Handle only integral types.
If Not typeof arg Is Byte AndAlso
Not typeof arg Is Int16 AndAlso
Not typeof arg Is Int32 AndAlso
Not typeof arg Is Int64 AndAlso
Not typeof arg Is SByte AndAlso
Not typeof arg Is UInt16 AndAlso
Not typeof arg Is UInt32 AndAlso
Not typeof arg Is UInt64 Then _
Return Nothing
Dim bytes() As Byte = BitConverter.GetBytes(arg)
Dim output As String = Nothing
For ctr As Integer = bytes.Length - 1 To 0 Step -1
output += String.Format("{0:X2} ", bytes(ctr))
Next
Return output.Trim()
End Function
End Class
' </Snippet15>
' <Snippet16>
Public Module Example10
Public Sub Main10()
Dim value As Long = 3210662321
Dim value1 As Byte = 214
Dim value2 As Byte = 19
Console.WriteLine((String.Format(New ByteByByteFormatter(), "{0:X}", value)))
Console.WriteLine((String.Format(New ByteByByteFormatter(), "{0:X} And {1:X} = {2:X} ({2:000})",
value1, value2, value1 And value2)))
Console.WriteLine(String.Format(New ByteByByteFormatter(), "{0,10:N0}", value))
End Sub
End Module
' The example displays the following output:
' 00 00 00 00 BF 5E D1 B1
' 00 D6 And 00 13 = 00 12 (018)
' 3,210,662,321
' </Snippet16>See also
| Title | Definition |
|---|---|
| Standard Numeric Format Strings | Describes standard format strings that create commonly used string representations of numeric values. |
| Custom Numeric Format Strings | Describes custom format strings that create application-specific formats for numeric values. |
| Standard Date and Time Format Strings | Describes standard format strings that create commonly used string representations of System.DateTime values. |
| Custom Date and Time Format Strings | Describes custom format strings that create application-specific formats for System.DateTime values. |
| Standard TimeSpan Format Strings | Describes standard format strings that create commonly used string representations of time intervals. |
| Custom TimeSpan Format Strings | Describes custom format strings that create application-specific formats for time intervals. |
| Enumeration Format Strings | Describes standard format strings that are used to create string representations of enumeration values. |
| Composite Formatting | Describes how to embed one or more formatted values in a string. The string can subsequently be displayed on the console or written to a stream. |
| Parsing Strings | Describes how to initialize objects to the values described by string representations of those objects. Parsing is the inverse operation of formatting. |