Question
How can I determine whether a string contains a valid number in C#? Is there a built-in approach similar in purpose to the old VB6 IsNumeric() function?
Short Answer
You will learn how C# parsing methods such as int.TryParse, decimal.TryParse, and double.TryParse both validate and convert numeric text safely. You will also learn why the intended numeric type and the current culture affect what counts as valid.
Concept
C# does not have one universal IsNumeric() method because valid number can mean different things:
- A whole number:
42 - A decimal amount:
19.95 - A very large or scientific value:
6.02e23 - A number written with a culture-specific separator:
19,95in some locales
Instead, .NET provides parsing methods for each numeric type. The TryParse family is usually the best choice because it attempts to convert text into a number without throwing an exception for ordinary invalid input.
if (int.TryParse(text, out int value))
{
// text is a valid Int32 and value contains the converted number.
}
else
{
// text is not a valid Int32.
}
This matters because validation alone is rarely the final goal. Applications typically need the converted value to calculate totals, save data, compare values, or call an API. TryParse validates and converts in one operation.
Mental Model
Think of TryParse as a receptionist checking an entry pass.
- The input string is a person arriving at the door.
- The target numeric type, such as
intordecimal, is the set of admission rules. TryParsechecks whether the text meets those rules.- It returns
truewhen the text is accepted and places the converted number in theoutvariable. - It returns
falsewhen the text is rejected, without causing an exception.
A string can be valid for one door but not another. For example, "12.5" can be accepted by decimal.TryParse, but it cannot be accepted by int.TryParse because an int has no fractional part.
Syntax and Examples
Use the TryParse method belonging to the numeric type you need.
string input = "125";
bool isValid = int.TryParse(input, out int quantity);
if (isValid)
{
Console.WriteLine($"Quantity: {quantity}");
}
else
{
Console.WriteLine("Enter a whole number.");
}
int.TryParse returns a bool:
true:inputis a valid integer within theintrange.false: the text is empty, contains invalid characters, has decimals, or is outside the allowed range.
Choose the type that matches your data:
string wholeText = "42";
string moneyText = "19.95";
string measurementText = "3.14159";
bool hasWholeNumber = int.TryParse(wholeText, out wholeNumber);
hasMoneyAmount = .TryParse(moneyText, moneyAmount);
hasMeasurement = .TryParse(measurementText, measurement);
Step by Step Execution
Consider this example:
string input = "27";
if (int.TryParse(input, out int age))
{
Console.WriteLine(age + 1);
}
else
{
Console.WriteLine("Age must be a whole number.");
}
Step by step:
inputstores the text"27".int.TryParseattempts to interpret that text as anint."27"is a valid whole number and fits in theintrange.- The method assigns
27toageand returnstrue. - The
ifbody runs and prints28.
Now change the input:
string input = "27 years";
The complete string is not an integer, so returns . The branch runs. It does not partially parse the ; validation requires the entire input to match the expected numeric format.
Real World Use Cases
TryParse is useful whenever numeric data begins as text:
- Form fields: Validate a user's age, quantity, or discount percentage.
- Command-line tools: Read a retry count or port number supplied as an argument.
- CSV imports: Safely convert columns such as product quantity and price.
- API requests: Validate string query parameters like
?page=3. - Configuration: Read optional numeric settings from environment variables.
- User-entered financial values: Parse an amount with
decimal.TryParseusing an explicitly chosen culture.
Real Codebase Usage
In production code, developers commonly parse at the boundary of the system: where input enters from a form, file, HTTP request, environment variable, or database text field. After successful parsing, the rest of the program works with numeric values rather than strings.
A guard clause keeps the happy path clear:
public static decimal CalculateTotal(string quantityText, string priceText)
{
if (!int.TryParse(quantityText, out int quantity) || quantity < 0)
{
throw new ArgumentException("Quantity must be a non-negative whole number.");
}
if (!decimal.TryParse(priceText, out decimal price) || price < 0)
{
throw new ArgumentException("Price must be a non-negative number.");
}
return quantity * price;
}
For external data formats, specify a culture rather than relying on the machine's current culture. For example, APIs commonly use a dot as the decimal separator:
using System.Globalization;
string apiValue = "19.95";
bool valid = .TryParse(
apiValue,
NumberStyles.Number,
CultureInfo.InvariantCulture,
amount);
Common Mistakes
Using Parse for normal validation
Parse throws FormatException when the input is invalid. That is inconvenient for expected user mistakes.
// Risky for ordinary user input:
int value = int.Parse(userInput);
Prefer:
if (!int.TryParse(userInput, out int value))
{
Console.WriteLine("Invalid whole number.");
}
Choosing the wrong numeric type
This rejects decimal input because int only accepts whole numbers:
int.TryParse("12.5", out int value); // false
Use decimal.TryParse or double.TryParse if fractions are allowed.
Ignoring range limits
A string may contain digits but still be too large for :
Comparisons
| Approach | Best use | Invalid input behavior | Result |
|---|---|---|---|
int.TryParse | Whole numbers such as counts and IDs | Returns false | int value through out |
long.TryParse | Larger whole numbers | Returns false | long value through out |
decimal.TryParse | Money and exact decimal quantities | Returns false | decimal value through |
Cheat Sheet
// Whole number
bool ok = int.TryParse(text, out int number);
// Large whole number
bool ok = long.TryParse(text, out long number);
// Currency or exact decimal amount
bool ok = decimal.TryParse(text, out decimal amount);
// Approximate measurement or scientific notation
bool ok = double.TryParse(text, out double measurement);
- Use
TryParsefor input that may be invalid. - Use
Parseonly when invalid input should be exceptional. - Use
intfor whole numbers within about ±2.1 billion. - Use
decimalfor money. - Use
doublefor approximate scientific or measurement values. TryParsereturnsfalsefor invalid text and for values outside the type's range.- For API and file formats, specify
CultureInfo.InvariantCulturewhen the format uses a dot decimal separator.
FAQ
Is there a C# equivalent of VB6 IsNumeric()?
The closest practical approach is a suitable TryParse method, such as decimal.TryParse or double.TryParse. Choose the type that represents the values your program accepts.
Should I use int.TryParse or decimal.TryParse?
Use int.TryParse when only whole numbers are valid. Use decimal.TryParse when fractions are allowed and especially for money.
Does TryParse throw an exception for invalid text?
No. It returns false for normal invalid input. This makes it appropriate for validation.
Does int.TryParse("12.0", out value) succeed?
No. 12.0 has a decimal component in its text representation, so it is not valid int input. Parse it as decimal or double if decimal input is allowed.
Can TryParse accept spaces?
Mini Project
Description
Build a small console-based order input validator. It accepts a product quantity and unit price as text, validates both values, and calculates a subtotal only after the inputs are valid. This resembles the validation required before an order can be saved or sent to an API.
Goal
Read and safely convert a non-negative whole-number quantity and a non-negative decimal price, then display the subtotal.
Requirements
Use int.TryParse to validate the quantity.|Use decimal.TryParse to validate the unit price.|Reject negative values.|Display a helpful message when either value is invalid.|Calculate the subtotal only when both values are valid.
Keep learning
Related questions
Abort Ajax Requests with jQuery jqXHR.abort()
Learn how to cancel an in-progress jQuery Ajax request with jqXHR.abort(), handle abort status safely, and avoid stale UI updates.
Access the Correct this Inside a JavaScript Callback
Learn why JavaScript this changes in callbacks and how to preserve an object context using bind, arrow functions, and event handler patterns.
Add Key-Value Pairs to JavaScript Objects
Learn how to add key-value pairs to JavaScript objects with dot and bracket notation, dynamic keys, examples, and common mistakes.