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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With