3D-kreativ
3D-kreativ

Reputation: 9309

Try Catch Throw

I'm trying to understand how I'm going to use Throw in my code. I have a MainForm class to handle the Windows Form GUI and then I have the Manager class to read and save data from/to files.

I use Try/Catch in both classes, but my instructor want me to use Throw in the Manager class and despite that I'm reading about it, I don't get the point what it will do? Will Throw affect the Try/Catch in the MainForm class?

I also use a message box in the manager class if an exception is catched, but no message box are allow to be in the manager according to the instructor, so how would I do then? Can I use the message box in MainForm class only? Preciate some help to understand and expand my knowledge! Thanks!

MainForm class:

try
{
     motelManager.SaveToFile(file);
}
catch
{
     MessageBox.Show("Ett fel uppstod!", "Varning!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}

Manager class:

 public void SaveToFile(string filePath)
 {
     try
     {
         string newFilePath = filePath.Replace(".bin", "");
         filestream = new FileStream(newFilePath + ".bin", FileMode.Create);
         BinaryFormatter b = new BinaryFormatter();
         b.Serialize(filestream, animals);
     }
     catch(Exception ex)
     {
         MessageBox.Show(ex.Message, "Varning!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
     }

     if (filestream != null) filestream.Close();
 }

Upvotes: 6

Views: 5030

Answers (7)

Artiom
Artiom

Reputation: 7847

you can use Application ThreadException to catch any exception. And your save logic to wrap with using instead of try catch, in this case it will close your stream.

public void SaveToFile(string filePath)
{
    string newFilePath = filePath.Replace(".bin", "");
    using(var filestream = new FileStream(newFilePath + ".bin", FileMode.Create))
    {
        BinaryFormatter b = new BinaryFormatter();
        b.Serialize(filestream, animals);
    }
}

in the entry point (static void main()) subscribe to this event.

    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());

        Application.ThreadException += Application_ThreadException;
    }

    static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
    {
        MessageBox.Show(".......");
    }

Upvotes: 1

danish
danish

Reputation: 5600

In an application with multiple tiers, exceptions that occur in underlying layers are not sent as is to higher layer or to the calling application.

For instance, if something goes wrong in the database related code, you do not send it to client application or to higher layer. Reason for doing so is to provide users with friendly error messages. Say, you had foreign key reference errors during delete operation, you can:

  1. Log the exception information.
  2. Replace with with a user friendly exception message and throw it to layer above.

Layer above may wrap this exception to another higher level message and then throw it ahead. This is similar to what you have been asked to do.

In your code in Manager class, check how many exceptions can possibly occur. If you are using VS, tooltip/help text provides that information. If you are not using VS, check out MSDN for this information.

In the form, handle all the exceptions that can be thrown by manager layer and also a generic exception if something terribly wrong happens. IMHO, this is how your code in manager layer should like

try
            {
                string newFilePath = filePath.Replace(".bin", "");
                FileStream filestream = new FileStream(newFilePath + ".bin", FileMode.Create);
                BinaryFormatter b = new BinaryFormatter();
                b.Serialize(filestream, animals);
            }
            catch (ArgumentNullException argNullException)
            {
                // Log current exception

                // Wrap it under your exception type
                CustomWrapException customWrap = new CustomWrapException();
                customWrap.Message = "Your custom message here.";
                customWrap.InnerException = argNullException;
                throw customWrap;
            }
            catch (SecurityException securityException)
            {
                // Log current exception

                // Replace current exception with you custom exception
                CustomReplaceException replaceException = new CustomReplaceException();
                replaceException.Message = "Your custom message here.";
                throw replaceException;
            }
            finally
            {
                // Close stream and dispose objects here
            }

Your form should be having exception handling like this:

try
            {
                // Call mananger code from here
            }
            catch (CustomWrapException wrapException)
            {
                // replace/wrap if desired
                // Display message to user
            }
            catch (CustomReplaceException replaceException)
            {
                // replace/wrap if desired
                // Display message to user
            }
            catch (Exception exception)
            {
                // This is for everything else that may go wrong apart from known possible exceptions
                // Display message to user
            }
            finally
            {

            }

HTH.

Upvotes: 1

Ria
Ria

Reputation: 10347

public void SaveToFile(string filePath)
{
    try
    {
         string newFilePath = filePath.Replace(".bin", "");
         filestream = new FileStream(newFilePath + ".bin", FileMode.Create);
         BinaryFormatter b = new BinaryFormatter();
         b.Serialize(filestream, animals);
    }
    catch (Exception ex)
    {
        if (filestream != null) filestream.Close();
        //what you want
        //MessageBox.Show(ex.Message, "Warning!");
        throw (new Exception("Your custom message"));
    }
}

And in your manager:

try
{
    manager.SaveToFile(filePath);
}
catch (Exception ex)
{
    // here shows your 'Your custom message'
    MessageBox.Show(ex.Message);
}

Upvotes: 1

John Woo
John Woo

Reputation: 263843

your manager class should look like this:

public void SaveToFile(string filePath)
{
    try
    {
        string newFilePath = filePath.Replace(".bin", "");
        filestream = new FileStream(newFilePath + ".bin", FileMode.Create);
        BinaryFormatter b = new BinaryFormatter();
        b.Serialize(filestream, animals);
    }
    catch(Exception ex)
    {
        if (filestream != null) filestream.Close();
        throw;
        // but don't use
        // throw ex;
        // it throws everything same
        // except for the stacktrace
    }
    // or do it like this
    //catch(Exception ex)
    //{
    //    throw;
        // but don't use
        // throw ex;
        // it throws everything same
        // except for the stacktrace
    //}
    //finally
    //{
    //    if (filestream != null) filestream.Close();
    //}

}

and in your main class:

try
{
    motelManager.SaveToFile(file);
}
catch (Exception e)
{
    MessageBox.Show("Ett fel uppstod!", "Varning!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}

Upvotes: 6

Richard Harrison
Richard Harrison

Reputation: 19403

It is better to handle the Exception in terms of presentation to the user in the Form - simply because in a larger well structured system the Manager object may well not have any connection to the GUI.

General rule is to catch the exception in the backend [Manager] class to cleanup any resources (i.e. close the file) and then re-throw the exception from the exception handler as follows:

public void SaveToFile(string filePath)
{
    try
    {
        string newFilePath = filePath.Replace(".bin", "");
        filestream = new FileStream(newFilePath + ".bin", FileMode.Create);
        BinaryFormatter b = new BinaryFormatter();
        b.Serialize(filestream, animals);
    }
    catch(Exception ex)
    {
        /* 
         * cleanup resources and rethrow the exception for catching and handling elsewhere
         */
        if (filestream != null)
            filestream.Close();
        throw;
    }

}

Upvotes: 1

Fry
Fry

Reputation: 4286

Throw simply raises the exception to the calling function. (in this case, whoever calls SaveToFile). If there is an error handler there, it will be caught, otherwise it will continue up the call stack until it is caught or at the top level.

Upvotes: 1

user1102001
user1102001

Reputation: 707

it is like this...

 try { } 
catch(Exception e) 
{ throw } 

When it throws the exception, it will change the source and the stack trace, so that it will appear that the exception has been thrown from this method, from that very line throw e on the method containing that try-catch block.

Upvotes: 0

Related Questions