Related
Hello I'm making a quiz app and I want to compare user answers to the correct answers. I'm planning to do that with two string lists as I collect the answers in strings and I also have the correct answers in strings.
The problem that I'm facing is that half of the questions are True/False questions so the answers are in "True" or "False" strings, the other half are questions where a calculation has to be performed, therefore the answer is a number/double which I store as a string.
I want to give a range of answer acceptance of 0.1 so if the correct answer is 22.5 an answer of 22.6 would still be considered correct. This, however, makes it impossible to compare the value of the "number" strings with the Equals() method.
So I'm ideally looking for an if statement where I want to say:
if the element is convertible to a double convert it and check if its value is the same as the correct answer or within the acceptance range
else, check if the element is equal to the correct answer
For now I have made a console app to try and solve this problem where I have defined the two lists which look like this:
static void Main(string[] args)
{
List<string> givenAnswers = new List<string>()
{
"True","False","True","False","True",
"60","50","2.321","0.8","1.55"
};
List<string> correctAnswers = new List<string>()
{
"True","False","False","True","False",
"70","20","1.231","0.5","1.25"
};
correctAnswers.ForEach(Console.WriteLine);
Console.ReadLine();
}
The main problem is that c# doesnt return false if the element is not convertible but gives error which breaks the program.
(I was previously making the comparison on my frontend - java script where an unsuccessful conversion would return false)
Let's extract a method to compare two answers:
private static bool IsCorrectAnswer(string answer,
string expectedAnswer,
double tolerance = 0.1) {
// Let's not be peevish and tolerate leading / trimming spaces,
// ignore cases i.e. let " TRUE " be equal to "True"
if (string.Equals(answer?.Trim(),
expectedAnswer?.Trim(),
StringComparison.OrdinalIgnoreCase))
return true;
// If we have two double values, let's to parse them and compare
// with provided tolerance
if (double.TryParse(answer, out var leftValue) &&
double.TryParse(expectedAnswer, out var rightValue))
return Math.Abs(leftValue - rightValue) <= tolerance;
//TODO: you may want to add support for other types (say, dates) here
return false;
}
I didn't get your string list of booleans and numbers, but the general check would look like this:
foreach (var answer in givenAnswers)
{
if (double.TryParse(answer, NumberStyles.Any, CultureInfo.InvariantCulture, out double answerVal) && answerVal == 0.8)
{
Console.WriteLine("Nailed it!");
}
}
I had to use "invariant culture" because in my country, 0.8 is written as "0,8" and thus "0.8" is parses to 8...
I wouldn't go into lengths about the "nearby" numbers, because it's very complicated. Comparing Floating Point Numbers, 2012 Edition
You can use double.TryParse to check if a string is parsable to a double and parse it at the same time when it is.
bool IsAcceptableAnswser(string givenAnswer, string correctAnswer)
{
if (double.TryParse(correctAnswer, out var correctNumber) && double.TryParse(givenAnswer, out var givenNumber))
{
// When the answers are doubles, use use the double values.
var diff = Math.Abs(correctNumber - givenNumber);
return diff <= 0.1;
}
else
{
// When the answers aren't doubles, use string.Equals.
return string.Equals(givenAnswer, correctAnswer);
}
Notes
I used string.Equals for simplicity, but you could of course use something else to be more permissive around casing.
You might also want to check the other overloads of double.TryParse if culture is an issue.
I used 0.1 directly for readability. It would be preferable to use a constant or receive it as parameter.
Try:
var convertible = int.TryParse("60", out_)
I'm wondering what the correct way to compare two characters ignoring case that will work for all cultures. Also, is Comparer<char>.Default the best way to test two characters without ignoring case? Does this work for surrogate-pairs?
EDIT: Added sample IComparer<char> implementation
If this helps anyone this is what I've decided to use
public class CaseInsensitiveCharComparer : IComparer<char> {
private readonly System.Globalization.CultureInfo ci;
public CaseInsensitiveCharComparer(System.Globalization.CultureInfo ci) {
this.ci = ci;
}
public CaseInsensitiveCharComparer()
: this(System.Globalization.CultureInfo.CurrentCulture) { }
public int Compare(char x, char y) {
return Char.ToUpper(x, ci) - Char.ToUpper(y, ci);
}
}
// Prints 3
Console.WriteLine("This is a test".CountChars('t', new CaseInsensitiveCharComparer()));
It depends on what you mean by "work for all cultures". Would you want "i" and "I" to be equal even in Turkey?
You could use:
bool equal = char.ToUpperInvariant(x) == char.ToUpperInvariant(y);
... but I'm not sure whether that "works" according to all cultures by your understanding of "works".
Of course you could convert both characters to strings and then perform whatever comparison you want on the strings. Somewhat less efficient, but it does give you all the range of comparisons available in the framework:
bool equal = x.ToString().Equals(y.ToString(),
StringComparison.InvariantCultureIgnoreCase);
For surrogate pairs, a Comparer<char> isn't going to be feasible anyway, because you don't have a single char. You could create a Comparer<int> though.
As I understand it, there isn't really a way that will "work for all cultures". Either you want to compare characters for some kind of internal, non-displayed-to-the-user reason (in which case you should use the InvariantCulture), or you want to use the CurrentCulture of the user. Obviously, using the user's current culture will mean that you will get different results in different locales, but they will be consistent with what your users in those locales will expect.
Without knowing more about WHY you are comparing two characters, I can't really advise you on which one you should be using.
I would recommend comparing uppercase, and if they don't match then comparing lowercase, just in case the locale's uppercasing and lowercasing logic behave slightly different.
Addendum
For example,
int CompareChar(char c1, char c2)
{
int dif;
dif = char.ToUpper(c1) - char.ToUpper(c2);
if (diff != 0)
dif = char.ToLower(c1) - char.ToLower(c2);
return dif;
}
What I was thinking that would be available within the runtime is something like the following
public class CaseInsensitiveCharComparer : IComparer<char> {
private readonly System.Globalization.CultureInfo ci;
public CaseInsensitiveCharComparer(System.Globalization.CultureInfo ci) {
this.ci = ci;
}
public CaseInsensitiveCharComparer()
: this(System.Globalization.CultureInfo.CurrentCulture) { }
public int Compare(char x, char y) {
return Char.ToUpper(x, ci) - Char.ToUpper(y, ci);
}
}
// Prints 3
Console.WriteLine("This is a test".CountChars('t', new CaseInsensitiveCharComparer()));
You could try:
class Test{
static int Compare(char t, char p){
return string.Compare(t.ToString(), p.ToString(), StringComparison.CurrentCultureIgnoreCase);
}
}
But I doubt this is the "optimal" way to do it, but I'm not all of the cases you need to be checking...
string.Compare("string a","STRING A",true)
It will work for every string
I know this is an old post, but things have changed since then.
The question above can be answered by using an extension. This would extend the char.Equals to allow for locality and case insensitivity.
In an extension class, add something such as:
internal static Boolean Equals(this Char src, Char ch, StringComparison comp)
{
Return $"{src}".Equals($"{ch}", comp);
}
I'm currently at work, so can't check this, but it should work.
Andy
You can provide last argument as true for caseInsensetive match
string.Compare(lowerCase, upperCase, true);
One thing that has bothered me about C# since its release was the lack of a generic IsNumeric function. I know it is difficult to generate a one-stop solution to detrmine if a value is numeric.
I have used the following solution in the past, but it is not the best practice because I am generating an exception to determine if the value is IsNumeric:
public bool IsNumeric(string input)
{
try
{
int.Parse(input);
return true;
}
catch
{
return false;
}
}
Is this still the best way to approach this problem or is there a more efficient way to determine if a value is numeric in C#?
Try this:
int temp;
return int.TryParse(input, out temp);
Of course, the behavior will be different from Visual Basic IsNumeric. If you want that behavior, you can add a reference to "Microsoft.VisualBasic" assembly and call the Microsoft.VisualBasic.Information.IsNumeric function directly.
You can use extension methods to extend the String type to include IsInteger:
namespace ExtensionMethods
{
public static class MyExtensions
{
public static bool IsInteger(this String input)
{
int temp;
return int.TryParse(input, out temp);
}
}
}
Rather than using int.Parse, you can use int.TryParse and avoid the exception.
Something like this
public static bool IsNumeric(string input)
{
int dummy;
return int.TryParse(input, out dummy);
}
More generically you might want to look at double.TryParse.
One thing you should also consider is the potential of handling numeric string for different cultures. For example Greek (el-GR) uses , as a decimal separator while the UK (en-GB) uses a .. So the string "1,000" will either be 1000 or 1 depending on the current culture. Given this, you might consider providing overloads for IsNumeric that support passing the intended culture, number format etc. Take a look at the 2 overloads for double.TryParse.
I've used the following extension method before, if it helps at all:
public static int? AsNumeric(this string source)
{
int result;
return Int32.TryParse(source, out result) ? result : (int?)null;
}
Then you can use .HasValue for the bool you have now, or .Value for the value, but convert just once...just throwing it out there, not sure what situation you're using it for afterwards.
If you use Int32.TryParse then you don't need to wrap the call in a TryCatch block, but otherwise, yes that is the approach to take.
Not exactly crazy about this approach, but you can just call the vb.net isNumeric function from C# by adding a reference to the Microsoft.VisualBasic.dll library...
bool x= Microsoft.VisualBasic.Information.IsNumeric("123");
The other approaches given are superior, but wanted to add this for the sake of completeness.
Lot's of TryParse answers. Here's something a bit different using Char.IsNumber():
public bool IsNumeric(string s)
{
for (int i = 0; i < s.Length; i++)
{
if (char.IsNumber(s, i) == false)
{
return false;
}
}
return true;
}
Take a look on the following answer:
What is the C# equivalent of NaN or IsNumeric?
Double.TryParse takes care of all numeric values and not only ints.
Another option - LINQ!
public static class StringExtensions
{
public static bool IsDigits(this String text)
{
return !text.Any(c => !char.IsDigit(c));
}
}
Note that this assumes you only want digits 0-9. If you want to accept decimal point, sign, exponent, etc, then repalce IsDigit() with IsNumber().
I've been using the following small code snippet for years as a pure C# IsNumeric function.
Granted, it's not exactly the same as the Microsoft.VisualBasic library's IsNumeric function as that (if you look at the decompiled code) involves lots of type checking and usage of the IConvertible interface, however this small function has worked well for me.
Note also that this function uses double.TryParse rather than int.TryParse to allow both integer numbers (including long's) as well as floating point numbers to be parsed. Also note that this function specifically asserts an InvariantCulture when parsing (for example) floating point numbers, so will correctly identify both 123.00 and 123,00 (note the comma and decimal point separators) as floating point numbers.
using System;
using System.Globalization;
namespace MyNumberFunctions
{
public static class NumberFunctions
{
public static bool IsNumeric(this object expression)
{
if (expression == null)
{
return false;
}
double number;
return Double.TryParse(Convert.ToString(expression, CultureInfo.InvariantCulture), NumberStyles.Any, NumberFormatInfo.InvariantInfo, out number);
}
}
}
Usage is incredibly simple, since this is implemented as an extension method:
string myNumberToParse = "123.00";
bool isThisNumeric = myNumberToParse.IsNumeric();
public bool IsNumeric(string input)
{
int result;
return Int32.TryParse(input,out result);
}
try this:
public static bool IsNumeric(object o)
{
const NumberStyles sty = NumberStyles.Any;
double d;
return (o != null && Double.TryParse(o.ToString(), sty, null, out d));
}
You can still use the Visual Basic function in C#. The only thing you have to do is just follow my instructions shown below:
Add the reference to the Visual Basic Library by right clicking on your project and selecting "Add Reference":
Then import it in your class as shown below:
using Microsoft.VisualBasic;
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'm wondering what the correct way to compare two characters ignoring case that will work for all cultures. Also, is Comparer<char>.Default the best way to test two characters without ignoring case? Does this work for surrogate-pairs?
EDIT: Added sample IComparer<char> implementation
If this helps anyone this is what I've decided to use
public class CaseInsensitiveCharComparer : IComparer<char> {
private readonly System.Globalization.CultureInfo ci;
public CaseInsensitiveCharComparer(System.Globalization.CultureInfo ci) {
this.ci = ci;
}
public CaseInsensitiveCharComparer()
: this(System.Globalization.CultureInfo.CurrentCulture) { }
public int Compare(char x, char y) {
return Char.ToUpper(x, ci) - Char.ToUpper(y, ci);
}
}
// Prints 3
Console.WriteLine("This is a test".CountChars('t', new CaseInsensitiveCharComparer()));
It depends on what you mean by "work for all cultures". Would you want "i" and "I" to be equal even in Turkey?
You could use:
bool equal = char.ToUpperInvariant(x) == char.ToUpperInvariant(y);
... but I'm not sure whether that "works" according to all cultures by your understanding of "works".
Of course you could convert both characters to strings and then perform whatever comparison you want on the strings. Somewhat less efficient, but it does give you all the range of comparisons available in the framework:
bool equal = x.ToString().Equals(y.ToString(),
StringComparison.InvariantCultureIgnoreCase);
For surrogate pairs, a Comparer<char> isn't going to be feasible anyway, because you don't have a single char. You could create a Comparer<int> though.
As I understand it, there isn't really a way that will "work for all cultures". Either you want to compare characters for some kind of internal, non-displayed-to-the-user reason (in which case you should use the InvariantCulture), or you want to use the CurrentCulture of the user. Obviously, using the user's current culture will mean that you will get different results in different locales, but they will be consistent with what your users in those locales will expect.
Without knowing more about WHY you are comparing two characters, I can't really advise you on which one you should be using.
I would recommend comparing uppercase, and if they don't match then comparing lowercase, just in case the locale's uppercasing and lowercasing logic behave slightly different.
Addendum
For example,
int CompareChar(char c1, char c2)
{
int dif;
dif = char.ToUpper(c1) - char.ToUpper(c2);
if (diff != 0)
dif = char.ToLower(c1) - char.ToLower(c2);
return dif;
}
What I was thinking that would be available within the runtime is something like the following
public class CaseInsensitiveCharComparer : IComparer<char> {
private readonly System.Globalization.CultureInfo ci;
public CaseInsensitiveCharComparer(System.Globalization.CultureInfo ci) {
this.ci = ci;
}
public CaseInsensitiveCharComparer()
: this(System.Globalization.CultureInfo.CurrentCulture) { }
public int Compare(char x, char y) {
return Char.ToUpper(x, ci) - Char.ToUpper(y, ci);
}
}
// Prints 3
Console.WriteLine("This is a test".CountChars('t', new CaseInsensitiveCharComparer()));
You could try:
class Test{
static int Compare(char t, char p){
return string.Compare(t.ToString(), p.ToString(), StringComparison.CurrentCultureIgnoreCase);
}
}
But I doubt this is the "optimal" way to do it, but I'm not all of the cases you need to be checking...
string.Compare("string a","STRING A",true)
It will work for every string
I know this is an old post, but things have changed since then.
The question above can be answered by using an extension. This would extend the char.Equals to allow for locality and case insensitivity.
In an extension class, add something such as:
internal static Boolean Equals(this Char src, Char ch, StringComparison comp)
{
Return $"{src}".Equals($"{ch}", comp);
}
I'm currently at work, so can't check this, but it should work.
Andy
You can provide last argument as true for caseInsensetive match
string.Compare(lowerCase, upperCase, true);
If I have these strings:
"abc" = false
"123" = true
"ab2" = false
Is there a command, like IsNumeric() or something else, that can identify if a string is a valid number?
int n;
bool isNumeric = int.TryParse("123", out n);
Update As of C# 7:
var isNumeric = int.TryParse("123", out int n);
or if you don't need the number you can discard the out parameter
var isNumeric = int.TryParse("123", out _);
The var s can be replaced by their respective types!
This will return true if input is all numbers. Don't know if it's any better than TryParse, but it will work.
Regex.IsMatch(input, #"^\d+$")
If you just want to know if it has one or more numbers mixed in with characters, leave off the ^ + and $.
Regex.IsMatch(input, #"\d")
Edit:
Actually I think it is better than TryParse because a very long string could potentially overflow TryParse.
You can also use:
using System.Linq;
stringTest.All(char.IsDigit);
It will return true for all Numeric Digits (not float) and false if input string is any sort of alphanumeric.
Test case
Return value
Test result
"1234"
true
✅Pass
"1"
true
✅Pass
"0"
true
✅Pass
""
true
⚠️Fail (known edge case)
"12.34"
false
✅Pass
"+1234"
false
✅Pass
"-13"
false
✅Pass
"3E14"
false
✅Pass
"0x10"
false
✅Pass
Please note: stringTest should not be an empty string as this would pass the test of being numeric.
I've used this function several times:
public static bool IsNumeric(object Expression)
{
double retNum;
bool isNum = Double.TryParse(Convert.ToString(Expression), System.Globalization.NumberStyles.Any, System.Globalization.NumberFormatInfo.InvariantInfo, out retNum);
return isNum;
}
But you can also use;
bool b1 = Microsoft.VisualBasic.Information.IsNumeric("1"); //true
bool b2 = Microsoft.VisualBasic.Information.IsNumeric("1aa"); // false
From Benchmarking IsNumeric Options
(source: aspalliance.com)
(source: aspalliance.com)
This is probably the best option in C#.
If you want to know if the string contains a whole number (integer):
string someString;
// ...
int myInt;
bool isNumerical = int.TryParse(someString, out myInt);
The TryParse method will try to convert the string to a number (integer) and if it succeeds it will return true and place the corresponding number in myInt. If it can't, it returns false.
Solutions using the int.Parse(someString) alternative shown in other responses works, but it is much slower because throwing exceptions is very expensive. TryParse(...) was added to the C# language in version 2, and until then you didn't have a choice. Now you do: you should therefore avoid the Parse() alternative.
If you want to accept decimal numbers, the decimal class also has a .TryParse(...) method. Replace int with decimal in the above discussion, and the same principles apply.
You can always use the built in TryParse methods for many datatypes to see if the string in question will pass.
Example.
decimal myDec;
var Result = decimal.TryParse("123", out myDec);
Result would then = True
decimal myDec;
var Result = decimal.TryParse("abc", out myDec);
Result would then = False
In case you don't want to use int.Parse or double.Parse, you can roll your own with something like this:
public static class Extensions
{
public static bool IsNumeric(this string s)
{
foreach (char c in s)
{
if (!char.IsDigit(c) && c != '.')
{
return false;
}
}
return true;
}
}
If you want to catch a broader spectrum of numbers, à la PHP's is_numeric, you can use the following:
// From PHP documentation for is_numeric
// (http://php.net/manual/en/function.is-numeric.php)
// Finds whether the given variable is numeric.
// Numeric strings consist of optional sign, any number of digits, optional decimal part and optional
// exponential part. Thus +0123.45e6 is a valid numeric value.
// Hexadecimal (e.g. 0xf4c3b00c), Binary (e.g. 0b10100111001), Octal (e.g. 0777) notation is allowed too but
// only without sign, decimal and exponential part.
static readonly Regex _isNumericRegex =
new Regex( "^(" +
/*Hex*/ #"0x[0-9a-f]+" + "|" +
/*Bin*/ #"0b[01]+" + "|" +
/*Oct*/ #"0[0-7]*" + "|" +
/*Dec*/ #"((?!0)|[-+]|(?=0+\.))(\d*\.)?\d+(e\d+)?" +
")$" );
static bool IsNumeric( string value )
{
return _isNumericRegex.IsMatch( value );
}
Unit Test:
static void IsNumericTest()
{
string[] l_unitTests = new string[] {
"123", /* TRUE */
"abc", /* FALSE */
"12.3", /* TRUE */
"+12.3", /* TRUE */
"-12.3", /* TRUE */
"1.23e2", /* TRUE */
"-1e23", /* TRUE */
"1.2ef", /* FALSE */
"0x0", /* TRUE */
"0xfff", /* TRUE */
"0xf1f", /* TRUE */
"0xf1g", /* FALSE */
"0123", /* TRUE */
"0999", /* FALSE (not octal) */
"+0999", /* TRUE (forced decimal) */
"0b0101", /* TRUE */
"0b0102" /* FALSE */
};
foreach ( string l_unitTest in l_unitTests )
Console.WriteLine( l_unitTest + " => " + IsNumeric( l_unitTest ).ToString() );
Console.ReadKey( true );
}
Keep in mind that just because a value is numeric doesn't mean it can be converted to a numeric type. For example, "999999999999999999999999999999.9999999999" is a perfeclty valid numeric value, but it won't fit into a .NET numeric type (not one defined in the standard library, that is).
I know this is an old thread, but none of the answers really did it for me - either inefficient, or not encapsulated for easy reuse. I also wanted to ensure it returned false if the string was empty or null. TryParse returns true in this case (an empty string does not cause an error when parsing as a number). So, here's my string extension method:
public static class Extensions
{
/// <summary>
/// Returns true if string is numeric and not empty or null or whitespace.
/// Determines if string is numeric by parsing as Double
/// </summary>
/// <param name="str"></param>
/// <param name="style">Optional style - defaults to NumberStyles.Number (leading and trailing whitespace, leading and trailing sign, decimal point and thousands separator) </param>
/// <param name="culture">Optional CultureInfo - defaults to InvariantCulture</param>
/// <returns></returns>
public static bool IsNumeric(this string str, NumberStyles style = NumberStyles.Number,
CultureInfo culture = null)
{
double num;
if (culture == null) culture = CultureInfo.InvariantCulture;
return Double.TryParse(str, style, culture, out num) && !String.IsNullOrWhiteSpace(str);
}
}
Simple to use:
var mystring = "1234.56789";
var test = mystring.IsNumeric();
Or, if you want to test other types of number, you can specify the 'style'.
So, to convert a number with an Exponent, you could use:
var mystring = "5.2453232E6";
var test = mystring.IsNumeric(style: NumberStyles.AllowExponent);
Or to test a potential Hex string, you could use:
var mystring = "0xF67AB2";
var test = mystring.IsNumeric(style: NumberStyles.HexNumber)
The optional 'culture' parameter can be used in much the same way.
It is limited by not being able to convert strings that are too big to be contained in a double, but that is a limited requirement and I think if you are working with numbers larger than this, then you'll probably need additional specialised number handling functions anyway.
UPDATE of Kunal Noel Answer
stringTest.All(char.IsDigit);
// This returns true if all characters of the string are digits.
But, for this case we have that empty strings will pass that test, so, you can:
if (!string.IsNullOrEmpty(stringTest) && stringTest.All(char.IsDigit)){
// Do your logic here
}
You can use TryParse to determine if the string can be parsed into an integer.
int i;
bool bNum = int.TryParse(str, out i);
The boolean will tell you if it worked or not.
If you want to know if a string is a number, you could always try parsing it:
var numberString = "123";
int number;
int.TryParse(numberString , out number);
Note that TryParse returns a bool, which you can use to check if your parsing succeeded.
I guess this answer will just be lost in between all the other ones, but anyway, here goes.
I ended up on this question via Google because I wanted to check if a string was numeric so that I could just use double.Parse("123") instead of the TryParse() method.
Why? Because it's annoying to have to declare an out variable and check the result of TryParse() before you know if the parse failed or not. I want to use the ternary operator to check if the string is numerical and then just parse it in the first ternary expression or provide a default value in the second ternary expression.
Like this:
var doubleValue = IsNumeric(numberAsString) ? double.Parse(numberAsString) : 0;
It's just a lot cleaner than:
var doubleValue = 0;
if (double.TryParse(numberAsString, out doubleValue)) {
//whatever you want to do with doubleValue
}
I made a couple extension methods for these cases:
Extension method one
public static bool IsParseableAs<TInput>(this string value) {
var type = typeof(TInput);
var tryParseMethod = type.GetMethod("TryParse", BindingFlags.Static | BindingFlags.Public, Type.DefaultBinder,
new[] { typeof(string), type.MakeByRefType() }, null);
if (tryParseMethod == null) return false;
var arguments = new[] { value, Activator.CreateInstance(type) };
return (bool) tryParseMethod.Invoke(null, arguments);
}
Example:
"123".IsParseableAs<double>() ? double.Parse(sNumber) : 0;
Because IsParseableAs() tries to parse the string as the appropriate type instead of just checking if the string is "numeric" it should be pretty safe. And you can even use it for non numeric types that have a TryParse() method, like DateTime.
The method uses reflection and you end up calling the TryParse() method twice which, of course, isn't as efficient, but not everything has to be fully optimized, sometimes convenience is just more important.
This method can also be used to easily parse a list of numeric strings into a list of double or some other type with a default value without having to catch any exceptions:
var sNumbers = new[] {"10", "20", "30"};
var dValues = sNumbers.Select(s => s.IsParseableAs<double>() ? double.Parse(s) : 0);
Extension method two
public static TOutput ParseAs<TOutput>(this string value, TOutput defaultValue) {
var type = typeof(TOutput);
var tryParseMethod = type.GetMethod("TryParse", BindingFlags.Static | BindingFlags.Public, Type.DefaultBinder,
new[] { typeof(string), type.MakeByRefType() }, null);
if (tryParseMethod == null) return defaultValue;
var arguments = new object[] { value, null };
return ((bool) tryParseMethod.Invoke(null, arguments)) ? (TOutput) arguments[1] : defaultValue;
}
This extension method lets you parse a string as any type that has a TryParse() method and it also lets you specify a default value to return if the conversion fails.
This is better than using the ternary operator with the extension method above as it only does the conversion once. It still uses reflection though...
Examples:
"123".ParseAs<int>(10);
"abc".ParseAs<int>(25);
"123,78".ParseAs<double>(10);
"abc".ParseAs<double>(107.4);
"2014-10-28".ParseAs<DateTime>(DateTime.MinValue);
"monday".ParseAs<DateTime>(DateTime.MinValue);
Outputs:
123
25
123,78
107,4
28.10.2014 00:00:00
01.01.0001 00:00:00
If you want to check if a string is a number (I'm assuming it's a string since if it's a number, duh, you know it's one).
Without regex and
using Microsoft's code as much as possible
you could also do:
public static bool IsNumber(this string aNumber)
{
BigInteger temp_big_int;
var is_number = BigInteger.TryParse(aNumber, out temp_big_int);
return is_number;
}
This will take care of the usual nasties:
Minus (-) or Plus (+) in the beginning
contains decimal character BigIntegers won't parse numbers with decimal points. (So: BigInteger.Parse("3.3") will throw an exception, and TryParse for the same will return false)
no funny non-digits
covers cases where the number is bigger than the usual use of Double.TryParse
You'll have to add a reference to System.Numerics and have
using System.Numerics; on top of your class (well, the second is a bonus I guess :)
Double.TryParse
bool Double.TryParse(string s, out double result)
The best flexible solution with .net built-in function called- char.IsDigit. It works with unlimited long numbers. It will only return true if each character is a numeric number. I used it lot of times with no issues and much easily cleaner solution I ever found. I made a example method.Its ready to use. In addition I added validation for null and empty input. So the method is now totally bulletproof
public static bool IsNumeric(string strNumber)
{
if (string.IsNullOrEmpty(strNumber))
{
return false;
}
else
{
int numberOfChar = strNumber.Count();
if (numberOfChar > 0)
{
bool r = strNumber.All(char.IsDigit);
return r;
}
else
{
return false;
}
}
}
Try the regex define below
new Regex(#"^\d{4}").IsMatch("6") // false
new Regex(#"^\d{4}").IsMatch("68ab") // false
new Regex(#"^\d{4}").IsMatch("1111abcdefg")
new Regex(#"^\d+").IsMatch("6") // true (any length but at least one digit)
With c# 7 it you can inline the out variable:
if(int.TryParse(str, out int v))
{
}
Use these extension methods to clearly distinguish between a check if the string is numerical and if the string only contains 0-9 digits
public static class ExtensionMethods
{
/// <summary>
/// Returns true if string could represent a valid number, including decimals and local culture symbols
/// </summary>
public static bool IsNumeric(this string s)
{
decimal d;
return decimal.TryParse(s, System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.CurrentCulture, out d);
}
/// <summary>
/// Returns true only if string is wholy comprised of numerical digits
/// </summary>
public static bool IsNumbersOnly(this string s)
{
if (s == null || s == string.Empty)
return false;
foreach (char c in s)
{
if (c < '0' || c > '9') // Avoid using .IsDigit or .IsNumeric as they will return true for other characters
return false;
}
return true;
}
}
public static bool IsNumeric(this string input)
{
int n;
if (!string.IsNullOrEmpty(input)) //.Replace('.',null).Replace(',',null)
{
foreach (var i in input)
{
if (!int.TryParse(i.ToString(), out n))
{
return false;
}
}
return true;
}
return false;
}
Regex rx = new Regex(#"^([1-9]\d*(\.)\d*|0?(\.)\d*[1-9]\d*|[1-9]\d*)$");
string text = "12.0";
var result = rx.IsMatch(text);
Console.WriteLine(result);
To check string is uint, ulong or contains only digits one .(dot) and digits
Sample inputs
123 => True
123.1 => True
0.123 => True
.123 => True
0.2 => True
3452.434.43=> False
2342f43.34 => False
svasad.324 => False
3215.afa => False
Hope this helps
string myString = "abc";
double num;
bool isNumber = double.TryParse(myString , out num);
if isNumber
{
//string is number
}
else
{
//string is not a number
}
Pull in a reference to Visual Basic in your project and use its Information.IsNumeric method such as shown below and be able to capture floats as well as integers unlike the answer above which only catches ints.
// Using Microsoft.VisualBasic;
var txt = "ABCDEFG";
if (Information.IsNumeric(txt))
Console.WriteLine ("Numeric");
IsNumeric("12.3"); // true
IsNumeric("1"); // true
IsNumeric("abc"); // false
All the Answers are Useful. But while searching for a solution where the Numeric value is 12 digits or more (in my case), then while debugging, I found the following solution useful :
double tempInt = 0;
bool result = double.TryParse("Your_12_Digit_Or_more_StringValue", out tempInt);
Th result variable will give you true or false.
Here is the C# method.
Int.TryParse Method (String, Int32)
bool is_number(string str, char delimiter = '.')
{
if(str.Length==0) //Empty
{
return false;
}
bool is_delimetered = false;
foreach (char c in str)
{
if ((c < '0' || c > '9') && (c != delimiter)) //ASCII table check. Not a digit && not delimeter
{
return false;
}
if (c == delimiter)
{
if (is_delimetered) //more than 1 delimiter
{
return false;
}
else //first time delimiter
{
is_delimetered = true;
}
}
}
return true;
}