Continue the try even excepted - c#

A few days ago I asked a question on this site, but I think the people who shared their time to help me (thank you to them) did not really realize my point of view. Here is the link Catch and Continue? C#
They thought I wanted to end the try-catch, and continue with the rest of the code. But I don't
That is my question but more reformed:
I want to get a try-catch, but I need the try to the end even it returns an exception. like this:
// I thought a perfect example with math for this case.
// It is possible to divide a number with negative and positive numbers
// but it is not possible to divide a number by zero, So
// 5/5= 1 // ok
// 5/4= 1.25 // ok
// 5/3= 1.66666666667 // ok
// 5/2= 2.5 // ok
// 5/1= 5 // ok
// 5/0= Math Error // Oh, this is an error so I stop the try here.
// 5/-1= -5 // foo
// 5/-2= -2.5 // foo
// 5/-3= -1.66666666667 // foo
// 5/-4= -1.25 // foo
// 5/-5= -1 // foo
// foo = This is not a error, but I will not do it because the previous error
What I need here is to "ignore" that exception and continue try-catch (divide all positive and negative numbers by ignoring division by zero.) How can I do it?
This is just a clear example for my problem, I know someone would say to put all the "numbers" in a listbox and remove what I do not want however my original code always returns the same exception
With undefined results (both can be x as y can be).
(Is not a critical exception such as lack of memory or capacity, is a simple exception that will not make any logical problem, so there is no problem ignoring the exception)
Thank You!

I think this is what you want:
foreach(var x = 5; x > -5; x--)
{
try
{
// Do the math here
}
catch(Exception)
{
// Log/Print exception, just don't throw one or the loop will exit
}
}
The code above will continue processing even if an exception occurs.

try { operation1(); } catch { }
try { operation2(); } catch { }
try { operation3(); } catch { }
...
As a side note, if you find yourself wanting to do this, chances are your design pattern is flawed.

Related

Implementing a while loop to check for multiple exceptions in input validity

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.

Take a Console.ReadLine(); input and put it into a List<Int32>? [duplicate]

This question already has answers here:
How to input in an integer array
(8 answers)
Closed 3 years ago.
heres a snip of some of what I have.C#FrameworkConsole app
namespace Arraylab
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Please guess a number, zero if you must.");
int guessedNumber = 1;
try
{
guessedNumber = Convert.ToInt32(Console.ReadLine());
}
catch (Exception)
{
Console.WriteLine("You did not make the right entry. Please hit Enter and try again.");
Console.ReadLine();
Environment.Exit(0);
}
//This will end the program if its not a number that is entered.
List<Int32> guessedNumbers = new List<int>;
guessedNumbers.AddRange(guessedNumber); //It wont accept this guessedNumber varriable.
}
}
}
First: instead of ConvertTo.Int32 and catching the exception, the better practice is to use int.TryParse, which returns false if the string cannot be parsed. You can then eliminate the try. Remember it is always better to avoid an exception than to catch an exception.
Second, if you are going to use exception handling, "pokemon handling" -- gotta catch them all -- is a bad practice when you know what exception you're expecting. Catch the specific exception.
It wont accept this guessedNumber variable.
guessedNumbers.AddRange(guessedNumber);
AddRange adds a sequence of elements to a list, not a single element. Use Add to add a single element to the end of a list.
Use add instead of addrange. This will accept an int
Edit: how is this not a correct answer?

Prioritization of IF-ELSE / TRY-CATCH and First() vs Single()

So, I've been having a little bit of an argument with a fellow coder lately. Specifically: We've been arguing about the proper use of Try / Catch and If / Else as well as First() / Single() in a specific scenario.
Variation #1 - His approach
var items = Search(dto.number); // Returns a List of Objects
if (items.Count = 1)
{
wPerson = items.First();
}
else
{
return;
}
Variation #2 - I changed his code to this.
var items = Search(dto.number); // Returns a List of Objects
try
{
wPerson = items.Single();
}
catch
{
// Handle exception
return;
}
We expect the result of var items = Search(dto.number); to always be 1.
The Question:
Which changes were nescessary? I am trying to defend my point of view below. Please correct me.
First of all: The Single(). I always try to be as specific as possible and I decided on the following rules:
First --> Accepts N
FirstOrDefault --> Accepts 0 and N
Single --> Accepts 1
SingleOrDefault --> Accepts 0 and 1
First() may have worked but it wasn't 100% specific, so I considered it wrong since we had an option to be even more specific.
Secondly: Try / Catch vs If / Else. Since I had already changed First() to Single(), I considered the if statement to be redundant. Yes. I know that Try / Catch is less performant than the If statement but we expect to have NOTHING BUT 1 result. And if we get more or less, I expect it to be a mistake and with Try / Catch I'd actually treat it that way.
Am I so off here?
Well, throwing / catching exceptions is for exceptional situation only, so your current code
try {
wPerson = items.Single();
}
catch {
// Something is very wrong (e.g. RDBMS table's ruined, file's corrupted etc)
throw;
}
means that you expect one and only one wPerson in items. If, however, 0, 1, or 2 item in items is expected behaviour
you should not use Single, but, say, Take
var items = Search(dto.number); // Returns a List of Objects
var wPersons = items.Take(2).ToArray();
if (wPersons.Length <= 0) {
// No person found; probably, wPerson = some_default_value
...
}
else if (wPersons.Length == 1) {
// Exactly one person found
wPerson = wPersons[0];
...
}
else {
// Two or more persons found; we have to resolve tie somehow
...
}
Don't try/catch if you can avoid it. An exception should be used to "exceptional flow", iE: not to be expected.
However I'd suggest you combine both of the variations.
var items = Search(dto.number); // Returns a List of Objects
if (items.Count != 1) return;
wPerson = items.Single();
Since you expect only 1 result if successful, you can immediately break.
If, for any reason, you change your code and there are x > 1 items this method will break since you only expect 1 (hence the Single) and not go into an "unexceptional" flow (assuming the First object is the correct object)

Trying to return an exception error when the method requires a double

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.

C# error handling (NaN)

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.

Categories

Resources