How to use TryParse in Code Contracts without getting warning - c#

When using Code Contracts I get the warning:
Detected call to method
'System.Int32.TryParse(System.String,System.Int32#)' without [Pure] in
contracts of method
Having a class with interface and code contracts defined on the inteface like the code below. The question is how to check that the string orgNumberWithoutControlDigit can be converted to an valid integer, as it's a prereq for the modulus to work?
public string getControlDigit(string orgNumberWithoutControlDigit)
{
List<int> orgNumberNumbers = this.getNumberList(orgNumberWithoutControlDigit);
List<int> productList = orgNumberNumbers.Zip(this.weightNumberList, (first, second) => first * second).ToList();
int modular = productList.Sum() % 11;
string controlDigit = getControlDigit(modular);
return controlDigit;
}
private static string getControlDigit(int modular)
{
string controlDigit;
if (modular == 0)
{
controlDigit = "0";
}
else if (modular == 1)
{
controlDigit = "-";
}
else
{
int result = 11 - modular;
controlDigit = result.ToString();
}
return controlDigit;
}
[ContractClass(typeof(CalculateOrgNumberControlDigitBusinessContract))]
public interface ICalculateOrgNumberControlDigitBusiness
{
string getControlDigit(string orgNumberWithoutControlDigit);
}
[ContractClassFor(typeof(ICalculateOrgNumberControlDigitBusiness))]
public abstract class CalculateOrgNumberControlDigitBusinessContract:ICalculateOrgNumberControlDigitBusiness
{
public string getControlDigit(string orgNumberWithoutControlDigit)
{
Contract.Requires(orgNumberWithoutControlDigit.Length == 8);
int parseResult;
Contract.Requires(int.TryParse(orgNumberWithoutControlDigit, out parseResult));
Contract.Ensures(parseResult >= 0);
var result = Contract.Result<string>();
Contract.Ensures(result != null && result.Length == 1);
return default(string);
}
}

I understand what you want to achieve, but I would say that passing orgNumberWithoutControlDigit as a string to getControlDigit [sic] is the real culprit here.
Even if you could make your contract to work - the caller must also convert the string to int in order to satisfy your contract. Now if the caller already have made that conversion to an int, why not let it pass that int instead?
I am a huge fan of Code Contracts and use it in most of my projects, and I have learned that it is not a silver bullet. So if you have to have a string parameter, remove the contract altogether and simply make sure your string is in a valid format before use.
Maybe an OrgNumberValidator helper would be a better choice than relying on contracts for this?
EDIT: Actually, I would recommend creating an OrgNumber class for handling them.

You can create a pure helper method instead of calling int.TryParse directly:
[Pure]
private static bool IsInt(string s)
{
int n;
return int.TryParse(s, out n);
}
You could go further and wrap the TryParse in a try block, returning false if any type of exception is thrown (just to be on the safe side).
However, I tend to share Michael's opinion that you would do better by avoiding passing strings about to represent integers if you can.

Related

Is there a way to create a Pass-By-Reference list of managed-type variables?

edit; Based on responses, I may have been unclear in my final goal. I've updated the last section.
Situation
I have a number of variables which I need to perform the same operation on. In this case, they are strings, and can at the point we reach this code have the value null, "", "Blank", or they could already have an assigned other value that I want to keep.
if (String.IsNullOrEmpty(MyVar1) || "Blank".Equals(MyVar1))
MyVar1 = null;
if(String.IsNullOrEmpty(MyVar2) || "Blank".Equals(MyVar2))
MyVar2 = null;
...
if(String.IsNullOrEmpty(MyVar10) || "Blank".Equals(MyVar10))
MyVar10 = null;
Being a programmer that wants to keep my code clean and this block drives me mad, I'm looking for a way to create a list of these variables, and perform this same if statement + null assignment on each.
For an example, here's what I'd like to do:
MyVar1 = "Blank";
DreamDataStructure varList = new DreamDataStructure() { MyVar1, MyVar2, ..., MyVar10 };
foreach(ref string MyVar in varList)
{
if(String.IsNullOrEmpty(MyVar) || "Blank".Equals(MyVar))
MyVar = null;
}
Console.WriteLine(MyVar1); //Should now be null
What Doesn't Work
1) Because my variables are strings, I can't do something like this.
var myListOfVariables = new[] { &MyVar1, &MyVar2, ..., &MyVar10 };
If I could, I'd be able to foreach over them as expected. Because string is a managed type though, it cannot be passed by reference like this.
2) Similarly, if I just made a List<string> of the variables, they would be passed by value and wouldn't help my case.
3) These variables can't be wrapped in an outer object type, as they need to be used as strings in a large number of places in a legacy application. Assume that it would be too large an effort to change how they're used in every location.
Question
Is there a way to iterate over string (or other managed type) variables in a pass-by-reference way that will allow me to put the entire operation inside of a loop and reduce the duplication of code that's happening here?
The goal here is that I can use the original variables later on in my code with the updated values. MyVar1, etc, are referenced later on already by legacy code which expects them to be null or have an actual value.
If I understand your question correctly, I don't think what you want to do is possible. Please see this question: Interesting "params of ref" feature, any workarounds?
The only thing I can suggest (which I know doesn't answer your question) is creating a method to avoid duplication of your conditional logic:
void Convert(ref string text)
{
if (string.IsNullOrEmpty(text) || "Blank".Equals(text))
{
text = null;
}
}
You could create a function instead of passing references, which would also be more readable.
string Validate(string inputString)
{
return string.IsNullOrEmpty(inputString) || "Blank".Equals(inputString) ? null : inputString;
}
<...>
MyVar1 = Validate(MyVar1);
Update:
Now I get what you're trying to do. You have a bunch of variables, and you want to perform some sort of bulk operation on them without changing anything else. Putting them in a class isn't an option.
In that case you're really stuck operating on them one at a time. There are ways to shorten it, but you're pretty much stuck with the repetition.
I'd
create a string SanitizeString(string input) function
type x = SanitizeString(x); once for each variable
copy and paste the variable names to replace x.
It's lame, but that's about all there is.
Perhaps this would be a better approach. It ensures that the values are always sanitized. Otherwise you can't easily tell whether the values have been sanitized or not:
public class MyValues
{
private string _value1;
private string _value2;
private string _value3;
public string Value1
{
get { return _value1; }
set { _value1 = Sanitize(value); }
}
// repeat for other values
private string Sanitize(string input) =>
string.IsNullOrEmpty(input) || string.Equals("Blank", input) ? null : input;
}
That's one option. Another is to sanitize the inputs earlier. But ideally we want to ensure that a given class is always in a valid state. We wouldn't want to have an instance of a class whether the values may or may not be valid. It's better to ensure that they are always valid.
ref doesn't really factor into it. We don't need to use it often, if ever. With a value type or string we can just return a new value from a function.
If we're passing a reference type and we want to make changes to it (like setting its properties, adding items to a list) then we're already passing a reference and we don't need to specify ref.
I'd try to write methods first without using ref and only use it if you need to. You probably never will because you'll succeed at whatever you're trying to do without using ref.
Your comment mentioned that this is a legacy app and it's preferable not to modify the existing class. That leaves one more option - reflection. Not my favorite, but when you say "legacy app" I feel your pain. In that case you could do this:
public static class StringSanitizer
{
private static Dictionary<Type, IEnumerable<PropertyInfo>> _stringProperties = new Dictionary<Type, IEnumerable<PropertyInfo>>();
public static void SanitizeStringProperties<T>(T input) where T : class
{
if (!_stringProperties.ContainsKey(typeof(T)))
{
_stringProperties.Add(typeof(T), GetStringProperties(typeof(T)));
}
foreach (var property in _stringProperties[typeof(T)])
{
property.SetValue(input, Sanitize((string)property.GetValue(input)));
}
}
private static string Sanitize(string input)
{
return string.IsNullOrEmpty(input) || string.Equals("Blank", input) ? null : input;
}
private static IEnumerable<PropertyInfo> GetStringProperties(Type type)
{
return type.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(property => property.PropertyType == typeof(string) && property.CanRead && property.CanWrite);
}
}
This will take an object, find its string properties, and sanitize them. It will store the string properties in a dictionary by type so that once it has discovered the string properties for a given type it won't have to do it again.
StringSanitizer.SanitizeStringProperties(someObject);
you can simply use a string[] and get the changes back to the caller method like this.
public Main()
{
var myVar1 = "Blank";
var myVar2 = "";
string myVar3 = null;
var myVar4 = "";
string[] dreamDataStructure = new string[] { myVar1, myVar2, myVar3, myVar4 };
}
private void ProcessStrings(string[] list)
{
for(int i = 0; i < list.Length; i++)
{
if (String.IsNullOrEmpty(list[i]) || "Blank".Equals(list[i]))
list[i] = null;
}
}

How to handle/Convert "" in C#

In C# Convert.ToInt32() and any method of Convert class can handle null values but all these method not handling "" as input. Throws an error "input string not in correct format"
Is there any way to handle/Convert "" to its specific value? like
Convert.ToInt32("") convert to 0
Convert.ToDecimal("") convert to 0.0
with out using if conditions
Thanks.
The POD classes in C# have a method just for this reason:
Int32.TryParse
You could even write an extension method to make this easier for you:
public static class Extensions {
public static decimal MyDecimalParse(this string val) {
decimal ret = decimal.Zero;
decimal.TryParse(val, out ret);
return ret;
}
} // eo class extension
Try int.TryParse
int i;
bool b = int.TryParse("", out i);
Console.WriteLine(b);
There isn't anything inherent in the frameworks that do this for you. It probably doesn't make sense for the entire community to understand "" as defaulting to 0 or 0.0 as you would want. I would recommend writing your own method that does what you specifically want.
Something to the effect of:
public class MyConvert
{
public static int ToInt32(string input)
{
return String.IsNullOrEmpty(input) ? 0 : Convert.ToInt32(input);
}
}
I realize you don't want to do the if check but you will have to check it one way or another (either by checking .IsNullOrEmpty or .TryParse), so abstracting it into your own convert method at least means you don't have to do it every time.

C# - better ways to validate if a string is a number other than int.TryParse()?

I find myself often needing to use int.TryParse() to test if a value is an integer. However, when using TryParse, I have to pass a reference variable to the function. So I find myself always needing to create a temp int to be passed in. Usually it looks something like:
int my_temp_integer;
int.TryParse(potential_integer, my_temp_integer);
I find this to be quite cumbersome considering that all I want is a simple true/false response, and I don't care about the actual parsed result. Is there a better way to approach this? Why isn't there an overloaded function where I can just pass the value I want to test and get a true/false response?
Thanks.
you could write an extension method:
public static bool IsInt(this string pString)
{
int value;
return int.TryParse(pString, out value);
}
then your example becomes:
potential_integer.IsInt();
EDIT:
Lately I have been using a generic form of this.
public delegate bool TryParser<T>(string pString, out T pResult);
public static bool Is<T>(this string pString, TryParser<T> pTryParser)
{
T val;
return pTryParser(pString, out val);
}
Can then use it as follows; it's not perfect, but it's more concise than anything I've found:
"1234".Is<int>(int.TryParse); // true
"asdf123".Is<int>(int.TryParse); // false
"1.2345".Is<float>(float.TryParse); // true
"1000".Is<byte>(byte.TryParse); // false
Theoretically, this would also work with custom TryParse methods, as long as you followed the same pattern as the official ones.
Update: If you maintain a static dictionary of TryParse methods by type, you can avoid having to ever directly pass the method. The dictionary can even be populated as needed with reflection.
A simple solution is to create an extension method.
public static class StringExtensions {
public static bool IsInt(this string s) {
int i; return Int.TryParse(s, out i);
}
}
Then you just use it as so:
string s = "123";
if (s.IsInt())
// do something.
if you don't want to actually convert the string, only test it, then you can use Regex
something kinda like this (you may need to adjust this to fit your needs):
public bool IsInt(this string inputData)
{
Regex isNumber = new Regex(#"^\d+$");
Match m = isNumber.Match(inputData);
return m.Success;
}
You could use
bool isInt = str.TrimEnd( new char[] {'0','1','2','3','4','5','6','7','8','9'})
.Length == 0;
A shorter alternative to Muad'Dib above:
bool IsInt(string input)
{
return new System.Text.RegularExpressions.Regex(#"^\d$").IsMatch(input);
}
/Hans

C# converting a decimal to an int safely

I am trying to convert a decimal to an integer safely.
Something like
public static bool Decimal.TryConvertToInt32(decimal val, out int val)
this will return false if it cannot convert to an integer, and true w/ successful output if it can.
This is to avoid catching the OverflowException in decimal.ToInt32 method. What is the easiest way to do this?
Here:
public static bool TryConvertToInt32(decimal val, out int intval)
{
if (val > int.MaxValue || val < int.MinValue)
{
intval = 0; // assignment required for out parameter
return false;
}
intval = Decimal.ToInt32(val);
return true;
}
I would write an extension method for class decimal like this:
public static class Extensions
{
public static bool TryConvertToInt32(this decimal decimalValue, out int intValue)
{
intValue = 0;
if ((decimalValue >= int.MinValue) && (decimalValue <= int.MaxValue))
{
intValue = Convert.ToInt32(decimalValue);
return true;
}
return false;
}
}
You can use it in that way:
if (decimalNumber.TryConvertToInt32(out intValue))
{
Debug.WriteLine(intValue.ToString());
}
Compare the decimal against int.MinValue and int.MaxValue prior to the conversion.
What's wrong with using Int32.TryParse(string) ?
Why are you trying to avoid catching the OverflowException? It is there for a reason and you should totally catch it where you call Decimal.ToInt32(). Exceptions are used widely throughout the framework and users should catch them. The Try methods can help you around them to make code tighter and cleaner, but where the framework doesn't have a suitable method (Decimal.TryConvertToInt32() in this case) catching OverflowException is the appropriate thing to do. It is actually more clear than making an extension class or writing your own separate static method (both of those involve writing your own code where the framework is already giving you this functionality).

Lack of IsNumeric function in C#

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!

Categories