Let's say that I have a class in my dll file:
public ClassInDllFile()
{
String str = "";
try
{
str = someClassMethod();
}
catch (Exception e) // or more precised exception type
{
// some code
}
}
I don't want to put exception message in MessageBox from Dll level (it requires additional references), but I would to pass it to some (on example) WinForm application.
You can just catch the exception in the WinForms class.
This means you should not catch the exception here, but in the WinForms class itself, where you can show a dialog.
You could use something like (I changed a bit of code from your example to improve naming):
public ClassInDllFile()
{
# Other functions
///
/// Might throw a ... exception
///
public Run()
{
String str = someClassMethod(); # Might cause an exception
# More code
}
And in your WinForms class:
var instance = ClassInDllFile()
try
{
instance.Run()
}
catch (Exception e) // or more precised exception type
{
// Error handling code
}
# More code
Also it is a good idea to document the ClassInDllFile.Run function which type of exceptions it might generate to inform calling functions to act upon it.
There are several ways in which you could handle this.
One simple way is to just throw the exception, and handle it in the outer / calling class.
Another is to gather info from the exception in your catch clause (like ExceptionMessage, StackTrace, and perhaps InternalException), and store these in properties that the the calling class can check. You might then also include a boolean property like Suceeded, which you set to false if an exception occurs. Then the calling class can check that property after making the call, and retrieve more details about the exception if it needs them.
You can manipulate this however you want. Experiment until you find a solution that fits your needs.
Related
What is the correct way to determine exactly what caused an exception, to correct it?
Consider the code below. I attempt to parse a string of XML, but occasionally, the incoming XML will not be top-level, meaning it needs to be surrounded by a root element.
Which this happens, the parser throws an XmlException, but it could throw that for a lot of reasons. I want to catch this one specific reason.
I do this, which I concede is probably not great:
var doc = new XmlDocument();
try
{
doc.LoadXml(xml);
}
catch(XmlException e)
{
if(e.Message.Contains("multiple root elements"))
{
doc.LoadXml($"<root>{xml}</root>");
}
else
{
throw e;
}
}
This feels like a hack. What is the correct way to do this?
There is a new feature of C# that allows you to filter exceptions in the catch clause with when keyword:
try
{
}
catch (XmlException ex) when ( ex.Message.Contains(...) )
{
//handle
}
You can use multiple fields to recognize the exception type, like the InnerException, StackTrace, and Data. As #David Hruška suggests, the HResult property is also a good place to check to recognize the type of the exception
The Message is not the best property to use for the check, as it is usually localized for the built-in types and as a result might look different with other culture setting.
you can try to make a switch for XmlException.HResult as described here:
https://msdn.microsoft.com/en-us/library/system.xml.xmlexception(v=vs.110).aspx
The only thing I am not sure, if it points the the specific exception type (like XmlException) or specific exception "message".
If this does not help, I think you have no other option than checking for message.
EDIT: Also, as was pointed above, you should throw; instead of throw e; as the second clears the StackTrace. ReSharper also warns about this one.
There are multiple ways to achieve what you're trying to do.
Different test frameworks bring their own tools to help with this too.
For example, if you're using MSVS Test Framework, the simplest option is to only check for the exception type. In this case you just mark the test method with "ExceptedExceptionAttribute" and specify the expected exception type to be thrown from the method, as follows:
[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void Action_ThrowsException()
{
// test logic here
}
There is another constructor available, which allows to specify the exact exception message as the second parameter, which is rarely used. You can find the documentation for ExpectedExceptionAttribute in MSDN.
Another option, where you have more control, would be what was already suggested in the other answers, which can be encapsulated in a helper method as follow:
private static T Throws<T>(Action action) where T : Exception
{
try
{
action();
Assert.Fail();
}
catch (T ex)
{
// This exception was expected.
return ex;
}
}
Using this helper method, you now can have your test method as follows:
[TestMethod]
public void Action_ThrowsException()
{
// test logic here
ArgumentException aex = Throws<ArgumentException>(()=>{
// Test logic here
});
Assert.AreEqual("Expected error message", aex.Message);
}
As you can see, this option provides you with higher flexibility as you can now validate other aspects of the exception explicitly.
FYI: The second solution is given as part of the xUnit framework.
In C# I'm trying to modify the StackTrace property of a custom exception I created. For this, I just override the StackTrace getter and it seems to be working (Exception has it as a virtual method, so it should work). This is my custom exception:
class CustomTimeoutException : Exception
{
private string oldStack;
public CustomTimeoutException(string message, String stack)
: base(message)
{
oldStack = stack;
}
public override string StackTrace
{
get
{
return oldStack;
}
}
public override string Message
{
get
{
return "lalalala2";
}
}
public override System.Collections.IDictionary Data
{
get
{
return null;
}
}
}
I'm using this class the following way:
class Program
{
static void Main(string[] args)
{
try
{
Program p = new Program();
p.throwTimeout2();
}
catch(TimeoutException e)
{
CustomTimeoutException tor = new CustomTimeoutException(e.Message + "with more", e.StackTrace);
Console.WriteLine(tor);
Console.WriteLine(tor.StackTrace);
throw tor;
}
}
public void throwTimeout2()
{
throwTimeout();
}
public void throwTimeout()
{
throw new TimeoutException("this is a message ");
}
}
When I write the property StackTrace to the console, it prints the StackTrace of the TimeoutException, which means it's in fact overriding it. But, when the console shows the error, the StackTrace is not the one it gets from my property, yet the Message is the one it gets from the Message property I'm also overriding.
So, where does the console get the StackTrace of the exception from? I'm using Visual Studio for running.
(Note: one thing I still really don't understand about your question is that, while you seem to be asking for a way to affect how an exception is reported to the console, you also say that you have some "tool" that apparently has access to the Exception object itself and is reporting on the inner-most exception, i.e. following the InnerException property chain until it reaches the last one. These two statements seem to be in contradiction with each other, so I'm not really sure I completely understand the question. Still, I spent some time looking into it, and will share what I have regardless. :) .)
IMHO, there is not a good way to do what you want. There is an ugly way (see below), but I don't recommend it. Especially since your main limitation is the "tool that uses the message"; it is IMHO a very bad idea to go changing production code just to suit some tool. That path leads to big maintenance headaches, if not outright buggy code.
If you really must change the exception message, you should just bite the bullet and toss the entire stack trace text you want to preserve into the message as well. Trying to mess around with the stack trace of the eventually-thrown exception itself is bad news.
That said…
If you were to add diagnostic calls to Console.WriteLine() to your method overrides, you would confirm (as you've probably already guessed) that the StackTrace property is not called when the exception is re-thrown and reported by the CLR to the console. Overriding the property is not going to help.
There are at least two problems with trying that strategy:
The StackTrace property is just a string containing formatted information about the stack trace. The Exception object does actually contain a private field _stackTrace. When you execute the throw statement with an Exception object, the CLR stores the current stack trace information into this field. You would have to find some way to overwrite this field after the fact, to fake a throw site different from the actual one.
The CLR exception handling leverages existing Windows exception handling infrastructure. One of the first things that happens when an exception is thrown is the exception handling code attempts to find a handler up the stack. If it fails to find one, then you get the "Unhandled Exception:" message. But note that in the process, the stack has not been unwound. Thus, the exception handling code does not even need to inspect the Exception object at all to determine the throw site; the stack is still there, and its state can be reported directly. There is literally nothing you can do with the Exception object that would affect reporting, if indeed the exception handling code is looking directly at the stack state.
Now, as it happens, for the version of .NET I'm running on my Windows 8.1 machine, it appears that the CLR is reporting the stack trace as stored in the Exception object and not directly inspecting the stack, per option #2 above. So something like this actually works:
ExceptionWrapper class
class ExceptionWrapper : Exception
{
private readonly string _trace;
private readonly string _message;
private readonly string _toString;
private readonly object _stackTrace;
public ExceptionWrapper(Exception e)
{
_trace = e.StackTrace;
_message = e.Message + ", wrapped";
_toString = e.ToString();
_stackTrace = typeof(Exception).GetField("_stackTrace",
BindingFlags.NonPublic | BindingFlags.Instance).GetValue(e);
}
public override string StackTrace { get { return _trace; } }
public override string Message
{
get
{
typeof(Exception)
.GetField("_stackTrace", BindingFlags.NonPublic | BindingFlags.Instance)
.SetValue(this, _stackTrace);
return _message;
}
}
public override string ToString() { return _toString; }
}
Test program
class Program
{
static void Main(string[] args)
{
try
{
M1();
}
catch (Exception e)
{
throw;
}
}
private static void M1()
{
try
{
M();
}
catch (Exception e)
{
throw new ExceptionWrapper(e);
}
}
static void M()
{
throw new Exception("test exception");
}
}
There is a very significant caveat though. This works only because of two specific facts:
The CLR is not taking advantage of the current stack state, but instead is trusting the Exception object to contain correct stack information in the _stackTrace field.
The CLR calls the Message getter of the Exception object before retrieving the stack trace. This gives the object an opportunity to overwrite the _stackTrace field before the CLR accesses it for the purpose of reporting the stack trace.
Both of these are, as near as I can tell, completely undocumented implementation details. The second one in particular is very fragile; while I can see why the CLR might always have to stick with the first detail, I see no reason at all that Microsoft (never mind other implementors of the CLS) should feel compelled to preserve the behavior in the second point.
Writing code that relies on these implementation details is just asking for trouble. Whatever the broader goal here is, I simply cannot imagine it would be worthwhile to suffer the risk of breaking your project for this need. IMHO, it would be much more reasonable to simply rewrite this "tool" you are trying to accommodate.
Tools are (or at least should be) inherently simple in nature, and not only would rewriting it allow you to produce the results you want without mucking around with private implementation details in third-party code, it would also give you the chance to a) add new features, such as providing options for controlling how to process exception data (e.g. looking at something other than the inner-most exception), and b) have a tool for which you do have the source code, with which you can make further improvements in the future.
I strongly advise that you not paint yourself into this particular corner. :)
I have some code that currently looks somewhat like this:
public void MainFunction()
{
try
{
SomeProblemFunction();
}
catch
{
AllFineFunction();
}
}
private void SomeProblemFunction() { ... }
private void AllFineFunction() { ... }
As you can see, I'm currently wrapping the call to SomeProblemFunction around a try statement because that function could fail (it relies on an outside web service call).
My question is this: should the try statement be a) outside the problem function (like I have it now) or b) inside the problem function?
Thanks.
Typically you want to allow your exceptions propagate up to your application boundaries. You're only going to want to do one of a few things with your exception:
Wrap it
Replace it
Let it propagate
Update
From your question it seems that you are looking for a fault tolerant solution for your web service calls. This is a more complex problem than simply "where do I put my try-catch?" You would still place your exception handling at the application boundary, but there you would implement your fault tolerance strategy. This would need to have many considerations, including asynchronously calling your web service, number of retry attempts, etc. I would suggest doing a search for web service fault tolerance.
What you have is correct; see the MSDN example:
public class ThrowTestB
{
static void Main()
{
try
{
// TryCast produces an unhandled exception.
TryCast();
}
catch (Exception ex)
{
// Catch the exception that is unhandled in TryCast.
Console.WriteLine
("Catching the {0} exception triggers the finally block.",
ex.GetType());
// Restore the original unhandled exception. You might not
// know what exception to expect, or how to handle it, so pass
// it on.
throw;
}
}
public static void TryCast()
{
int i = 123;
string s = "Some string";
object obj = s;
try
{
// Invalid conversion; obj contains a string, not a numeric type.
i = (int)obj;
// The following statement is not run.
Console.WriteLine("WriteLine at the end of the try block.");
}
finally
{
// Report that the finally block is run, and show that the value of
// i has not been changed.
Console.WriteLine("\nIn the finally block in TryCast, i = {0}.\n", i);
}
}
// Output:
// In the finally block in TryCast, i = 123.
// Catching the System.InvalidCastException exception triggers the finally block.
// Unhandled Exception: System.InvalidCastException: Specified cast is not valid.
}
As a rule of thumb I try and build code that focuses try catches to the exact spot the problem may occur.
That said both of your solutions are correct.
If it were my code I would do this
public void MainFunction()
{
try
{
SomeProblemFunction();
}
catch(Exception e)
{
Messagebox.Show(e.Message);
}
}
private void SomeProblemFunction() {
try{
web call
}
catch{
throw a specific exception related to this spot
}
}
private void AllFineFunction() { ... }
With this method you can easily create applications that handle a slew of very accurate exceptions
A fine question, I think. I'll attempt an answer.
If you want to recover within SomeProblemFunction, then it would make perfect sense to move the try...catch inside of that method. If, however, you are comfortable saying that if anything fails in SomeProblemFunction, then the whole thing is a failure, then keep it as you have it now and recover in (or throw from) MainFunction.
Thanks to the comment below, I'm adding some clarity. Depending on the specific exception that is being thrown within SomeProblemFunction, you may not have the ability to recover within that method. If you have a mixture of recoverable and non-recoverable, then it would be prudent to have the try...catch in both places.
The most important thing is that you NEVER catch an exception from which you cannot recover without throwing it on after doing your thing. It's tempting to add big broad catches (catch (Exception)) to avoid your app crashing during development, but it is never worth it. If those things make it into your production code, you've introduced a problem-solving and debugging nightmare.
In my opinion, there is no straight answer for this. The try catch is used to handle the exceptions that may occur. If your exception handling code is going in the main function then you should have the try catch in the main function. If your exception handling code in the problem function then you should add it to the problem function.
My preference though is to put it in both functions. If you put the try catch in the problem function, you can throw the exception and catch it in the main function. This always appear to other developers that the exception was thought of in that function and not missed handling it by mistake.
This depends on how severe this web service call failure would be.
Is it a failure that would prevent further processing of your code to run? If so, have no try/catch here, allowing it to propagate up to the guy who needs to know that this web service call failed. Optionally, you could still catch and throw a new exception with some more meaningful Exception type/ details.
Do you simply just want to re-try the web service call again if it doesn't work? IF so, then you have the try in the correct place; you just need to add a loop.
Is it not a big deal if this web service call fails? e.g. - will the rest of your code work OK? (I've found this to be uncommon). If so, leave the try/catch where it is, and log the error somewhere so that you're alerted.
I have a problem running a Gurobi Optimization Model using a C#/.NET library through IronPython.
I have a method to access variables though their name (ie GRBModel.GetVarByName), something like
public GRBVar variable(i,t)
{
try
{
GRBModel M = getModel();
string varname = varname(i,t);
GRBVar var = M.GetVarByName(varname);
return var;
}
catch (GRBException ex)
{
System.Console.WriteLine(ex.ToString());
throw new GRBException(ex.ToString());
}
}
The problem is that on my IronPython script, when I try to access a non existing variable, nothing happens... the message doesnt appear on the console. What I'm doing wrong???
I think you're missing a return statement somewhere; if you catch the exception, the method does not return. (Doesn't the C# compiler error in that case?)
If this method is just for IronPython, you could just let the exception pass through to IronPython and deal with it there.
According to this page in the Gurobi .NET Reference Manual, GRBException inherits from the .NET Exception class. To obtain the error message from an Exception based class you should use the Message property rather than the ToString() method, which by default normally displays only the class name for reference classes.
In other words, change the catch clause to:
catch (GRBException ex)
{
System.Console.WriteLine(ex.Message);
}
Alternatively, you could output the ErrorCode property which is specific to the GRBException class.
I have a class called "Website", and inside of that class I have the following property:
public HtmlForm RegisterForm
{
get
{
if (Forms.RegForm != null) / Forms is a custom object called HTMLForms that is a custom list collection
{
return Forms.RegForm;
}
else
{
// FindPageWithGoogle Google = new FindPageWithGoogle();
// use Google.FindRegistrationForm(this.currentUrl) method
//throw new Exception(); // if registration form object can't be found
}
return Forms.RegForm;
}
}
Would this be an efficient way of handling the error? In the case of it not being found, how would I halt the entire flow of the program if this exception is thrown? I know how to use a simple try catch, but I don't think that's enough. I believe I need to learn how to make my own custom exception handling system to handle these custom events accordingly.
Thanks for any help. Also, if you have a specific book on exception handling, since the C# books i've read thus far didn't go into the topic much, it would be greatly appreciated.
Thanks,
Cody
To terminate the code on an exception, just don't catch it.
You should create a meaningful exception class (e.g. InitializationError) and then throw that when the error occurs. Go out to the calling code that can display the message to the user and catch the exception there. You might also terminate the program at that point.
As far as books on exception handling, I think you'll find the MSDN chapter on exceptions helpful.