6

我试图了解我将如何在我的代码中使用 Throw。我有一个 MainForm 类来处理 Windows 窗体 GUI,然后我有一个 Manager 类来读取和保存文件中的数据。

我在两个课程中都使用 Try/Catch,但我的导师希望我在 Manager 课程中使用 Throw,尽管我正在阅读它,但我不明白它会做什么?Throw 会影响 MainForm 类中的 Try/Catch 吗?

如果捕获到异常,我也会在管理器类中使用消息框,但是根据讲师的说法,管理器中不允许有消息框,那我该怎么办?我可以只在 MainForm 类中使用消息框吗?对理解和扩展我的知识有一些帮助!谢谢!

MainForm 类:

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

经理类:

 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();
 }
4

7 回答 7

6

您的经理类应如下所示:

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();
    //}

}

在你的主要课程中:

try
{
    motelManager.SaveToFile(file);
}
catch (Exception e)
{
    MessageBox.Show("Ett fel uppstod!", "Varning!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
于 2012-07-30T09:35:25.917 回答
1

Throw 只是将异常引发到调用函数。(在这种情况下,无论谁调用 SaveToFile)。如果那里有错误处理程序,它将被捕获,否则它将继续调用堆栈,直到它被捕获或在顶层。

于 2012-07-30T09:39:27.653 回答
1

最好在表单中处理向用户呈现的异常 - 仅仅是因为在更大的结构良好的系统中,Manager 对象可能与 GUI 没有任何连接。

一般规则是在后端 [Manager] 类中捕获异常以清理任何资源(即关闭文件),然后从异常处理程序重新抛出异常,如下所示:

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;
    }

}
于 2012-07-30T09:39:33.540 回答
1

在具有多个层的应用程序中,底层发生的异常不会按原样发送到更高层或调用应用程序。

例如,如果数据库相关代码出现问题,您不会将其发送到客户端应用程序或更高层。这样做的原因是为用户提供友好的错误消息。假设您在删除操作期间出现外键引用错误,您可以:

  1. 记录异常信息。
  2. 替换为用户友好的异常消息并将其扔到上面的层。

上面的层可能会将此异常包装到另一个更高级别的消息中,然后将其抛出。这类似于您被要求做的事情。

在 Manager 类的代码中,检查可能发生多少异常。如果您使用的是 VS,则工具提示/帮助文本会提供该信息。如果您不使用 VS,请查看 MSDN 以获取此信息。

在表单中,处理管理层可能抛出的所有异常,以及如果发生严重错误时的通用异常。恕我直言,这就是您在管理层中的代码应该如何

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
            }

你的表单应该有这样的异常处理:

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。

于 2012-07-30T09:51:33.553 回答
1
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"));
    }
}

在你的经理中:

try
{
    manager.SaveToFile(filePath);
}
catch (Exception ex)
{
    // here shows your 'Your custom message'
    MessageBox.Show(ex.Message);
}
于 2012-07-30T09:35:23.147 回答
1

您可以使用Application ThreadException来捕获任何异常。并且您的保存逻辑使用 using 而不是 try catch 进行包装,在这种情况下,它将关闭您的流。

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);
    }
}

在入口点 (static void main()) 中订阅此事件。

    [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(".......");
    }
于 2012-07-30T09:35:33.490 回答
0

是这样的……

 try { } 
catch(Exception e) 
{ throw } 

当它抛出异常时,它将更改源和堆栈跟踪,以便看起来异常已从该方法中抛出,从包含该 try-catch 块的方法上的那一行 throw e 开始。

于 2012-07-30T09:38:10.013 回答