 .NET 1.1C# Numeric String Conversion Part 1
The eighteenth part of the C# Fundamentals tutorial brings together the native data types discussed so far. This article describes how to convert string values to numeric types. This is essential when allowing free-form user input of numeric data.
Converting Strings to Numeric Data Types
When developing software that requires user input, it is often the case that the user is presented with a textbox or other control that allows text to be typed freely. The entered information is provided to the programmer's code as the contents of a string. However, if the textbox is being used to allow the user to specify a number, this string may need to be converted to an appropriate numeric data type.
In a previous article in this series, we discussed the possibilities for implicit and explicit conversion between numeric types using the cast functions. Casting is not available when converting between string and numeric values. Instead, .NET framework provides a 'Convert' class specifically designed for conversion between native types. The numeric classes also provide methods that allow strings to be parsed.
Convert Class
The .NET framework provides the Convert class within the System namespace. The class provides many conversion functions as static methods. Static methods will be described in detail in another tutorial. For the purposes of the C# Fundamentals tutorial, it is enough to understand that when a method is static, it is used without first creating an object. In other words, we will not be creating a Convert object to access the methods we require.
.NET Structures and C# Keywords
One complication when using the Convert class is that native C# data types are named differently from the underlying .NET framework structures. This occurs to keep the keywords similar to those of the C and C++ languages that preceded C#. The following table lists the numeric and Boolean data types that have been described in the tutorial so far and the corresponding .NET framework structure name. The Convert class uses the case-sensitive .NET structure names.
| C# Data Type | .NET Structure Name |
|---|
| bool | Boolean | | byte | Byte | | decimal | Decimal | | double | Double | | float | Single | | int | Int32 | | long | Int64 | | sbyte | SByte | | short | Int16 | | uint | UInt32 | | ulong | UInt64 | | ushort | UInt16 |
Conversion Syntax
The static conversion methods of the Convert class all follow a similar syntax. The method is named as the word 'To' followed by the desired resultant data type, using the .NET structure name. For example, to convert a string to a float, the method called is Convert.ToSingle. The string value to be converted is provided as a parameter to the method.
// Convert a string to an integer
int stringToInt = Convert.ToInt32("25");
// Convert a string to a decimal
decimal stringToDecimal = Convert.ToDecimal("25.5");
// Booleans can be converted too
bool stringToBoolean = Convert.ToBoolean("true");
NB: The Convert method can be used without a reference to the System namespace because Visual Studio automatically includes the following line at the top of the code file:
using System;
The using statement tells the compiler which namespaces should be searched for classes automatically. Without this command, the namespace must be included in the code. As namespaces can have long names, this can become untidy and difficult to read. Without the using statement, conversion code would look like this:
int stringToInt = System.Convert.ToInt32("25");
Numeric Conversions with Convert
The Convert class is not only used for conversion from strings to other data types. Numeric data types may also be converted using this class rather than using casting functions. Where a floating point number is converted to an integer type, the result is rounded to the nearest whole number, unlike casting where the decimal part is truncated. However, unlike the standard rules of mathematical rounding, if the floating point number is exactly half way between two integers then the nearest even number is used.
decimal originalValue = 25.5M;
int converted = Convert.ToInt32(originalValue); // Result is 26
int casted = (int)originalValue; // Result is 25
Parse Method
The numeric data type structures provide a Parse method by which strings can be converted into numbers. This method provides extra flexibility by allowing the developer to specify different styles of numeric string that can be converted. For example, allowing the use of currency symbols or hexadecimal numbers.
The Parse method is overloaded. This means that there are several ways to call the method, each using different parameters. We will examine two of the overloads in this article. The first takes a single string parameter holding the representation of the numeric value to be converted.
string toConvert = "100";
int convertedInt = int.Parse(toConvert); // Result is 100
float convertedFloat = float.Parse(toConvert); // Result is 100.0
Using Number Styles
The simple way of calling the Parse method described above has a drawback. The string containing the number must be formatted correctly with only numeric digits. A number such as "£10,000" that is easily understood by the user causes an exception should it be parsed. To avoid this, a second parameter can be added to define the allowable number styles for the string contents.
The .NET framework provides an enumeration for the allowable number styles. An enumeration is a special value type that contains a named set of available values. It restricts the selection of values to items in this named set. Enumerations will be described in detail later in the C# Fundamentals tutorial.
The NumberStyles enumeration is defined within the System.Globalization namespace. To avoid having to type System.Globalization before every reference to NumberStyles, add a using statement to the start of the code file.
using System.Globalization;
With the using statement added, we can use the NumberStyles enumeration as a second parameter to the Parse method.
// Conversion including thousands separator
int thousands = int.Parse("1,000", NumberStyles.AllowThousands);
// Conversion of value including a decimal point
float withDecimal = float.Parse("5.50", NumberStyles.AllowDecimalPoint);
// Conversion of value including a currency symbol
// (Make sure you change the currency symbol to match your local currency)
int withCurrency = int.Parse("£5", NumberStyles.AllowCurrencySymbol);
The NumberStyles enumeration values represent individual bits in an integer value. This means that we can combine multiple styles by using the OR operator (|). For example:
// Conversion of value including a decimal point and currency symbol
float multiple = float.Parse("£5.50",
NumberStyles.AllowDecimalPoint | NumberStyles.AllowCurrencySymbol);
The enumeration also provides some useful combinations of styles as named values. The example above used two styles to allow the conversion of a currency value. We can use the Currency value of the NumberStyles enumeration to permit these styles and more.
// Conversion of a currency value
float money = float.Parse("£9,999.99", NumberStyles.Currency);
Available Number Styles
The full list of available number styles is as follows:
| Number Styles | Description | Example |
|---|
| AllowCurrencySymbol | The string may include a currency symbol. The currency symbol permitted is determined by the user's local configuration settings. | "£1500" | | AllowDecimalPoint | The string may include a single decimal point | "1500.00" | | AllowExponent | The string may be a number expressed using exponential notation. | "1.5E3" | | AllowHexSpecifier | The string may contain a hexadecimal number only. | "5DC" | | AllowLeadingSign | The string may include a leading sign indicating a positive or negative number. The sign symbols permitted are determined by the user's local configuration settings. | "-1500" | | AllowLeadingWhite | The string may include leading whitespace characters including true spaces and some control characters (Unicode characters 9 to 13). | " 1500" | | AllowParentheses | The string may include a single pair of parentheses around the number. If the parentheses are present, the number is determined to be negative. | "(1500)" | | AllowThousands | The string may include thousands separators. The separator symbol permitted is determined by the user's local configuration settings. | "1,500" | | AllowTrailingSign | The string may include a trailing sign indicating a positive or negative number. The sign symbols permitted are determined by the user's local configuration settings. | "1500-" | | AllowTrailingWhite | The string may include trailing whitespace characters. | "1500 " | | Any | The string may contain any combination of the above "Allow" number styles except for the use of hexadecimal numbers. | "1.5E3-" | | Currency | The string may contain any combination of the above "Allow" number styles except for the use of hexadecimal numbers or exponential notation. | "(£1,500.00)" | | Float | Provides a combination of the AllowDecimalPoint, AllowExponent, AllowLeadingSign, AllowLeadingWhite and AllowTrailingWhite number styles. | "-1,500.00" | | HexNumber | Provides a combination of the AllowHexSpecifier, AllowLeadingWhite and AllowTrailingWhite number styles. | " 5DC " | | Integer | Provides a combination of the AllowLeadingSign, AllowLeadingWhite and AllowTrailingWhite number styles. | " -1500" | | None | The string may include none of the "Allow" number styles. | "1500" | | Number | Provides a combination of the AllowDecimalPoint, AllowLeadingSign, AllowLeadingWhite, AllowThousands, AllowTrailingSign and AllowTrailingWhite number styles. | " -1,500.00 " |
Internationalisation (Internationalization)
The .NET framework includes a large amount of functionality relating to internationalisation (or internationalization in code). This simply means developing your software to function for all users in any part of the world using their local settings for numbers, currencies, languages, etc. This is a complex subject and beyond the scope of a tutorial for C# language basics. Generally speaking for numeric conversions you can use the above number styles to use local settings.
|