views:

936

answers:

10

If I have a method that returns something, like

public DataTable ReturnSomething()
{
   try
   {  
      //logic here
     return ds.Tables[0];
   }
   catch (Exception e)
   {
      ErrorString=e.Message;
   }
}

This produces compiler error, obviously because catch{} block does not return anything.

So when I have methods with return values I don't use try-catch block, which is a bad practice. If there is an error, I would like to set error string to that error. But then I need a return value as well. Advice?

+10  A: 

You should raise/throw the exception in your catch block and handle it in the calling method.

public void invokeFaultyCode()
{
    try
    {
        DataTable dt = ReturnSomething();
    }
    catch(Exception e)
    {
        // Print the error message, cleanup, whatever
    }    
}
public DataTable ReturnSomething() throws Exception
{
   try
   {  
      //logic here
     return ds.Tables[0];
   }
   catch (Exception e)
   {
      ErrorString=e.Message;
      throw;
   }
}

See also: some best practices.

PS: Sorry for any syntax error, I'm a bit rusty on C#.

Manrico Corazzi
You may want to just throw as throw e will alter the exception stack.
John Hunter
Good point you have here.
Manrico Corazzi
+2  A: 

It depends on you application. You can return null, an empty DataTable or whatever is suitable under circumstances.

Anton Gogolev
It entirely depends on the circumstances. You should always ask the question "what does it mean if an exception happens here?" rather than follow the same rote practice. Part of the reason of having an exception handler is to, well, HANDLE the exception.
plinth
+3  A: 

You should wrap the caller with a try catch... any exceptions that happen in the routine that is called will bubble out to the caller and you can catch them there.

Personally, I think it is overkill to have a try catch in this routine as you should have the caller handling the exception.

For my example, this would be coded as follows...

private void DoSomething() {
    try {
        DataTable dt = ReturnSomething();
    }
    catch (Exception ex) {
    }    
}

public DataTable ReturnSomething() {
    DataTable dt = new DataTable();

    // logic here
    return dt;
}
Bryan Sebastian
+9  A: 

Store your return value in a temporary variable like this:

public DataTable ReturnSomething()
{
    DataTable returnValue = null;

    try
    {
        //logic here
        returnValue = ds.Tables[0]; 
    }
    catch (Exception e)
    {
        ErrorString=e.Message;
    }

    return returnValue;
}
Simon
simple and does the job.
Like others have noted, you should think about throwing the exception instead of setting an ErrorString though. If you want an exception with your own message, you should throw a new exception, with the original exception as inner exception. throw new ArgumentException("My message", e);
Svish
I agree with Svish and others; although I've attempted to answer your question as asked, I don't think it's the best solution to your problem.
Simon
A: 

I think your code is being run at a sufficiently high level of the call stack and it's blended with UI code. If this is really the case, you could return null in the catch block. However, if you are writing reusable code, you should refactor it so that it doesn't contain UI manipulation and handle the exception at a higher level in the call stack.

Mehrdad Afshari
A: 

Since you are cacthing the exception (and not throwing it again) in your example, The outside code assumes everyting is okay and therefor you should return something useful.

If you need to catch the exception there and do somthing that's all fine, but if it's still an error case you should also throw it, or a different exception, perhaps with the one you just caught as InnerException.

Kris
+2  A: 

i'd assume you can still set the message, then return null or whatever the c# equivalent is

public DataTable ReturnSomething(){ 
   try {
        //logic here 
        return ds.Tables[0]; 
   } catch (Exception e) {
        ErrorString=e.Message;
        return null;
   }
}
zaczap
+1  A: 

How about this :

public DataTable ReturnSomething(out string errorString)
{
   errorString = string.Empty;
   DataTable dt = new DataTable();
   try
   {  
      //logic here
     dt = ds.Tables[0];
   }
   catch (Exception e)
   {
      errorString = e.Message;
   }
   return dt;
}
Canavar
Won't it be a compiler error, since errorString is an out, and it isn't guaranteed to be set?
Daniel LeCheminant
yeap, you're right, I just write it in SO editor :) editing !
Canavar
@ScarletGarden: I do the same thing ;]
Daniel LeCheminant
+2  A: 

If you are going to head the "don't throw an exception route" (which I am not necessarily reccomending), you could follow the TryParse approach MS uses.

Something like:

private string FillDataTable(out DataTable results)
{

  try
{
  results = new DataTable(); //something like this;
  return String.Empty;
}
catch (Exception ex)
{
  results = null;
 return ex.Message;

}

}

Kevin
+4  A: 

The ErrorString variable looks suspiciously like an error code variable. Recommended practice is to use exceptions to pass error information directly, where necessary, rather than storing things off into error codes.

You are effectively doing the same thing with your ErrorString as you would be if you just let the exception be caught by the caller: removing the responsibility of responding to an error from the method itself. This is a good goal to have. But the use of an error string doesn't gain you anything over the use of an exception. In fact, you lose information this way. There are any number of types of errors that could occur, and many have special exceptions associated with them, with their own special properties to hold contextual info about the failure. By just storing off the message in a String, you're losing this information.

So unless your goal is specifically to hide the type of error that is occurring from the caller, you can only gain by letting the exception through.

Another thing to consider is whether this is truly an error scenario. If it is, it's very unlikely that your calling method is going to care at all what the return value is. In which case, you have nothing to worry about by just letting the exception go and not returning anything. If it's NOT really an error scenario, and the caller is just going to continue on and do something else, well, that's for the caller to decide, right? There's still not much benefit to obtain by returning an error string and a dummy DataTable or a null, over throwing the exception with all its contextual failure info.

Chris Ammerman