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.
Related
So I'm a student in programming and I want my code to do a try-catch on an exception but ONLY if another exception as not occured. Let me show you want I did:
using (var ctxInsert = new model())
{
CATEGORIES c1 = new CATEGORIES(6, "cat6", "category6");
Console.WriteLine("Please wait while rows are added to tables...");
//first try-catch to know if the new entry exist
try
{
ctxInsert.CATEGORIES.Add(c1);
}
catch (ModelValidationException e1)
{
Console.WriteLine(e1.Message);
Console.WriteLine("Category already exist");
}
//second try-catch to make sure saving changes to table is succesful
try
{
ctxInsert.SaveChanges();
Console.WriteLine(c1.NAME + " : Succesfuly added");
}
catch (DbEntityValidationException e)
{
Console.WriteLine(e.Message);
Console.WriteLine("not done");
}
}
Console.ReadLine();
So what I'm trying to do is that the second try-catch block only runs if the first DIDN'T catch an exception. Cause right now, like this, both try-catch runs and it doesn't make sense to save changes if the first one catches an exception.
I tried a bunch of things on my own but nothing works...
If you need just to make your code working as you expected, you can write like this:
using (var ctxInsert = new model())
{
CATEGORIES c1 = new CATEGORIES(6, "cat6", "category6");
Console.WriteLine("Please wait while rows are added to tables...");
//first try-catch to know if the new entry exist
try
{
ctxInsert.CATEGORIES.Add(c1);
ctxInsert.SaveChanges();
Console.WriteLine(c1.NAME + " : Succesfuly added");
}
catch (ModelValidationException e1)
{
Console.WriteLine(e1.Message);
Console.WriteLine("Category already exist");
}
catch (DbEntityValidationException e)
{
Console.WriteLine(e.Message);
Console.WriteLine("not done");
}
}
Console.ReadLine();
BUT, I'd rather write code without any try/catch but make exception interceptors on top level of your application (There are best practices, depending on what framework you are using)
The whole point of a try-catch is to stop an exception from preventing the rest of your code from executing. In your case, there are a few options I see off the top of my head:
Decide whether a try-catch is really what you're looking for - you could also have your method throw an exception and prevent execution of the rest of the code
Throw an exception in your catch, that way you get your logs and it tells the rest of the code that something went wrong, preventing execution
Use a variable which gets modified by the first catch, then conditionally execute the rest of the code based on that variable
Use a try-catch-finally
yes you can use the finally keyword let me show you with code example
using System;
namespace ErrorHandlingApplication {
class DivNumbers {
int result;
DivNumbers() {
result = 0;
}
public void division(int num1, int num2) {
try {
result = num1 / num2;
} catch (DivideByZeroException e) {
Console.WriteLine("Exception caught: {0}", e);
} finally {
Console.WriteLine("Result: {0}", result);
}
}
static void Main(string[] args) {
DivNumbers d = new DivNumbers();
d.division(25, 0);
Console.ReadKey();
}
}
}
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.
I'm reading information from an xml file and at some point an exception may be thrown by two Boolean.Parse() instructions
Given that the whole snippet is already under a try statement, I wanted to put all catches in one place instead of putting the two above method calls under some other try-catch.
My question is how can I know which method is throwing the exception? I have to display different error messages depending on who's failing to convert.
try
{
XmlNode db = _xml.SelectSingleNode("root/database");
string usr = db.SelectSingleNode("username").InnerText;
string psw = db.SelectSingleNode("password").InnerText;
string srvr = db.SelectSingleNode("server").InnerText;
string dbn = db.SelectSingleNode("dbname").InnerText;
//Here a FormatException can be thrown by both these Parse()
//And I need to know which is the caller in order to display the correct error message
bool clean_db = Boolean.Parse(db.Attributes["clean"].Value);
bool functions = Boolean.Parse(db.Attributes["insertFunctions"].Value);
return new DatabaseConfiguration(usr, psw, srvr, dbn, clean_db, functions);
}
catch (XPathException)
{
Console.WriteLine("<database> node is missing");
}
catch(FormatException e)
{
//Here I'm supposed to do something to get the caller
Console.WriteLine("Error message");
}
Throw an additional try/catch around each of the boolean.parse methods, then have the catch just be:
try
{
XmlNode db = _xml.SelectSingleNode("root/database");
string usr = db.SelectSingleNode("username").InnerText;
string psw = db.SelectSingleNode("password").InnerText;
string srvr = db.SelectSingleNode("server").InnerText;
string dbn = db.SelectSingleNode("dbname").InnerText;
//Here a FormatException can be thrown by both these Parse()
//And I need to know which is the caller in order to display the correct error message
bool clean_db;
try
{
clean_db = Boolean.Parse(db.Attributes["clean"].Value);
}
catch
{
throw new Exception ("clean exception");
}
bool functions;
try
{
functions = Boolean.Parse(db.Attributes["insertFunctions"].Value);
}
catch
{
throw new Exception ("function exception");
}
return new DatabaseConfiguration(usr, psw, srvr, dbn, clean_db, functions);
}
catch (XPathException)
{
Console.WriteLine("<database> node is missing");
}
catch(FormatException e)
{
//Here I'm supposed to do something to get the caller
Console.WriteLine("Error message");
}
then the outer catch will tell which line the exception came from.
then modify your outer catch to show the exception message.
Here's how Steve suggested, since he told me to update my answer :)
try
{
XmlNode db = _xml.SelectSingleNode("root/database");
string usr = db.SelectSingleNode("username").InnerText;
string psw = db.SelectSingleNode("password").InnerText;
string srvr = db.SelectSingleNode("server").InnerText;
string dbn = db.SelectSingleNode("dbname").InnerText;
//Here a FormatException can be thrown by both these Parse()
//And I need to know which is the caller in order to display the correct error message
bool clean_db = ParseDbAttributeValue(db.Attributes["clean"].Value);
bool functions = ParseDbAttributeValue(db.Attributes["insertFunctions"].Value);
return new DatabaseConfiguration(usr, psw, srvr, dbn, clean_db, functions);
}
catch (XPathException)
{
Console.WriteLine("<database> node is missing");
}
catch(FormatException e)
{
//Here I'm supposed to do something to get the caller
Console.WriteLine("Error message");
}
private bool ParseDbAttributeValue(object myValue)
{
return Boolean.Parse(myValue);
}
What about using TryParse.
The TryParse method is like the Parse method, except the TryParse method does not throw an exception if the conversion fails.
So you can simply check for failure with the returning Boolean value
bool clean_db;
if(!Boolean.TryParse(db.Attributes["clean"].Value),out clean_db)
{
// Failled
}
bool functions;
if(!Boolean.TryParse(Boolean.Parse(db.Attributes["insertFunctions"].Value,out functions)
{
// Failled
}
The MessageBox.Show call below shows "Inner". Is this a bug?
private void Throw()
{
Invoke(new Action(() =>
{
throw new Exception("Outer", new Exception("Inner"));
}));
}
private void button1_Click(object sender, EventArgs e)
{
try
{
Throw();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message); // Shows "Inner"
}
}
I had a look at the reference source for System.Windows.Forms.Control, and the code that deals with Invoke looks like this:
try {
InvokeMarshaledCallback(current);
}
catch (Exception t) {
current.exception = t.GetBaseException();
}
GetBaseException:
public virtual Exception GetBaseException()
{
Exception inner = InnerException;
Exception back = this;
while (inner != null) {
back = inner;
inner = inner.InnerException;
}
return back;
}
So apparently it's like this by design. The comments in the source offer no explanation as to why they do this.
EDIT: Some site that is now gone claims this comment came from a guy at Microsoft:
Based on the winform comfirmation in the record, our analysis is
correct of the root cause and this behavior is intended. The reason was to
prevent the user from seeing too much of the Windows.Forms internal mechanisms.
This is because the winform's default error dialog also leverages Application.ThreadException to show the exception details. .Net Winform
team trims the other exceptions information so that the default error
dialog will not display all the details to the end user.
Also, some MSFTs have sugguested to change this behavior. However, .Net
Winform team thinks that changing the exception to throw is a breaking
change and for this reason WinForms will keep sending the innermost exception to the Application.ThreadException handler.
The OP doesn't seem to be interested in a work-around. Anyhow, this is mine:
public static object InvokeCorrectly(this Control control, Delegate method, params object[] args) {
Exception failure = null;
var result = control.Invoke(new Func<object>(() => {
try {
return method.DynamicInvoke(args);
} catch (TargetInvocationException ex) {
failure = ex.InnerException;
return default;
}
}));
if (failure != null) {
throw failure;
}
return result;
}
How is it possible to resume code execution after an exception is thrown?
For example, take the following code:
namespace ConsoleApplication1
{
public class Test
{
public void s()
{
throw new NotSupportedException();
string #class = "" ;
Console.WriteLine(#class);
Console.ReadLine();
}
}
public class Program
{
public static void Main(string[] args)
{
try
{
new Test().s();
}
catch (ArgumentException x)
{
}
catch (Exception ex)
{
}
}
}
}
After catching the exception when stepping through, the program will stop running. How can I still carry on execution?
EDIT: What I specifically mean is the line Console.WriteLine(#class); does not seem to be hit, because when I run to it when in debug mode, the program exits from debug mode. I want to run to this line and stop at it.
Thanks
Well, you don't have any code after the catch blocks, so the program would stop running. Not sure what you're trying to do.
The following should be proof that the program doesn't simply "stop" after the catch blocks. It will execute code after the catch blocks if there is code to be executed:
static void Main(string[] args)
{
try
{
new Test().s();
}
catch (ArgumentException x)
{
Console.WriteLine("ArgumentException caught!");
}
catch (Exception ex)
{
Console.WriteLine("Exception caught!");
}
Console.WriteLine("I am some code that's running after the exception!");
}
The code will print the appropriate string depending on the exception that was caught. Then, it will print I am some code that's running after the exception! at the end.
UPDATE
In your edit you asked why Console.WriteLine(#class); does not seem to be hit. The reason is that you are explicitly throwing an exception in the very first line of your s() method; anything that follows is ignored. When an exception is encountered, execution stops and the exception is propagated up the call stack until the appropriate handler can handle it (this may be a catch block that corresponds to the try that wraps the statement in question within the same method, or it may be a catch block further up the call-stack. If no appropriate handler is found, the program will terminate with a stacktrace [at least in Java - not sure if the same happens in C#]).
If you want to hit the Console.WriteLine line, then you shouldn't be explicitly throwing an exception at the beginning of the method.
It sounds like you're wanting resumeable exceptions. C# doesn't do resumeable exceptions, and I'm doubtful that CLR supports them.
The purpose of throwing an exception is to abort a function and an entire operation (call stack) if/when something in the call environment (parameters, object state, global state) makes the function's operation impossible or invalid. Passing a zero param to a function that needs to divide a quantity by that param, for example. Division by zero won't produce a meaningful result, and if that's the sole purpose of the function, then the function can't return a meaningful result either. So, throw an exception. This will cause execution to jump to the nearest catch or finally block on the call stack. There is no returning to the function that threw the exception.
If you want to step into your code in the debugger to trace the Console.WriteLine() calls, you need to remove the throw new NotSupportedException() line from your code and recompile.
If you're worried that an exception will be thrown in the method but you want the method to continue, add an error handler inside the method.
class Test
{
public void s()
{
try
{
// Code that may throw an exception
throw new NotSupportedException();
}
catch(Exception ex)
{
// Handle the exception - log?, reset some values?
}
string #class = "" ;
Console.WriteLine(#class);
Console.ReadLine();
}
}
You could also return a bool or some other value to indicate the state.
Disclaimer: I am not suggesting that you actually do this.
You can mimic the old VB style On Error Resume Next with the following code.
public static class ControlFlow
{
public static Exception ResumeOnError(Action action)
{
try
{
action();
return null;
}
catch (Exception caught)
{
return caught;
}
}
}
And then it could be used like the following.
public static void Main()
{
ControlFlow.ResumeOnError(() => { throw new NotSupportedException(); });
ControlFlow.ResumeOnError(() => { Console.WriteLine(); });
ControlFlow.ResumeOnError(() => { Console.ReadLine(); });
}
Some simple code I put together to catch exceptions that are thrown inside a catch block:
try
{
//do code here
}
catch (Exception ex)
{
try { SomeMethod1(); }
catch { }
try { SomeMethod2(); }
catch { }
try { SomeMethod3(); }
catch { }
}
finally
{
//cleanup goes here
}
Execution is still carying on but there is no code after the exception is caught. If you want to repeatedly call s then consider wrapping the try/catch block in a while loop.
The program stops running because there is no following code to be executed in the Main() method! You can add the following line to your code to keep the program running until there is a console input:
Console.ReadLine();
For that code, you can't. If you break the tasks up to smaller chunks, you can resume at the next chunk. But normally it's easier to have a different mechanism than exceptions to report non-fatal errors, such as a callback function which returns whether or not to continue.
You can use the "step-over" feature in debugging to achieve this on a per-run basis.
Instead of thowing the NotSupportedException, you could track that an exception was encountered, use a default value, and throw the exception at the end of the method call:
namespace ConsoleApplication1
{
public class Test
{
public void s()
{
bool exceptionEncountered = false;
if(someConditionNotSupported){//stub condition
exceptionEncountered=true
#class="DefaultValue";
}
Console.WriteLine(#class);
Console.ReadLine();
if(exceptionEncountered){
throw new NotSupportedException();
}
}
}
public class Program
{
public static void Main(string[] args)
{
try
{
new Test().s();
}
catch (ArgumentException x)
{
}
catch (Exception ex)
{
}
}
}
}
public static void Main()
{
for (int j = 0; j <= 100000; j++)
{
try
{
// TODO: Application logic...
}
catch
{
System.Threading.Thread.Sleep(1000);
}
}
}