Proper way to test if a value is numeric in C# - c#

I just need to know if the value is numeric. I don't need to do anything with the value. Is this the best way? Feel dirty creating a variable that I won't ever use beyond this:
int val;
if(int.TryParse(txtFoo.Text, out val))
{
....
}

Yes, using the relevant TryParse method and ignoring the out parameter is the best way of doing this.
You may want to wrap this up into your own set of helper methods (which could specify the appropriate culture etc, if the default isn't right for you) and just return a bool without the out parameter to make them easier to call.
Of course, you need to work out what kind of parsing is most appropriate - even for integers, you need to consider whether the range of Int32 is enough for your use case. In my experience, most numeric input has its own "natural" range of valid values, which is unlikely to be exactly the range of any predefined type. You may therefore want to expand your helper methods to include the range of valid values to accept.

"is numeric" is an ambiguous term.
Culture-aware?
Allow thousands and/or decimal separators?
Allow scientific notation?
Allow a sign (before? after?...)
What range of values do you allow? Signed 32-bit integer (Int32.TryParse), Unsigned 32-bit integer (UInt32.TryParse), decimal, double, ...
Hence there is no "best" way, and the Framework provides a multitude of different ways to parse numbers.

You can use Regular expressions
Regex _isNumber = new Regex(#"^\d+$");
_isNumber.IsMatch(txtFoo.Text);
This will only match Ints, but you can write one that also matches decimals.

It's not as flexible as int.TryParse, but you could check to see if each character is a number:
bool isInt = txtFoo.Text.All(c => char.IsNumber(c));
In general, though, I would recommend sticking with int.TryParse. You can even call the unused parameter "ignored" to be explicit about your intent, e.g.:
int ignored;
bool isInt = int.TryParse(txtFoo.Text, out ignored);

That is the recommended way of doing it in C#. However, you could also add Microsoft.VisualBasic.dll as a reference to your project and then use Microsoft.VisualBasic.Information.IsNumeric()

You can try using Regex parsing to determine that there are no non-numeric characters in a string, or you can use Int.TryParse(), Double.TryParse(), Float.TryParse() depending on the input.

bool test (string teststring)
{ for (i=0;i==teststring.length;i++){
if instr("0123456789.,-+Ee",teststring.substring(i,1) <0){return false;}
// some additional tests below here if you like
return true;
}
however E1001E12e.12e would be noted as a number a little bit more magic is needed to do a clean check, but then you might be able to determine if its a int or a float too..

That's the best way of doing it in my knowledge - that's what our company standards adhere to anyway due to the error handling being done within the parsing.
This details the advantages: https://web.archive.org/web/20150510214425/http://www.dotnetperls.com:80/int-tryparse

Related

How to use StepArgumentTransformation properly in Specflow(BDD)?

I encountered a scenario where i have to send an array of integers as parameter from specflow feature file. I could have used tables which i don't want to do as i have send as row[] or col[]. If i pass parameter as a string
eg: Given set the value as '470,471,472,472'
and receive it and do split in step definition file. How different is StepArgumentTransformation from the above scenario? Is any other benefit in using step argument transformation. I understand we can convert XML,Date or any object. Why do we have to use stepargumenttransformation???
I hope I understood the question correctly.
Specflow supports some automatic transformation out of the box, so things like converting to Date, Double, int etc etc, and it does these by default as there is no ambiguity about them. You can easily convert a string to a double or a Date as you know the locale being used.
Why isn't converting to arrays supported? I suppose it could be, but there is some ambiguity. What should the list separator be? a comma? What about locales that use that as a separator between the whole and fractional part of a number?
So providing a default implementation of something which converted a list to int[] or IEnumerable<int> could be possible, but its just likely to get some people asking why it doesn't work for them when they have used ☃ as a list separator.
It's better to leave the things with ambiguity to individuals to implement, rather than guess at the best implementation.
The StepArgumentTransformation you want is very simple to write and could be included in an external step assembly if you wanted to share it amongst many projects.
So to answer your many questions:
It's not really any different, it just encapsulates it in a single place, which is good practise, which is a benefit.
Yes you can convert any object.
You don't have to use StepArgumentTransformation, many people don't, but IMHO they make your life much easier

Why do bool.TrueString and bool.FalseString exist?

I was reading the MSDN article of the boolean structure, when I saw that a boolean has two fields: TrueString and FalseString. These respectively return "True" and "False".
After some searching, the only example I could find is in this dotnetperls article. The article states:
Programs often need these strings. TrueString and FalseString are a useful pair of readonly members. They represent truth values in string format. They provide indirection and abstraction over directly using string literals.
So appearantly it's useful for some situations. But the same article fails to provide a realistic example (IMHO anyway).
Some further reading also brought this to my attention: TrueString and FalseString are public static readonly fields. And this dornetperls article states:
The language specification recommends using public static readonly fields ... when the field is subject to change in the future.
Now this I can somewhat understand. If the .NET developers ever decide to change "True" and "False" to respectively "OkeyDokey" and "Negatory", it's smart to use TrueString and or FalseString.
But that still leaves me with the question: in what kind of scenario do you want to compare a string with the string literal of a boolean? Because appearantly: "Programs often need" them.
For the same reason that string.Empty exists. Some people prefer a semantically named value in code over a literal one.
In modern .NET (anything after .NET Framework) the following code prints True three times:
Console.WriteLine(ReferenceEquals("True", bool.TrueString));
Console.WriteLine(ReferenceEquals("False", bool.FalseString));
Console.WriteLine(ReferenceEquals("", string.Empty));
This tells us there is zero runtime difference between the literals and the fields. They are exactly the same object at runtime.
Try this for yourself on sharplab.io here.
Others have mentioned using it to compare with when parsing boolean strings, but I would not recommend that. If you want to convert a string to a bool, use bool.TryParse or bool.Parse. Using == does a case-sensitive comparison, which is probably not what you want. Furthermore, the framework's methods are optimised specifically for common cases. You can see these optimisations in the code on GitHub here: https://github.com/dotnet/runtime/blob/f8fa9f6d1554e8db291187dd7b2847162703381e/src/libraries/System.Private.CoreLib/src/System/Boolean.cs#L226
If the program stores data in a human readable file or database, it may need to store values as strings. When you read the data back in, if you know the data was written by your application and uses a standard string representation, you can compare x == bool.TrueString faster than you can bool.TryParse(x ...). You could also validate the data by making sure all values x == bool.TrueString || x == bool.FalseString
If the data was typed by humans, or a different system, TryParse is a better option, as it accepts more values as true and differentiates between a definite false and an invalid input. (MSDN Boolean TryParse)
In easy words. Boolean is a Structure. this boolean expose ToString() method which represent a human readable text for the users. So if you write some thing like.
bool b = false;
b.ToString();
the output will be the "False" insteed of 0. the "False" is readable by human and easyly being captured.
Also some where you may want to parse a text value to a boolean value. so these also can be represented as boolean values. for example. we use
Boolean.TryParse("false" ,out mybool)
the false value is being set by the Tryparse method as this finds that we can read values from strings tool.
It can be used as a default value for missing "stringly-typed" configuration parameters. Here's a concrete example I've recently used:
if (bool.Parse(ConfigurationManager.AppSettings["IsTestMode"] ?? bool.FalseString)) ...
...which is - in my humble opinion - simpler and more readable than
var isTestModeString = ConfigurationManager.AppSettings["IsTestMode"];
if (isTestModeString != null && bool.Parse(isTestModeString)) ...
(I deliberately do not use TryParse here, since I do not want to silently ignore invalid values. I want an exception to be thrown, if the configuration value is present and something other than True or False.)
There are many situations where you may need to compare if a string is equal to "True", such as checking an API response. Note: it's more efficient to compare strings but often safer to parse.
The only advantage to using the built-in properties is you won't make typos (assuming you have Intellisense) and you don't have to remember the casing (e.g. "true" instead of "True).

Efficient(?) string comparison

What could possibly be the reasons to use -
bool result = String.Compare(fieldStr, "PIN", true).Equals(0);
instead of,
bool result = String.Equals(fieldStr, "PIN", StringComparison.CurrentCultureIgnoreCase);
or, even simpler -
bool result = fieldStr.Equals("PIN", StringComparison.CurrentCultureIgnoreCase);
for comparing two strings in .NET with C#?
I've been assigned on a project with a large code-base that has abandon use of the first one for simple equality comparison. I couldn't (not yet) find any reason why those senior guys used that approach, and not something simpler like the second or the third one. Is there any performance issue with Equals (static or instance) method? Or is there any specific benefit with using String.Compare method that even outweighs the processing of an extra operation of the entailing .Equals(0)?
I can't give immediate examples, but I suspect there are cases where the first would return true, but the second return false. Two values maybe equal in terms of sort order, while still being distinct even under case-ignoring rules. For example, one culture may decide not to treat accents as important while sorting, but still view two strings differing only in accented characters as unequal. (Or it's possible that the reverse may be true - that two strings may be considered equal, but one comes logically before the other.)
If you're basically interested in the sort order rather than equality, then using Compare makes sense. It also potentially makes sense if the code is going to be translated - e.g. for LINQ - and that overload of Compare is supported but that overload of Equals isn't.
I'll try to come up with an example where they differ. I would certainly say it's rare. EDIT: No luck so far, having tried accents, Eszet, Turkish "I" handling, and different kinds of spaces. That's a long way from saying it cant happen though.

How to generically analyze data through code?

I have an XML file that contains a "script" of items to check and validate. What it does is reads in a value to check, and if that check is true, it does something. I originally wrote this to work with just integers, but I realize I need to make it work with more data types.
A sample check is like this...It sees if SomeValue is greater than 20.
<If field="SomeValue" test="#gt" value="20" />
*The field is just some string value. So for a double, the field would be something like 55.7.
All I do is do a int.TryParse on the value to see if I can cast the string (SomeValue) to an integer. If I can, I check to see if it is greater than 20. If not, I just assume false on the check.
Does anyone have any suggestions on how I could this with any data type? (i.e. string, double, DateTime)
Would Generics work? I have never used them so I dont know if they would be the best solution. Thanks.
The tricky bit is a parse when you don't know the types, but this can be done with TypeDescriptor.GetConverter:
object knownVal = 21; //perhaps obtained from reflection
Type type = typeof(int);
string text = "20";
object val = TypeDescriptor.GetConverter(type)
.ConvertFromInvariantString(text);
int rel = Comparer.Default.Compare(knownVal, val);
Generics is an option (especially with Comparer<T>.Default.Compare), but generics doesn't mix well with Type values only known at runtime. It can be done (MakeGenericType/MakeGenericMethod), but it is ugly and a bit slow.
To be honest, though: if it was me I would assume there is a small number of types that need handling here, and special-case them.

How to prohibit comma as decimal separator

I'm writing code with german culture settings
Nevertheless I would like to force the user to use the point as a decimal separator.
My piece of test code outputs the wrong value.
How do I detect the "wrong" comma ?(throw an exception)
string nok_str = "14,9";
string ok_str = "14.9";
double nok_Var1 = double.Parse(nok_str, CultureInfo.InvariantCulture.NumberFormat); // outputs 149.0
double nok_Var2 =Convert.ToDouble(nok_str, CultureInfo.InvariantCulture.NumberFormat); // outputs 149.0
First off, and please forgive me, I’d like to question your design decision:
How is this enhancing the user experience? The application should rather try to accept all unambiguous user input, not reject theoretically sound input.
That said, a number such as “19,2” will be interpreted, with an invariant culture, as having a thousands separator (which is simply discarded). This is why your code silently produces bad values. If you want to explicitly forbid this input, the easiest way to achieve this is an explicit test:
if (nok_str.Contains(","))
throw new FormatException(…);
As an alternative, you can try modifying the NumberFormatInfo.NumberGroupSeparator property of a custom NumberFormatInfo object that you pass to the Parse method.
Basically the default is to include AllowThousands in the number style. If you specify the number style you want, you can prohibit this:
using System;
using System.Globalization;
class Test
{
static void Main(string[] args)
{
string text = "19,2";
double value;
bool valid = double.TryParse(text, NumberStyles.Float,
CultureInfo.InvariantCulture,
out value);
Console.WriteLine(valid); // Prints false
}
}
Note that NumberStyles.Float is a composite style for AllowLeadingWhite, AllowTrailingWhite, AllowLeadingSign, AllowDecimalPoint, and AllowExponent - but not AllowThousands.
I am not sure what is the source of your input.
If it comes from user it also depends... If it is GUI application, you may think of restricting the input to certain possible keys, excluding comma. If it is a console app, you can try regular expressions to pre-validate input strings.
If it comes from various sources (i.e. web service) maybe simply brute-force string replace will do the trick?
Last, but not least: there are reasons for parsing to be culture-sensitive and if I were you, I would encourage users to enter valid regional number format instead forcing them to provide incorrect one.

Categories

Resources