Question

Check Whether a String Is a Valid Number in C#

javascriptvalidationnumeric

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,95 in 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 int or decimal, is the set of admission rules.
  • TryParse checks whether the text meets those rules.
  • It returns true when the text is accepted and places the converted number in the out variable.
  • It returns false when 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.

Take Quiz

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: input is a valid integer within the int range.
  • 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 int wholeNumber);
bool hasMoneyAmount = decimal.TryParse(moneyText, out decimal moneyAmount);
bool hasMeasurement = double.TryParse(measurementText, out double measurement);

For money and other exact base-10 amounts, prefer decimal. Avoid using double for currency because many decimal fractions cannot be represented exactly as binary floating-point values.

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:

  1. input stores the text "27".
  2. int.TryParse attempts to interpret that text as an int.
  3. "27" is a valid whole number and fits in the int range.
  4. The method assigns 27 to age and returns true.
  5. The if body runs and prints 28.

Now change the input:

string input = "27 years";

The complete string is not an integer, so TryParse returns false. The else branch runs. It does not partially parse the 27; 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.TryParse using an explicitly chosen culture.
Take Quiz

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 = decimal.TryParse(
    apiValue,
    NumberStyles.Number,
    CultureInfo.InvariantCulture,
    out decimal amount);

Use this pattern when a format is defined by your application, file specification, or API contract.

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 int:

bool valid = int.TryParse("999999999999", out int value); // false

Choose long, decimal, or another suitable type when your domain needs a larger range.

Assuming decimal separators are universal

"19.95" and "19,95" may be interpreted differently depending on the current culture. For stored files and APIs, parse with an explicit CultureInfo.

Using a regex when conversion is needed

A regular expression can check a particular text pattern, but it does not naturally handle numeric ranges, conversion, or culture rules. If you need a number afterward, TryParse is usually simpler and safer.

Treating double as a currency type

double is designed for approximate floating-point calculations. Use decimal for prices, invoices, and balances.

Comparisons

ApproachBest useInvalid input behaviorResult
int.TryParseWhole numbers such as counts and IDsReturns falseint value through out
long.TryParseLarger whole numbersReturns falselong value through out
decimal.TryParseMoney and exact decimal quantitiesReturns falsedecimal value through out
double.TryParseMeasurements and scientific valuesReturns falseApproximate double value through out
int.ParseInput already guaranteed to be validThrows on invalid textint value
Regular expressionEnforcing a custom text formatMatch or no matchNo converted number by itself

TryParse is the usual replacement for an IsNumeric()-style check because it answers both questions: “Is this valid for my intended type?” and “What is its numeric value?”

Take Quiz

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 TryParse for input that may be invalid.
  • Use Parse only when invalid input should be exceptional.
  • Use int for whole numbers within about ±2.1 billion.
  • Use decimal for money.
  • Use double for approximate scientific or measurement values.
  • TryParse returns false for invalid text and for values outside the type's range.
  • For API and file formats, specify CultureInfo.InvariantCulture when the format uses a dot decimal separator.
using System.Globalization;

bool ok = decimal.TryParse(
    "19.95",
    NumberStyles.Number,
    CultureInfo.InvariantCulture,
    out decimal amount);

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?

Standard parsing generally allows leading and trailing whitespace. Do not rely on this if your input format must be strict; trim or apply explicit validation rules.

Why does the same numeric string work on one computer but not another?

Parsing can use the current culture, which affects decimal and thousands separators. Use an explicit culture for shared data formats.

Should I validate with regex before calling TryParse?

Usually no. Call TryParse directly. Add a regex only when you must enforce a custom visual format that parsing alone does not express.

Take Quiz

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.

Take Quiz

Keep learning

Related questions

View more