Best way to make a return propagate - c#

I couldn't find a answer to this, probably because I'm not asking this question in a proper way.
So, I'm writting a method that is inside a class, and at some point I want it to test for the formatting of a string. If it is not correct, I want it to show a message to the user, and to stop the execution, so that the user can fix that mistake. I have this:
if (Is not properly formated)
{
//get error information
//show error box with the formation error line
MessageBox.Show(String.Format(
"Error message{0}",
errorLine.ToString()), "Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);
return;
}
Of course, this will stop the execution of this method, but I want to stop the execution of the main method (a button click method).
What is the best way to do this in C#?

You should really be using exceptions in C#, for example
private void Calculate(string[] lines)
{
try
{
lines.ForEach(Validate);
// process lines
}
catch(InvalidArgumentException ex)
{
MessageBox.Show(...);
}
}
private void Validate(string s)
{
if(s.IsNullOrEmpty)
throw new InvalidArgumentException(/* some details here*/);
}

You could write a validation method that returns true if the value is valid, and optionally return a string telling what is wrong:
private bool Validate(string s, out string error)
{
if (string.IsNullOrEmpty(s))
{
error = "s is null";
return false;
}
else
{
error = null;
return true;
}
}
Then call it:
string error;
if (!Validate(null, out error))
{
MessageBox.Show(error);
// Do something
}
Instead of the string you could use an enum if you want to structure the list of possible errors.

Related

In C# I have implemented a custom exception, how do I now implement it?

I'm making a Tic-Tac-Toe game for an assignment and I am new to C#. I have a custom exception for bad moves called BadMoveException, which would be if the user enters anything other than 0-8. There is existing code for the assignment and I'm wondering if I should do away with the code to create my own to use this exception or if it is easy enough to implement here? Here is the code:
string input;
int position;
do
{
input = Console.ReadLine();
}
while (!int.TryParse(input, out position));
I need to catch the BadMoveException, and any others with an unknown error message. Thank you in advance!
As long as your BadMoveException inherits from Exception, then you can use it just like any other Exception, like this:
try {
//do stuff
if (badMove) {
throw new BadMoveException();
}
} catch (BadMoveException) {
//user made a bad move!!
} catch {
//something else went wrong
}
There is more information about exception handling here: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/exceptions/
Here's what I have:
1- First, your exception need to inherit from Exception like this:
public class BadMoveException : Exception { // Your code here }
2- When you have an error, you use it like this:
throw new BadMoveException(// Enter parameter if you have any in you class);
And you catch it:
try
{
if(Position < 0 || Position > 8)
{
throw new BadMoveException(// Enter parameter here if you have any);
}
else
{
// Your code here
}
}
catch(BadMoveException bmex) { // Show message here }
catch(Exception ex) { // Show other exception }
Hope it helps !
Links for documentation: http://www.tutorialsteacher.com/csharp/custom-exception-csharp
https://stackify.com/csharp-exception-handling-best-practices/

Multi checks in a try catch statement - is this okay?

Is there anything wrong with doing something like this? I am basically just trying to assert that these elements exist and if not then return false:
public static bool IsAllDataPresent()
{
try
{
Driver.Instance.FindElement(By.Id("id-a");
Driver.Instance.FindElement(By.Id("id-b");
Driver.Instance.FindElement(By.Id("id-c");
return true;
}
catch (NoSuchElementException)
{
return false;
}
}
Is this is wrong then any help would be greatly appreciated. I am new to try catch.
If there is a method that tells you what you need to know without throwing, then call it.
If there is not, then you are in what I call a "vexing exception" situation. The best way out of that situation is to write the method that is missing.
public static bool IsPresent(string id)
{
try
{
Driver.Instance.FindElement(By.Id(id);
return true;
}
catch (NoSuchElementException)
{
return false;
}
}
And now your method is sensible:
public static bool IsAllDataPresent() =>
IsPresent("id-a") && IsPresent("id-b") && IsPresent("id-c");
Notice how when you write the correct abstraction, your method bodies get nice and concise.
For your specific question about checking multiple things and using try-catch... there's no problem with that, other than if it does fail, you're throwing away the exception which would tell you which of the things was missing.
In general, if you're expecting to find elements, you should wait for them to exist. If they exist right now, no waiting is done.
Example:
WebDriverWait wait = new WebDriverWait(Driver.Instance, new TimeSpan(0,0,5));
wait.Until(ExpectedConditions.ElementExists(By.Id("id-a")));
wait.Until(ExpectedConditions.ElementExists(By.Id("id-b")));
wait.Until(ExpectedConditions.ElementExists(By.Id("id-c")));
return true;
If you don't wait, there's a risk you'll test the browser for an element which isn't there right now, but will exist in a few milliseconds time, and your script gives a premature, false negative, answer.
As you are trying to assert that these three elements exist and if not then return false you can optimize your code as per the code block below :
public static bool IsAllDataPresent()
{
if(Driver.Instance.FindElement(By.XPath("//*[#id='id-a' or #id='id-b' or #id='id-c']")).size() != 3)
{
Console.WriteLine("All the 3 elements exists")
return true;
}
else
{
Console.WriteLine("All the 3 elements doesn't exists")
return false;
}
}

Variable outside a try catch block loses value

I am having a little problem. I have a function with a string outside a try-catch-finally block that is changed depending on what happens inside the block. Once that is finished, I want to display it. My problem is that the value that was changed in the block returns to the original value it had. How can I fix this?
string error = "No issues";
try{
error = "Correct";
}catch(Exception ex){
error = "Wrong:" + ex.Message.ToString();
}finally{
// Closes connection
}
MessageBox.Show(error);
It's not clear to me, if the string in question declared outside the method. If you are 100% sure, that a new value is given to the string, the following code will probably do the problem you have:
static void Foo(string s)
{
try
{
s = "OK";
}
catch { }
}
static void Main(string[] args)
{
string temp = "??";
Foo(temp);
Console.WriteLine(temp); //prints ??
Console.ReadLine();
}
as you are passing string by value. If you need to change the value you should either:
make a ref parameter:
static void Foo(ref string s)
and call it
Foo(ref temp);
or return the new value from the method:
static string Foo(string s)
{
try
{
s = "OK";
}
catch { }
return s;
}
and call it:
temp = Foo(temp);
The code you posted will show a message box with the text
Correct
if no exceptions are thrown, otherwise the message
Wrong: (plus the exception's message property)
It will never show the message
No issues
because you overwrite the initial value of error in the first line of your try block.
error will never lose a value (as in I guess become null) given the code you post. Eventually error will go out of scope (e.g. when you exit the method that this code is defined in).
UPDATE
I took your code, created a brand-new WinForms project, double-clicked on Form1 to create a Load event handler, and posted in your code like this:
private void Form1_Load(object sender, EventArgs e)
{
string error = "No issues";
try
{
error = "Correct";
}
catch (Exception ex)
{
error = "Wrong:" + ex.Message.ToString();
}
finally
{
// Closes connection
}
MessageBox.Show(error);
}
The result was a message box that said "Correct".
If that is not what you see in your real code, you are not sharing enough code to reproduce the problem.

C# If Method Failed (Catch), DoSomething

Imagine, that u have a Method:
public void SometimesIFail(string text)
{
bool everythingOk = true;
try
{
//Anything
}
catch(Exception)
{
//Anything
everythingOk = false
}
}
Now I would like to do something like that:
foreach (String text in texts)
{
if(!SometimesIFail(text)) //If SometimesIFail() Failed (walked into Catch) Do the same for the next TEXT from the List: texts
{
SometimesIFail(text); // The Next Text - Until iterated through all the texts..
//FROM HERE ON, I HAVE A RECURSIVE CALL, THAT MEANS THAT THIS CODE, MUSTNT BE EXECUTED
//Any Code..
}
else
{
//Do Something
}
}
Whats the best way, to solve the problem?
EDIT:
After the test (Checking if it was ok), I want to do something, when it did not was OK:
foreach (String text in texts)
{
if(!SometimesIFail(text))
{
//HERE I will do SometimesIFail(text) for the next text (in foreach)
// And here is a Recursive Call which should be called, after the foreach iterated through all the texts..
}
}
Let the exception bubble up as far as possible. So remove the try/catch from the SometimesIFail method and catch the error closer to the user. Something like this:
try {
SometimesIFail();
// Do stuff
} catch {
// Tell the user an error has occurred.
}
And do consider exceptions for what they are called - they are exceptions and shouldn't be used for flow control. If there is a problem with your code that makes it crash sometimes, fix the problem instead.
I think without try catch if you solved your problem then it would be better option...
At first I thought I knew what you were looking for, then I read the comments in the code snippet, so now I'm not so sure. Here is my answer based on what I think you want. It looks like you want to check the SometimesIFail method for success and if it succeeds execute some code, if it fails you want to continue to the next iteration. Here's what I would do for that scenario:
// Don't use a void here, use a bool
public bool SometimesIFail(string text)
{
try
{
//Anything
return true;
}
catch(Exception)
{
//Anything
return false;
}
}
....
foreach (String text in texts)
{
if(SometimesIFail(text)) // Evaluates to true for success
{
// Do your success matching code
}
// There doesn't need to be an else condition if you're
// only passing to the next iteration
}
Try using this:
public bool SometimesIFail(string text)
{
try
{
//Anything
return false;
}
catch(Exception)
{
//Anything
return true;
}
}
foreach (String text in texts)
{
SometimesIFail(text);
if(SometimesIFail(text))
{
// returned true - exception was thrown
SometimesIFail(text);
}
else
{
//Do Something
}
}

Catch and Continue

I want an extension method or generic method where I want code execution to continue even there is some exception and keep recording the exceptions in a list. This is an example what I tried
public void ValidateName()
{
if (_customer.Name.Length < 5)
throw new Exception("shortname");
}
public void ValidateAge()
{
if (_customer.Age < 5)
throw new Exception("short age");
}
internal void Validate()
{
this.CatchAndContinue(delegate()
{
this.ValidateName(); // throws exception and add to list
this.ValidateAge(); // but this should also execute
});
}
public void CatchAndContinue(Action action)
{
try
{
action();
}
catch (Exception ex)
{
exceptions.Add(ex);
}
}
For current class I can pass exceptions to ValidateName and ValidateAge method, but I want if we can do the way I want, with little change in validate() method body. I know semantically it sounds weired but I need lot of places to do this. Or if there is something better to achieve it
EDIT
This validation is simple example, not in all scenerio it will be validator only. By the way in this case I want to provide UI the list of errors and why throw, because when model constructed from DB (due to wrong data in DB) such objects should not be created. These are just examples of concern
Don't use exceptions for control flow.
Instead, your validate method should return a bool, and let the client of the validate method decide what to do. One step beyond that is return a ValidationResult with a ValidationStatus property that indicates success or failure and a Message property that records the reason that validation failed.
Yield / return may be useful to you.
http://msdn.microsoft.com/en-us/library/9k7k7cf0%28v=vs.80%29.aspx
Does it have to be exceptions?
To clarify:
internal IEnumerable<string> Validate()
{
if( _customer.Age > 5 ) { yield return "Too Old"; }
if( _customer.Name.Length < 3 ) { yield return "Not enough name characters"; }
}
// using it
IEnumerable<string> errors = myCustomer.Validate();
if( errors.Length > 0 ) {
// uh oh, print out the errors!
foreach( string error in errors ) {
MsgBox(error);
}
}
Instead of throwing exceptions in the Validate methods, I would add to the exceptions list and return a bool value indicating success/failure (return part is optional, add it only if you care about the status of validation).
Something like:
public void ValidateName()
{
if (_customer.Name.Length < 5) {
LogValidationFailure("shortName"); // you can add more params if needed
return; // or return false if you need it
}
// do normal business here
}
Not only is this cleaner, it is better performing since try/catch and exception throwing are expensive.

Categories