What is the C# equivalent of NaN or IsNumeric?

What is the most efficient way of testing an input string whether it contains a numeric value (or conversely Not A Number)? I guess I can use Double.Parse or a regex (see below) but I was wondering if there is some built in way to do this, such as javascript's NaN() or IsNumeric() (was that VB, I can't remember?).

public static bool IsNumeric(this string value)
{
return Regex.IsMatch(value, "^\\d+$");
}
127427 次浏览

This doesn't have the regex overhead

double myNum = 0;
String testVar = "Not A Number";


if (Double.TryParse(testVar, out myNum)) {
// it is a number
} else {
// it is not a number
}

Incidentally, all of the standard data types, with the glaring exception of GUIDs, support TryParse.

update
secretwep brought up that the value "2345," will pass the above test as a number. However, if you need to ensure that all of the characters within the string are digits, then another approach should be taken.

example 1:

public Boolean IsNumber(String s) {
Boolean value = true;
foreach(Char c in s.ToCharArray()) {
value = value && Char.IsDigit(c);
}


return value;
}

or if you want to be a little more fancy

public Boolean IsNumber(String value) {
return value.All(Char.IsDigit);
}

update 2 ( from @stackonfire to deal with null or empty strings)

public Boolean IsNumber(String s) {
Boolean value = true;
if (s == String.Empty || s == null) {
value=false;
} else {
foreach(Char c in s.ToCharArray()) {
value = value && Char.IsDigit(c);
}
} return value;
}

VB has the IsNumeric function. You could reference Microsoft.VisualBasic.dll and use it.

Yeah, IsNumeric is VB. Usually people use the TryParse() method, though it is a bit clunky. As you suggested, you can always write your own.

int i;
if (int.TryParse(string, out i))
{


}

I prefer something like this, it lets you decide what NumberStyle to test for.

public static Boolean IsNumeric(String input, NumberStyles numberStyle) {
Double temp;
Boolean result = Double.TryParse(input, numberStyle, CultureInfo.CurrentCulture, out temp);
return result;
}

In addition to the previous correct answers it is probably worth pointing out that "Not a Number" (NaN) in its general usage is not equivalent to a string that cannot be evaluated as a numeric value. NaN is usually understood as a numeric value used to represent the result of an "impossible" calculation - where the result is undefined. In this respect I would say the Javascript usage is slightly misleading. In C# NaN is defined as a property of the single and double numeric types and is used to refer explicitly to the result of diving zero by zero. Other languages use it to represent different "impossible" values.

public static bool IsNumeric(string anyString)
{
if (anyString == null)
{
anyString = "";
}


if (anyString.Length > 0)
{
double dummyOut = new double();
System.Globalization.CultureInfo cultureInfo = new System.Globalization.CultureInfo("en-US", true);
return Double.TryParse(anyString, System.Globalization.NumberStyles.Any, cultureInfo.NumberFormat, out dummyOut);
}
else
{
return false;
}
}

Maybe this is a C# 3 feature, but you could use double.NaN.

Actually, Double.NaN is supported in all .NET versions 2.0 and greater.

Simple extension:

public static bool IsNumeric(this String str)
{
try
{
Double.Parse(str.ToString());
return true;
}
catch {
}
return false;
}

I was using Chris Lively's snippet (selected answer) encapsulated in a bool function like Gishu's suggestion for a year or two. I used it to make sure certain query strings were only numeric before proceeding with further processing. I started getting some errant querystrings that the marked answer was not handling, specifically, whenever a comma was passed after a number like "3645," (returned true). This is the resulting mod:

   static public bool IsNumeric(string s)
{
double myNum = 0;
if (Double.TryParse(s, out myNum))
{
if (s.Contains(",")) return false;
return true;
}
else
{
return false;
}
}

I like the extension method, but don't like throwing exceptions if possible. I opted for an extension method taking the best of 2 answers here.

    /// <summary>
/// Extension method that works out if a string is numeric or not
/// </summary>
/// <param name="str">string that may be a number</param>
/// <returns>true if numeric, false if not</returns>
public static bool IsNumeric(this String str)
{
double myNum = 0;
if (Double.TryParse(str, out myNum))
{
return true;
}
return false;
}

You can still use the Visual Basic function in C#. The only thing you have to do is just follow my instructions shown below:

  1. Add the reference to the Visual Basic Library by right clicking on your project and selecting "Add Reference":

enter image description here

  1. Then import it in your class as shown below:

    using Microsoft.VisualBasic;

  2. Next use it wherever you want as shown below:

                if (!Information.IsNumeric(softwareVersion))
    {
    throw new DataException(string.Format("[{0}] is an invalid App Version!  Only numeric values are supported at this time.", softwareVersion));
    }
    

Hope, this helps and good luck!

I know this has been answered in many different ways, with extensions and lambda examples, but a combination of both for the simplest solution.

public static bool IsNumeric(this String s)
{
return s.All(Char.IsDigit);
}

or if you are using Visual Studio 2015 (C# 6.0 or greater) then

public static bool IsNumeric(this String s) => s.All(Char.IsDigit);

Awesome C#6 on one line. Of course this is limited because it just tests for only numeric characters.

To use, just have a string and call the method on it, such as:

bool IsaNumber = "123456".IsNumeric();

I have a slightly different version which returns the number. I would guess that in most cases after testing the string you would want to use the number.

public bool IsNumeric(string numericString, out Double numericValue)
{
if (Double.TryParse(numericString, out numericValue))
return true;
else
return false;
}

This is a modified version of the solution proposed by Mr Siir. I find that adding an extension method is the best solution for reuse and simplicity in the calling method.

public static bool IsNumeric(this String s)
{
try { double.Parse(s); return true; }
catch (Exception) { return false; }
}

I modified the method body to fit on 2 lines and removed the unnecessary .ToString() implementation. For those not familiar with extension methods here is how to implement:

Create a class file called ExtensionMethods. Paste in this code:

using System;
using System.Collections.Generic;
using System.Text;


namespace YourNameSpaceHere
{
public static class ExtensionMethods
{
public static bool IsNumeric(this String s)
{
try { double.Parse(s); return true; }
catch (Exception) { return false; }
}
}
}

Replace YourNameSpaceHere with your actual NameSpace. Save changes. Now you can use the extension method anywhere in your app:

bool validInput = stringVariable.IsNumeric();

Note: this method will return true for integers and decimals, but will return false if the string contains a comma. If you want to accept input with commas or symbols like "$" I would suggest implementing a method to remove those characters first then test if IsNumeric.

If you don't want the overhead of adding the Microsoft.VisualBasic library just for isNumeric, here's the code reverse engineered:

public bool IsNumeric(string s)
{
if (s == null) return false;


int state = 0; // state 0 = before number, state 1 = during number, state 2 = after number
bool hasdigits = false;
bool hasdollar = false;
bool hasperiod = false;
bool hasplusminus = false;
bool hasparens = false;
bool inparens = false;


for (var i = 0; i <= s.Length - 1; i++)
{
switch (s[i])
{
case char n when (n >= '0' && n <= '9'):
if (state == 2) return false; // no more numbers at the end (i.e. "1 2" is not valid)


if (state == 0) state = 1; // begin number state
hasdigits = true;
break;


case '-':
case '+':
// a plus/minus is allowed almost anywhere, but only one, and you cannot combine it with parenthesis
if (hasplusminus || hasparens) return false;


if (state == 1) state = 2; // exit number state (i.e. "1-" is valid but 1-1 is not)
hasplusminus = true;
break;


case ' ':
case '\t':
case '\r':
case '\n':
// don't allow any spaces after parenthesis/plus/minus, unless there's a $
if (state == 0 && (hasparens || (hasplusminus && !hasdollar))) return false;
if (state == 1) state = 2; // exit number state
break;


case ',':
// do not allow commas unless in the middle of the number, and not after a decimal
if (state != 1 || hasperiod) return false;
break;


case '.':
// only allow one period in the number
if (hasperiod || state == 2) return false;


if (state == 0) state = 1; // begin number state
hasperiod = true;
break;


case '$':
// dollar symbol allowed anywhere, but only one
if (hasdollar) return false;


if (state == 1) state = 2; // exit number state (i.e. "1$" is valid but "1$1" is not)
hasdollar = true;
break;


case '(':
// only allow one parens at the beginning, and cannot combine with plus/minus
if (state != 0 || hasparens || hasplusminus) return false;
hasparens = true;
inparens = true;
break;


case ')':
if (state == 1 && inparens) state = 2; // exit number state
if (state != 2 || !inparens) return false; // invalid end parens
inparens = false; // end parens mode
break;


default:
// oh oh, we hit a bad character
return false;
}
}


// must have at leats one digit, and cannot have imbalanced parenthesis
if (!hasdigits || inparens) return false;


// if we got all the way to here...
return true;
}