Is it alright to return an empty object in case of an exception or should we throw the exception so that caller may know what has gone wrong?
public async Task<UserInfoModel> GetUserInfoByRole(Role role)
{
UserModel userInfo = new UserModel();
try
{
// do something
}
catch (Exception ex)
{
// do logging
// throw;
}
return userInfo;
}
It depends if you are creating a class, component, ... for others to use, you obviously should throw an exception. because they need to know about it and handle the exception the way that suits them.
If it is a method in your own code, may be returning a null value would be sufficient, because you might just check the return value and if it is null you know that there was an error and you don't want to program break because of the exception, otherwise you will need another exception handling again.
Related
This might be a broad question, but recently I ahve wondered about the following: In our C# backend we have many places that wrap some code in a try/catch block, specifically calls to external WcF services. Some of these calls are crucial for the application so in the catch block we log the error and rethrow, like:
catch(Exception ex)
{
_logger.Error("Some good error message");
throw ex;
}
On the other hand there are services we allow to fail, but we still want to log the error, so they look like:
catch(Exception ex)
{
_logger.Error("Some good error message");
}
Now reading the code of team members I can not be sure if they forgot to throw or if this is the intended behaviour.
Q: Is there a way, resp. what is the default way, to explicitly NOT rethrow (without including a comment in the code).
I have considered something like this:
catch(Exception ex)
{
_logger.Error("Some good error message");
NotThrowingHereOnPurpose();
}
// ...
// and further below a private method
// ...
private void NotThrowingHereOnPurpose(){}
One approach that may be useful here is to change the way of invoking the code that you explicitly allow to fail in such a way that it does not look like a try/catch block at all.
For example, you could write a helper method that does error reporting, and call it with actions expressed as lambdas:
void InvokeFailSafe(Action action, Action<Exception> onFailure = null) {
try {
action();
} catch (Exception e) {
if (onFailure != null) {
onFailure(e);
}
}
}
Now instead of try/catch you would write this:
InvokeFailSafe(
() => {
... The code that may fail
}
, exception => _logger.Error("Some good error message: {0}", exception)
);
or like this, if you don't want anything logged:
InvokeFailSafe(
() => {
... The code that may fail
}
);
If you code things this way, there would be no doubts about a missing throw statement.
It's an opposite solution to dasblinkenlight's answer. Instead of notifying others that the exception mustn't be rethrown it would say that it must be.
If you only want to log it then use the Error method as usual. Otherwise, you can write an extension method for your logger to log and throw exceptions.
The method would take the catched exception and rethrow it using the ExceptionDispatchInfo class. The ExceptionDispatchInfo is used to rethrow the exception with the original stack trace information and Watson information. It behaves like throw; (without the specified exception).
public static void ErrorAndThrow(this ILogger logger, string message, Exception exception)
{
var exceptionInfo = ExceptionDispatchInfo.Capture(exception);
logger.Error(message);
exceptionInfo.Throw();
}
And use it this way:
try
{
}
catch (Exception ex)
{
// ex would be rethrown here
_logger.ErrorAndThrow("Some good error message", ex);
}
Q: Is there a way, resp. what is the default way, to explicitly NOT
rethrow (without including a comment in the code).
Ideal way would be not to catch a generic exception. Now, to throw or not that entirely depends on your case. You need to understand that Exception handling is used when you know what to do in case an exception occurs. So, only specific exceptions should be handled. Catching exceptions without knowing what you are catching will change the behavior of your application.
Now reading the code of team members I can not be sure if they forgot
to throw or if this is the intended behaviour.
This is something the author of the code can explain to you. But here is a learning to take from this. Your code should be self explanatory. In specific cases where you are unable to express yourself with the code, add a meaningful comment.
You can check this link for better understanding.
I actually found another way that kind of includes what other have suggested here, but uses a built in feature: exception filters. I was free to modify the example given in here to illustrate this:
public void MethodThatFailsSometimes()
{
try {
PerformFailingOperation();
}
catch (Exception e) when (e.LogAndBeCaught())
{
}
}
and then one could have two extension methods on Exception, say LogAndBeCaught and LogAndEscape like so:
public static bool LogAndBeCaught(this Exception e)
{
_logger.Error(#"Following exception was thrown: {e}");
return true;
}
public static bool LogAndEscape(this Exception e)
{
_logger.Error(#"Following exception was thrown: {e}");
return false;
}
Modifying to make it clear:
I have a question on exception logging and graceful exit. This is in continuation with previous question. The code looks like:
string status = "0";
ClassA ObjA = new ClassA();
try
{
status = objA.Method1();
if (status != "-1")
{
status = objA.Method1();
}
}
catch (Exception Ex)
{
//Log Exception EX
}
Inside the Method1:
public string Method1()
{
string status = "0";
try
{
//Code
return "0";
}
catch (Exception Ex)
{
//Log Exception with details
return "-1"
}
}
I log the Exception in the calling method and return only a status to the caller.
Should I return the Exception to the calling method or is only a status sufficient. With a status of "-1", I know there was an Exception in the called method and details of that Exception were logged in a log file.
I think it is OK to do it like that if you have a lot of status codes, otherwise you could also just throw an exception and catch it in the method higher up.
Also maybe reconsider your return type. Looks like you could be using integers, think you are opening yourself up to errors using strings.
Don't use the status return value, it is not adding anything that is useful to you.
consider,
var a = new ClassA()
try
{
a.Mehtod1();
}
catch
{
try
{
a.Method1();
}
catch (Exception ex)
{
//Log without details;
}
}
class ClassA
{
void Method1()
{
try
{
//Code
}
catch (Exception ex)
{
//Log with details
throw;
}
}
}
This code achieves the same functionality but leaves the return code of the functions for something useful and non exceptional.
More generally, I suggest that you should have one catch all handler at the top level of your application that deals with logging, or at most one per public entry point. Other handlers should deal with specific exception types that they can actually "handle" (do something about.)
It all depends on the purpose and implementation of the code; sometimes it is better to allow exceptions to pass back to the caller - they should be used in exceptional cases.
If you do intend on using return codes, however, I would be more inclined to use enum's (though, again, it depends what the purpose of the code is). That way, it is easy for the caller to check against an available selection of return codes. Also, a comment on using integers or strings as error codes - it may not be very descriptive for a caller to know what the issue was. In this case, throwing an Exception or a specific type (containing the error message), or returning a pre-defined enum with a descriptive name, would be more meaningful to the caller.
From these short code snippets which does nothing it is very difficult to say what is best practice.
In general it is best to push exceptions to where they are handled best. If you are writing a framework for interfacing with some webservice the users of your framework will most likely not care about network exceptions etc. - they want return codes or, even better some framework specific exceptions that you include/code.
Hm - in your situation I'd rather do the following, but it really depends on the situation:
public string Method1()
{
string status = "0";
//Code - Exception may be thrown
return "0";
}
string status = "0";
ClassA ObjA = new ClassA();
try
{
status = objA.Method1();
}
Catch(Exception Ex)
{
//Log Exception EX
status = "-1;
}
EDIT
Sometimes it's hard to define values that indicate whether an error occurred in the method. You should keep Nullable types in mind. If you can find a suitable return value that indicates errors, it may also be ok to log the error within the method that caused the error and just react to the return value as you suggested.
By the way: In your code you're calling Method1 twice if the first call succeeded. I guess that is because it is a quick sample...
class MyException : Exception
{
public readonly int status;
public MyException(int status, string msg):base(msg)
{
this.status = status;
}
}
public string Method1()
{
throw new MyException(-1,"msg");
return "0";
}
SomeCode()
{
try
{
Method1();
}catch(MyException ex)
{
ex.status //here you get the status
}
}
I`m writing class. Here is one of functions:
public string GetAttribute(string attrName)
{
try
{
return _config.AppSettings.Settings[attrName].Value;
} catch(Exception e)
{
throw new ArgumentException("Element not exists", attrName);
return null;
}
}
Then, I am using it in the main form MessageBox.Show(manager.GetAttribute("not_existing_element"));
Visual Studio throws an Exception at line:throw new ArgumentException("Element not exists", attrName);
but, I am want to get an Exception at line MessageBox.Show(manager.GetAttribute("not_existing_element"));
How can I do that?
P.S: Sorry for bad English.
You are misusing exception handling. In your code, if you get (for example) a NullReferenceException, you will catch it and then throw an ArgumentException.
Rewrite your method to not have any exception handling:
public string GetAttribute(string attrName)
{
return _config.AppSettings.Settings[attrName].Value;
}
This way, you are not resetting the stack trace and swallowing the original exception.
In terms of getting an exception on the calling line - you will never be able to get an exception at a line that isn't throwing an exception.
A couple of things:
First, you'll get an unreachable code warning for the return null statement in your catch, because the throw will execute before the return. You can simply delete the return null statement.
Secondly, I'm not sure what you mean by getting the exception at the MessageBox line, but I think you mean you want to catch it there. Wrap the call to MessageBox in a try-catch.
try
{
MessageBox.Show(manager.GetAttribute("not_existing_element"));
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
Is it possible to call catch for a special condition when you are inside of try without using system error? For instance if a value int value 1 and then I want to use "catch".
One of the biggest sins in programming:) Don't use exceptions for managing programming flow! Now to your question - the catch block can be called in case an exception is thrown.
Your wording is a bit confusing but I think this is what you want.
int value = GetValue();
try
{
if (value == 1)
throw new InvalidOperationException();
HappyPath(value);
}
catch (InvalidOperationException)
{
SadPath(value);
}
Incidentally using exceptions for control flow is not the best practice.
No. You should catch exceptions (you can filter them by type), and then inside catch block you can filter on any condition.
It is not possible in C# to throw an exception that doesn’t derive from Exception, even though the CLR allows it.
It is possible to catch such an exception, but it is not possible to access the object that was thrown:
try
{
MethodThatThrows();
}
catch // This catches everything, even objects not deriving from Exception
{
// Process exception
}
As soon as you specify a variable (e.g. catch (Exception e)), C# requires that the type is Exception or derived from it.
I think you might be saying that you want to catch an exception only in specific circumstances, and pass it through in all other circumstances? In that case, you can just use an if to check for the condition and then throw to re-throw the exception:
try
{
// ...
}
catch (Exception e)
{
// If it’s any value other than 1, we’re not interested in the exception
if (value != 1)
throw; // note: throw; *not* throw e;
// Process the exception here
}
So, I have a list containing a custom class, MyClass
MyClass has properties, which can be null (but aren't meant to be).
When this class is sorted, using a custom sorter, where the sorter accesses this null property and throws an exception, the exception is considered unhandled, even though there is a try-catch block around the sort method.
Now for some reason the exception still gets written to the console, which is what the exception handler is doing.
I have a real application with this same issue, causing my unit tests to fail, even though the exception is handled correctly and I cannot explain this.
So I have attached some sample code to explain myself better, run this from VS.
Updated Code
Results:
System.InvalidOperationException
Failed to compare two elements in the array.
Done!
So it seems to be handling my custom exception, and throwing its own?
using System;
using System.Collections.Generic;
using System.Data;
namespace TestSortException
{
class Program
{
static void Main()
{
try
{
var list = new List<MyClass>
{
new MyClass("1"),
new MyClass(null),
new MyClass("fdsfsdf")
};
list.Sort(new MyClassSorter());
}
catch(Exception e)
{
Console.WriteLine(e.GetType());
Console.WriteLine(e.Message);
}
Console.WriteLine("Done!");
Console.ReadLine();
}
}
class MyClassSorter : IComparer<MyClass>
{
public int Compare(MyClass x, MyClass y)
{
// try
// {
if (x.MyString == y.MyString)
return 0;
// Unhandled??? Exception here
if (x.MyString.Length > y.MyString.Length)
return 1;
return -1;
// }
// catch (Exception)
// {
// return -1;
// }
}
}
class MyClass
{
private string _myString;
public string MyString
{
get
{
if (_myString == null) throw new DataException("MyString is Null");
return _myString;
}
}
public MyClass(string myString)
{
_myString = myString;
}
}
}
There's a try/catch block round the Sort method, yes - and that catch block catches the exception. In other words, Sort throws an exception and your catch block catches it. It doesn't propagate out beyond Main - so "Done!" is printed.
This is exactly what I'd expect. In what way is it "unhandled" in your experience? Were you expecting Sort not to throw the exception? It needs to do something to indicate the failure to compare two elements, and this seems to be the most appropriate course of action.
In what way are your unit tests failing? Are you deliberately giving them invalid data? How do you want your comparison code to react to invalid data? If it should ignore it (and return a comparison based on another property), then you should actively check the property rather than letting an exception propagate. In most cases I'd rather allow the exception if this indicates that there's a bug earlier on though.
EDIT: Based on your other comments, it sounds like you're doing the appropriate thing, letting the exception bubble up - but it's not clear in what way you're seeing the exception not be handled.
If you're running in the debugger, it may be breaking on the exception being thrown, but that doesn't mean it won't be handled. Try either changing your exception settings or running without the debugger.
EDIT: Yes, Sort will catch the exception and throw an InvalidOperationException instead - but you can use the InnerException property of that exception to get hold of the original one. It's unfortunate that the documentation doesn't specify this :(
For example, when it checks that string "1" isn't equal to null. But it wants then to compare lengths of "1" string and null => which is impossible.
I assume you work with .Net Framework 4.0. The new thing there is that a NullRefenrenceException can not be caught any more (similar to OutOfMemory exception).