I have made a simple program. I want to add loop for try, catch statement, so if the user write input, he gets and error message and the program let him to write again.
Console.WriteLine("Enter The File Location");
string userValue = Console.ReadLine();
try
{
string content = File.ReadAllText(userValue);
Console.WriteLine(content);
}
catch (FileNotFoundException ex)
{
Console.WriteLine("There was a Problem");
Console.WriteLine(ex.Message);
}
catch (DirectoryNotFoundException ex)
{
Console.WriteLine("There was a Problem");
Console.WriteLine("Could not find the Directory");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.ReadLine();
You can wrap your code inside a while loop, that repeats the code until a successful operation has been completed.
var success = false;
while (success == false)
{
Console.WriteLine("Enter The File Location");
string userValue = Console.ReadLine();
try
{
string content = File.ReadAllText(userValue);
Console.WriteLine(content);
success = true;
}
catch (FileNotFoundException ex)
{
Console.WriteLine("There was a Problem");
Console.WriteLine(ex.Message);
}
catch (DirectoryNotFoundException ex)
{
Console.WriteLine("There was a Problem");
Console.WriteLine("Could not find the Directory");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
When you are able to check for invalid input, it's usually best to do that rather than let an exception happen.
In your case you can check File.Exists(...) and/or Directory.Exists(...) based on the user's input.
You could make those the conditions of your loop statement, so continue to prompt the user until they use a correct directory and file.
However, I would suggest that this is not necessarily the best user experience, as you are expecting them to know a valid file and directory, which they may not. Certainly you should provide a way for them to exit out of the loop.
I would use a while construct with a specified condition when the user input is done (when you detect an Enter keypress, or have a complete command or otherwise).
Then you can loop while that condition is not met (and there is no unrecoverable error), and use your code above to check for user errors and print messages when needed.
You don't need loop. Yuo can use Recursive function.
Try this: https://dotnetfiddle.net/4NR26P
Related
save:
try
{
s.Save();
}
catch (Exception ex) when (ex is IOException or UnauthorizedAccessException)
{
FSErrorDialog fsError = new(ex, FSVerb.Access, new FileInfo(path), Button.Retry, Button.Ignore);
if (fsError.ShowDialog().ClickedButton == Button.Retry)
{
goto save;
}
}
The Save() method saves the object to the disk.
If an exogenous exception occurs, the user is prompted to retry the operation to avoid loosing unsaved data.
I know I could use a while (true) loop with break statements but I think the goto approach is more readable. It also saves an indentation level.
I am scared of using goto.
Is this a legitimate use of goto statements?
I would suggest declaring a boolean to track if you should retry. That way you can use a do/while loop:
bool shouldRetry;
do
{
try
{
s.Save();
shouldRetry = false;
}
catch (Exception ex) when (ex is IOException or UnauthorizedAccessException)
{
FSErrorDialog fsError = new(ex, FSVerb.Access, new FileInfo(AppDirectory.Scripts.Join(s.FilePath)), Button.Retry, Button.Ignore);
shouldRetry = fsError.ShowDialog().ClickedButton == Button.Retry;
}
}
while (shouldRetry);
To address the "more readable" aspect that you mentioned in the question, I think this is more readable for 2 reasons:
We're using something that exists explicitly as a loop, so it's clear from the beginning that looping is possible. You don't need to find the goto to work out that it loops.
The variable name shouldRetry makes it abundantly clear why we are looping: because we need to retry.
I suggest infinite loop; we loop until either we have no exception or when we decide to stop our attempts:
while (true) {
try {
s.Save();
break; // No more looping (success)
}
catch (Exception ex) when (ex is IOException or UnauthorizedAccessException) {
FSErrorDialog fsError = new(ex, FSVerb.Access, new FileInfo(path), Button.Retry, Button.Ignore);
if (fsError.ShowDialog().ClickedButton != Button.Retry)
break; // No more looping (no more tries)
}
}
I have a program that reads the amount entered
If the user enters a non numeric input,
try {
number = Convert.ToDouble(input);
}
catch (Exception ex) {
Response.Redirect(Request.RawUrl);
Label1.Text = ex.Message;
}
But the exception message doesn't show when the page is refreshed. IS there a better way to do this?
Thanks.
I have this code:
try {
var bookingResult = externalService.Confirm(masterLocator, itemLocator);
}
catch (AvailabilityException)
{
ConfirmingService.SaveErrorType(itemLocator.Id,(int)ErrorType.Availability);
throw;
}
catch
{
ConfirmingService.MarkItem(confirmation.Id);
throw;
}
When I execute the program, I know that the exception is an Availability Exception because I forced the service to give me the Availability Exception, but always enters the empty catch.
What am I doing wrong? or Why always enter in the catch empty?
The problem was that the Service sent me two different AvailabilityException.
Now I catch the different AvailabilityException.
Very useful your comments
I have a line:
string[] cPathDirectories = Directory.GetDirectories(Properties.Settings.Default.customerFolderDirectory);
that will throw the error "Path is not of legal form" if the user didn't specify a search path (this setting is saved as String.Empty at this point). I would like throw this error to say, "Hey you idiot, go into the application settings and specify a valid path" instead. Is there a way to do this instead of:
...catch (SystemException ex)
{
if(ex.Message == "Path is not of legal form.")
{
MessageBox.Show("Hey you idiot, go into the application settings and specify a valid path","Error");
}
else
{
MessageBox.Show(ex.Message,"Error");
}
}
No, you need to check what the type of the exception is and catch that explicitly. Testing for strings in exception messages is a bad idea because they might change from one version of the framework to another. I'm pretty sure Microsoft doesn't guarantee that a message will never change.
In this case, looking at the docs you might be getting either a ArgumentNullException or ArgumentException, so you need to test for that in your try/catch block:
try {
DoSomething();
}
catch (ArgumentNullException) {
// Insult the user
}
catch (ArgumentException) {
// Insult the user more
}
catch (Exception) {
// Something else
}
Which exception you need here, I have no idea. You need to determine that and structure your SEH block accordingly. But always try to catch exceptions, not their properties.
Note the last catch is highly recommended; it ensures that if something else happens you won't get an unhandled exception.
you might check for an argument exception
...catch (SystemException ex)
{
if(ex is ArgumentException)
{
MessageBox.Show("Hey you idiot, go into the application settings and specify a valid path","Error");
}
else
{
MessageBox.Show(ex.Message,"Error");
}
}
That's an ArgumentException:
catch (ArgumentException) {
MessageBox.Show("Please enter a path in settings");
} catch (Exception ex) {
MessageBox.Show("An error occurred.\r\n" + ex.Message);
}
A couple ways to go about it.
First, just check the setting first before you make the GetDirectories() call:
if(string.IsNullOrEmpty(Properties.Settings.Default.customerFolderDirectory))
{
MessageBox.Show("Fix your settings!");
}
else
{
string[] cPathDirectories = Directory.GetDirectories(Properties.Settings.Default.customerFolderDirectory);
}
Or catch a more specific exception:
catch (ArgumentException ex)
{
MessageBox.Show("Hey you idiot, go into the application settings and specify a valid path","Error");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
I'd probably go with the former, since then you don't run into a penalty (albeit minor) for exception throwing and can do any other validation you want such as checking whether the path exists, etc.
If you prefer the latter, though, you can find the list of exceptions Directory.GetDirectories() throws here, so you can tailor your messages appropriately.
P.S. I also wouldn't call your users idiots, but that's between you and your god. :)
Yes, you can again throw exception from catch block, example:
catch (SystemException ex)
{
if(ex.Message == "Path is not of legal form.")
{
throw new Exception("Hey you idiot, go into the application settings and specify a valid path", ex);
}
else
{
MessageBox.Show(ex.Message,"Error");
}
}
Am just wondering how to workaround my scenario,here is my code
try
{
bool b;
foreach (string file in files)
{
#region donloadfiles
if (b = file.Contains(story))
{
try
{
logger.Info("calling xml creation Method");
baseMeta(story, XML);
logger.Info("XML created");
}
catch (Exception ex)
{ logger.Error(ex.Message); throw; }
logger.Info("calling Download Method");
Download(file, story, xml, program);
logger.Info("Download Method processed successfully");
}
#endregion
}
}
catch (Exception ex)
{ logger.Error(ex.Message); throw; }
As promised,here is my main method contains try catch block
try
{
//update the status here in DB
Status = "Closed";
Update(status);
}
catch (Exception ex)
{
Status = "Failed";
Update(status);
break;
}
i have directory "for eg:C:\" my getlist method grab all the record and pass it to my foreach loop "foreach (string file in files)" then i have a condition
if (b = file.Contains(story)) to check any of my file have the name "story" then do some logic inside.this thing works good.
Now what am trying to do is,if none of the files are matching then i have to forcefully call the catch and throw to the main catch,am doing some logic update in my main catch.
Someone please advice me how can i workaround this scenario.
Thanks in advance
what am trying to do is,if none of the files are matching then i have
to forcefully call the catch and throw to the main catch,am doing some
logic update in my main catch.
bool anyMatch = false;
foreach (.....)
{
if (b = file.Contains(story))
anyMatch = true;
}
if(!anyMatch)
throw ... //this will be caught by main catch
Keep a bool variable outside foreach loop. Set it to true if any file matches. if it is false at the end of foreach loop throw exception
Usher, using exceptions to manage process flow is a BAD idea!
Exceptions are there to manage errors, and not to handle expected conditions in your code's execution.
A much better way (in the long run:trust me on this) would be to return some value out of your method when none of the files match instead of throwing an exception.
Something like:
#region donloadfiles
if (b = file.Contains(story))
{
try
{
logger.Info("calling xml creation Method");
baseMeta(story, XML);
logger.Info("XML created");
}
catch (Exception ex)
{ logger.Error(ex.Message); throw; }
logger.Info("calling Download Method");
Download(file, story, xml, program);
logger.Info("Download Method processed successfully");
}
else return "no matches found";
#endregion
and handle the process from there once you've gotten the "no matches found" value in the place that called this method.