C# "IsNumeric" Extension Method
IsNumeric Function for a Loooooooong String Value
I had a failure on some production code when testing for a Social Security Number. The code was testing string inputs provided by a file upload to ensure that they were positive numeric and exactly 9 digits long (no punctuation was allowed in the input).
That seems easy enough but one of the requirements was to try to provide as much error or validation failure information as possible. If the string wasn't exactly 9 digits that failure information should be returned to the user. In addition, if the string value did not evaluate to a numeric value, that failure information should also be returned to the user.
The problem was that if the string was not exactly 9 digits, it could be 20 digits. The code had been using an Int32.TryParse which will successfully test a value up to 2147483647.
String.IsNumeric()
After poking around, I found this solution which I think is pretty cool. I added an IsNumeric() extension method to strings and now I've got my IsNumeric() test that works! I like this solution in that there's not explicit looping:
/// <summary>
/// Tests a string value to see if it is numeric.
/// </summary>
/// <param name="s">The string to test.</param>
/// <returns>Boolean set to true if the string is numeric,
/// false otherwise.</returns>
public static bool IsNumeric( this String s )
{
// TODO: Add functionality to allow decimal, comma, sign?
return s.Length == 0 ? false : s.All( Char.IsDigit );
}
This method only tests for numeric values and does NOT allow punctuation even if the punctuation makes sense for a numeric value. This answer is based on the example from:
-- see the Jan 13 '09 at 3:35 answer by NotMe.
I found out, however, that using NotMe's answer alone gave me a "true" for an empty string. An empty string apparently evaluates to true because there are no non-numeric values in an empty string. By adding the additional conditional to test for an empty string I think I have all of the bases covered.
This extension method returns a bool and can be used in code similar to:
if( stringvalue.IsNumeric() ) { ... }
Pretty easy, eh? Oh - you will have to ensure your extension method namespace is included in the calling code's file or you can set the namespace of the file containing the extension method to "System" so that as long as you are referencing the project containing the extension method file you'll have access to the extension method.
An alternative solution could be to use the .Net BigInteger.TryParse() but I haven't given that a Try Implement yet. The BigInteger data type has been around since Visual Studio 2010 and supports arbitrary integer values according to Microsoft.
Testing the new Extension Method
I also added these tests to my Microsoft Visual Studio 2017 Test Project to test the new extension method (note that my string extensions use the "System" namespace so there is no additional using statement required):
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace UnitTests.Common.ExtensionMethods
{
[TestClass]
public class StringExtensionsTests
[TestMethod]
public void StringExtensions_IsNumeric_EmptyString()
{
// Arrange
var sut = "";
var expected = false;
// Act
var actual = sut.IsNumeric();
// Assert
Assert.AreEqual( expected, actual );
}
[TestMethod]
public void StringExtensions_IsNumeric_NonNumeric()
{
// Arrange
var sut = "12345678910111x21314151617181920";
var expected = false;
// Act
var actual = sut.IsNumeric();
// Assert
Assert.AreEqual( expected, actual );
}
[TestMethod]
public void StringExtensions_IsNumeric_Numeric()
{
// Arrange
var sut = "1234567891011121314151617181920";
var expected = true;
// Act
var actual = sut.IsNumeric();
// Assert
Assert.AreEqual( expected, actual );
}
}
}
They all pass! And, since I have unit tests available, I can now go try changing my code to the BigInteger.TryParse to see if it works.
Comments
Post a Comment