Consider the following function:
public enum Operator
{
EQUAL = 1,
GREATER_THAN = 2
}
public class checkString
{
public static bool isValid(string inputString, string checkString, Operator operation)
{
switch (operation)
{
case Operator.EQUAL:
if (inputString == checkString)
return true;
break;
case Operator.GREATER_THAN:
// Numeric check for greater than
try
{
double inputDouble, checkDouble;
inputDouble = Convert.ToDouble(inputString);
checkDouble = Convert.ToDouble(checkString);
if (inputDouble > checkDouble)
return true;
}
catch (Exception)
{ }
// Date check for greater than
try
{
DateTime inputDate, checkDate;
inputDate = DateTime.Parse(inputString);
checkDate = DateTime.Parse(inputString);
if (inputDate. > checkDate)
return true;
}
catch (Exception)
{ }
break;
}
return false;
}
}
Parameters
inputString: What we want to evaluate
checkString: The criteria (value) that the input must evaluate against
Operator: Enum for the operation we want to perform
Other things to know
Each line in a file is evaluated against this method to return if a condition has been met
The process of evaluating the records in the file checks line by line, in one instance that its equal to the condition. It may also check that the same line is also greater than the condition. Once the checks are done, it moves to the next record
There are no additional event listeners hooked up other than whatever defaults are in place, I am not pushing extra data to debug or trace logs
Problem
What people are going to evaluate is unknown to me at any point in this process but I need to be able to check that 'something' (regardless of what) is equal to, greater than or less than something else. Sure I check other things but I've simplified this function greatly.
That said, using EQUAL or NOT_EQUAL runs fast as can be, processing records in a very large file against said criteria pretty quick and efficiently. Once I added the GREATER_THAN logic, its slow... to the point where it takes minutes to process 20 meg files that used to take half a minute tops.
From what I can tell:
Exceptions are thrown all over the place. There is no guarantee that a field is going to be numeric or of date type. So I must attempt to cast to these data types to attempt to evaluate the condition
When exceptions are thrown, the console gets output where I have not instructed it to do so, its sort of automated
Yes I have a lack of experience in this area and am looking to learn more about exception handling and what really happens behind the scenes because when the other 80% of the records are not numeric, thats a lot of exceptions in a 20 meg, 80 thousand record file.
Is there a better way to handle the cast itself to increase efficiency? I've seen double.Parse / TryParse and can direct cast in front but am not sure which benefits the most.
Use double.TryParse and DateTime.TryParse instead of Convert.ToDouble and DateTime.Parse respectively.
Example:
double result;
if (double.TryParse(someString, out result))
{
Console.WriteLine(result);
}
else
{
// not a valid double
}
You can use TryParse() on those data types. Exceptions are messy and expensive. TryParse will return true/false if it worked or not while NOT throwing an exception. So you can just check the results of the call. Much more efficient than exceptions.
Convert.ToDouble() and Double.Parse() will throw exceptions.
try this code. It isn't the best, but it's better than what you have now considering you don't know what the type could be:
public static bool isValid(string inputString, string checkString, Operator operation)
{
double dblTmp1;
double dblTmp2;
if (Double.TryParse(inputString, out dblTmp1) && double.TryParse(checkString, out dblTmp2))
{
return Compare<Double>(dblTmp1, dblTmp1, operation);
}
DateTime dtTmp1;
DateTime dtTmp2;
if (DateTime.TryParse(inputString, out dtTmp1) && DateTime.TryParse(checkString, out dtTmp2))
{
return Compare<DateTime>(dtTmp1, dtTmp2, operation);
}
throw new InvalidOperationException("Unknown type");
}
public static bool Compare<T>(T obj1, T obj2, Operator operation) where T : IComparable
{
switch (operation)
{
case Operator.EQUAL:
{
return obj1.Equals(obj2);
}
case Operator.GREATER_THAN:
{
return obj1.CompareTo(obj2) > 0;
}
default:
{
throw new InvalidOperationException("Unknown operation");
}
}
}
Keep in mind that using exceptions slows down your program, because behind the scenes the runtime is creating an exception stack in order to be able to unwind this in case an exception is thrown. This stack is maintained regardless of whether your program throws or not, and that overhead is what slows you down the most.
The other answers are probably the best solution in this case, but in the general case you can improve your solution by catching the specific exception, which is probably NumberFormatException or ClassCastException. Catching Exception can cause all kinds of annoying, hard to trace problems (since you're not logging the exception).
Related
Sorry if this is a simple question; this is my first language and I'm trying my best to seek out and follow examples and explanations on this site and otherwise.
I've been trying to expand on a Microsoft C# tutorial program that creates "bank accounts." I'm trying to work on catching and handling exceptions, specifically by prompting the user to try again for a valid input.
I've come across this thread and many similar threads about running a loop while the input is invalid, and this example specifically using try/catch, which if I'm understanding correctly, is what I want to use here because I have a few lines of code that could throw multiple exceptions (it could be non-numerical or it could be negative). Following those and other examples, I can't figure out how to assign the initial balance input to a value that I can reference outside the loop (but still only within the CreateAccount method) once the input is valid.
I'm not sure what I have currently is working otherwise, but currently this code produces an error because initBalInput is left unassigned after the while loop, even though it's declared outside the loop and assigned in the try block.
public static void CreateAccount()
{
// Prompt for BankAccount constructor parameter {name} which is passed to BankAccount.Owner in constructor
Console.WriteLine("Name on new account: ");
string nameInput = Console.ReadLine();
decimal initBalInput;
bool valid = false;
while (valid == false)
{
try
{
Console.WriteLine("How much to deposit for initial balance: ");
initBalInput = Convert.ToDecimal(Console.ReadLine());
}
catch (ArgumentOutOfRangeException)
{
Console.WriteLine("Initial balance must be positive!");
valid = false;
continue;
}
catch (FormatException)
{
Console.WriteLine("Initial balance must be a number!");
valid = false;
continue;
}
valid = true;
}
// Create new instance "account" of type BankAccount and set its parameters
BankAccount account = new BankAccount(nameInput, initBalInput);
Console.WriteLine($"Account {account.Number} was created for {account.Owner} with {account.Balance} initial balance.");
}
Instead of catching the exceptions, write the code that handles the invalid input.
public static void CreateAccount()
{
// Prompt for BankAccount constructor parameter {name} which is passed to BankAccount.Owner in constructor
Console.WriteLine("Name on new account: ");
string nameInput = Console.ReadLine();
string initBalInput = Console.ReadLine();
// try parse will check for invalid decimal values and also, positive values can be checked
if(decimal.TryParse(initBalInput, out decimal initBal) && initBal > 0) {
// Create new instance "account" of type BankAccount and set its parameters
BankAccount account = new BankAccount(nameInput, initBal);
Console.WriteLine($"Account {account.Number} was created for {account.Owner} with {account.Balance} initial balance.");
} else {
Console.WriteLine("Invalid initial balance");
}
}
but currently this code produces an error because initBalInput is left unassigned after the while loop, even though it's declared outside the loop and assigned in the try block
The problem is that the compiler doesn't know if execution will ever reach the try block:
while (valid == false)
is evaluated at runtime. You and me both know that execution will enter at least once the while loop because valid is initially false but the compiler doesn't go into that type of analysis where variables are involved and therefore assumes execution might never enter the while loop and an unitialized initBalInput can be read.
That said, you should not get into the habit of using exepctions as control flow mechanisms. Exceptions should be exceptions, don't base the logic of your programs around exceptions. In your case, you should look into the method decimal.TryParse.
Also, always break up your problem into smaller problems. At the beginning, start small, make one liner methods that are obviously correct. It's very hard to write a bug in methods that are one or two lines long.
So what do you need?
A method that prompts the user for an input.
A method that validates the input
Something that asks the user to try again if the input is wrong.
Ok, numer one:
static string RequestUserInput(string message)
{
Console.Write(message);
return Console.ReadLine();
}
Number two: We already have it with decimal.TryParse(string, out decimal d). This method will return true if the input string can be parsed into a valid decimal number which will be assigned to d and false otherwise.
Number three:
public static decimal GetDecimalInput(string message)
{
decimal d;
while (true)
{
if (!decimal.TryParse(RequestUserInput(message), out d))
//tryparse failed, input is not a valid decimal number
Console.WriteLine("Initial balance must be a number!");
else if (d < 0) //try parse succeeded, we know input is a valid
// decimal number d but it might be negative.
Console.WriteLine("Initial balance must be positive!");
else
//we know inout is a valid non negative decimal number.
//break out of the loop, we don't need to ask again.
break;
}
return d;
}
And now, you put it all together:
var accountBalance = GetDecimalInput("How much to deposit for initial balance: ");
First, I have two articles on Exception handling that I consider required reading:
This one helps to classify the 4 common exception types - and if you should even consider catching them.
While this one goes into more details for good practices.
You should not be using convert, but parse. Or even better TryParse(). The exceptions on the string -> number conversion are the examples for vexing exceptions.
If there is no TryParse, I did once wrote a custom implementation of Int.TryParse() for someone still on Framework 1.1:
//Parse throws ArgumentNull, Format and Overflow Exceptions.
//And they only have Exception as base class in common, but identical handling code (output = 0 and return false).
bool TryParse(string input, out int output){
try{
output = int.Parse(input);
}
catch (Exception ex){
if(ex is ArgumentNullException ||
ex is FormatException ||
ex is OverflowException){
//these are the exceptions I am looking for. I will do my thing.
output = 0;
return false;
}
else{
//Not the exceptions I expect. Best to just let them go on their way.
throw;
}
}
//I am pretty sure the Exception replaces the return value in exception case.
//So this one will only be returned without any Exceptions, expected or unexpected
return true;
}
But that code looks like you want to have detailed information why it failed. At wich point you may have to write a detailed list of catch blocks.
I am doing a small project on 4x4 tic-tac-toe game. I am using Alpha Beta Search for finding the next best move. In the alpha beta search, I am using a cutoff evaluation function that is being called in "utility" function of the following algorithm
I implemented everything successfully, but the problem is the utility function doesn't return a negative value and I really don't know why! Following is the function
private static int utility(GameTreeNode gtn, bool isMin = false)
{
int nodeValue = 0;
switch (gtn.NodeBoard.getBoardStatus())
{
case Status.Success:
nodeValue = 50;
if (isMin) nodeValue = -50; /// here
break;
case Status.Incomplete:
if (isMin)
nodeValue = gtn.evaluate(State.X);
else
nodeValue = gtn.evaluate(State.O);
break;
}
// case Status.Draw:
return nodeValue;
}
isMin is set to true, when it is called from MinValue function
isMin is the move of O and the AI's move is X. If O wins the utility is supposed to return -50. But it returns only 0. I debugged the program and it actually assigns -50 to nodeValue (nodeValue changes in the debugger to -50), but when I receive in the Min or Max function, it is zero.
Note: All the int used in the entire project is signed int. No unsigned keyword is used, if you are thinking the function-caller is unsigned
The full code of alpha-beta search is here: http://pastie.org/8538015
Please friends, help as soon as possible.
Since you're using an optional parameter in your method signature, I'd caution you to pay attention to what your code is actually running when entering your function. You said you debugged it and the value gets assigned, but I don't have enough context to know if it only happens in one of many cases or not. Anyway, just be careful with those!
I would rewrite your function like this:
private static int utility(GameTreeNode gtn, bool isMin)
{
switch (gtn.NodeBoard.getBoardStatus())
{
case Status.Success:
return isMin
? -50
: 50;
case Status.Incomplete:
return isMin
? gtn.evaluate(State.X)
: gtn.evaluate(State.O);
default:
throw new NotImplementedException("The status is not implemented.");
}
}
A few improvements I see with this approach:
You don't need to store a value and return it at the end. In your case, you're always storing 50 into nodeValue when you take the Status.Success path, and then sometimes assigning -50 to it. Unless you're adamant about one return in your function, I think this approach is more clear. Might just be my opinion though.
There's a default in the switch statement so that you'll explicitly throw an exception in the case where you have a status that isn't implemented.
There is no optional parameter to your function. I don't see the benefit of making this parameter optional. In my opinion, it only looks like it's adding room to make things harder to debug.
EDIT:
Based on the code at:http://pastie.org/8538015#33,43
It looks like the only time you can ever get utility to return a negative value is when if (gtn.Nodes.Count == 0) return utility(gtn, true); is hit in the private static int MinValue(GameTreeNode gtn, int alpha, int beta) function. Otherwise, unless there's more code which you haven't posted, no other call to the utility function will hit the logical path your going for. You've mentioned when you step into there, you can see the value for nodeValue get properly assigned.
I'm suggesting you change:
// if Terminal-test(state) then return utitly(state)
if (gtn.Nodes.Count == 0) return utility(gtn, true);
gtn.Value = Globals.MAXINT;
To
// if Terminal-test(state) then return utitly(state)
if (gtn.Nodes.Count == 0)
{
int retVal = utility(gtn, true);
return retVal;
}
gtn.Value = Globals.MAXINT;
At least temporarily, and then put a breakpoint on return retVal. If your utility function is actually setting the value you expect like you say, there's no way that it could magically go away when it returns it to the MinValue function. I have a feeling something fishy is happening and the code isn't actually executing the path you expect.
Bit of a coding newbie here and looking for some advice!
I have the following method - a simple weight converter for kilograms to pounds, that's part of a larger console application. The user selects what conversion scheme they want and then they enter their weight and it will convert it. I was doing some unit tests for it to get a better understanding of them and decided to add some code that will return an exception if the user enters a minus number, just to make it more robust. The code is as follows:
public static double KilogramsToPounds(string weightInKilos)
{
//Convert parameter to a double for calculation
double kiloWeight = Double.Parse(weightInKilos);
//Convert Kilograms to Pounds
double poundWeight = kiloWeight * 2.20462;
try
{
if (kiloWeight < 0)
{
throw new ArgumentOutOfRangeException();
}
else
{
return poundWeight;
}
}
catch (ArgumentOutOfRangeException argEx)
{
Console.WriteLine(argEx);
}
return 0;
}
However, when this runs it will always return 0 because it requires a double as its return type. So you get the ArgumentOutOfRange Exception, AND a 0 because it requires a double.
I was just wondering if there was any way to basically say "if you enter a number below 0, you get this error message, but if you enter a valid positive number, you will get the correct numerical result"? Because it seems no matter what you will need to provide a numerical value for it to be happy as well as the error message, or else you will get a "Not all code paths return a value" error.
Any help is greatly appreciated.
Note - I should add the string parameter "weightInKilos" is taken from the user's console input. The code to show the choices is in a different file, and the conversion rates are in a separate file.
Remove the try-catch from your method. Just throw your exception. Your method is not supposed to catch exceptions it throws itself.
Put the try-catch around the call to KilogramsToPounds.
The key to this is that throwing an exception will stop execution of the function, thus getting you around the whole "Not all code paths return a value" error. For instance, this is valid:
public int ZeroOrError(bool error)
{
if (error)
throw new ArgumentOutOfRangeException();
else
return 0;
}
even though technically you don't return a value in the first part of the if block.
So you just need to not catch your exception (which you shouldn't be doing anyway) and you should be good to go.
I know the title is probably really hard to understand, it was hard to think of a proper title, but here's the essence of what I want to do.
Basically I want to have a method like this:
void Validate(bool validation)
{
if (!validation)
{
throw new Exception();
}
}
And then I want to call it like:
try
{
Validate(1 > 2);
}
catch (Exception e)
{
// This is where I would output the error to the user
}
I want to get the 1 > 2 part as a string without defining it as one elsewhere, or evaluating a string to a bool, or using predicates, or using external methods. Ideally this would be done via reflection. I'll also take suggestions on a better way to do what I want to do. Assume that the bool could be anything: 1 > 2, "cheese" != "ham", objectA == objectB, etc.
You can't. Well, perhaps you happen to can (in Python, one could hack something like this together, I suppose, although it wouldn't be pretty, wouldn't work reliably and would require having the source code at hand), but generally:
You don't have string repesentations of code at runtime.
Arguments (expressions) are evaluated before the function is called.
The evaluation yields nothing but a lone bool that doesn't remember the slightest bit about where it came from.
Before you're looking for some nasty nasty hack to emulate this, check if it isn't easier to add a string literal during compilation.
The closest you are going to be able to get is to use lambda expressions, which would look something to the effect of:
void Validate(Expression<Func<bool>> validation)
{
if (!Lambda.Compile(validation)())
{
string message = "..." //parse lambda expression here.
//see: http://msdn.microsoft.com/en-us/library/bb397951.aspx
throw new Exception(message);
}
}
try
{
Validate(() => 1 > 2);
}
catch (Exception e)
{
Console.Write(e.Message)// This is where I would output the error to the user
}
Though, honestly, I'm not sure it's worth the trouble, and you wouldn't want to use it in a tight loop, due to the dynamic compilation of the lambda expression (though you could possibly cache the result of the compilation if necessary)
I have written simple math function plotter in C# using Patrick Lundin´s Math free parser.
Now, my code snippet is this:
for (float value = -xaxis; value < xaxis; value += konst)
{
hash.Add("x", value.ToString());
double result = 0;
result = parser.Parse(func, hash);...
This works perfectly for functions defined on real numbers. But, when I want want to parse functions defined only on R+ for example, ln(x), naturally parser gives NaN into result.
Now, I tried to handle it thru exception handling, like so:
for (float value = -xaxis; value < xaxis; value += konst)
{
hash.Add("x", value.ToString());
double result = 0;
try{
result = parser.Parse(func, hash);
}
catch {
count = false; //just a variable I am using to draw lines
continue; // I hoped to skip the "wrong" number parsed until I came to R+ numbers
}...
But this doesen´t work, while debugging, catch is not executed at all.
Please, what am I doing wrong? Thanks.
You say that the parser returns NaN. That is not an exception, which is what a try/catch handles. So there is no exception for the catch block, hence it never being run.
Instead, you should test your result against NaN like so:
if(double.IsNaN(result))...
It sounds as if your parser is just returning NaN, not throwing an exception. You can test for NaN using the static IsNaN method:
result = parser.Parse(func, hash);
if (float.IsNaN(result)) // assuming that result is a float
{
// do something
}
else
{
// do something else
}
You can also try turning on "Check for arithmetic overflow/underflow." It is located in your project properties, under "Build->Advanced Build Settings"
When it is turned on, arithmetic exceptions will be thrown for an overflow and underflow (instead of wrapping). It may or may not apply to the ln function. Give it a try.