C# 试着接球
我试图理解我将如何在代码中使用Throw。我有一个MainForm类来处理Windows窗体GUI,然后有一个Manager类来从文件中读取和保存数据 我在两门课上都使用Try/Catch,但我的教练希望我在经理课上使用Throw,尽管我正在阅读有关它的文章,但我不明白它会做什么?Throw会影响MainForm类中的Try/Catch吗 如果捕捉到异常,我也会在manager类中使用消息框,但是根据讲师的说法,manager中不允许有消息框,那么我该怎么做呢?我只能在MainForm类中使用消息框吗?请给我一些帮助,以了解和扩展我的知识!谢谢 主窗体类:C# 试着接球,c#,.net,C#,.net,我试图理解我将如何在代码中使用Throw。我有一个MainForm类来处理Windows窗体GUI,然后有一个Manager类来从文件中读取和保存数据 我在两门课上都使用Try/Catch,但我的教练希望我在经理课上使用Throw,尽管我正在阅读有关它的文章,但我不明白它会做什么?Throw会影响MainForm类中的Try/Catch吗 如果捕捉到异常,我也会在manager类中使用消息框,但是根据讲师的说法,manager中不允许有消息框,那么我该怎么做呢?我只能在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();
}
在您的经理中:
try
{
manager.SaveToFile(filePath);
}
catch (Exception ex)
{
// here shows your 'Your custom message'
MessageBox.Show(ex.Message);
}
您的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)
{
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
{
// 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
{
}
在你的主课上:
try
{
motelManager.SaveToFile(file);
}
catch (Exception e)
{
MessageBox.Show("Ett fel uppstod!", "Varning!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
您可以使用捕获任何异常。您的save逻辑将使用而不是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(".......");
}
就像这样
try { }
catch(Exception e)
{ throw }
当它抛出异常时,它将更改源和堆栈跟踪,这样它就会显示异常是从这个方法抛出的,从包含try-catch块的方法上的行throw e抛出的。throw只是将异常引发到调用函数。(在本例中,调用SaveToFile的人)。如果那里有一个错误处理程序,它将被捕获,否则,它将继续向上调用堆栈,直到被捕获或处于顶层。最好在表单中向用户表示的方面处理异常,因为在结构良好的大型系统中,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;
}
}
在具有多个层的应用程序中,底层发生的异常不会按原样发送到更高层或调用应用程序 例如,如果数据库相关代码中出现错误,则不会将其发送到客户端应用程序或更高的层。这样做的原因是为用户提供友好的错误消息。例如,您在删除操作期间出现外键引用错误,您可以:
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
}
您的表单应具有如下异常处理:
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
{
// 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.Hmmm,但是抛出的作用是什么呢?您应该使用filestream,而不是在catch中显式关闭它。它将抛出当前异常,它将捕获并向
main
类抛出相同的异常。它被称为异常的rethrowing
。啊哈!就像我当时想的那样!美好的如果您传递了一个无效的字符串格式,如{}*
等,该怎么办?这是一个危险的代码,您可能会让dispose在全局范围内被调用,真正的问题不是这段代码,而是filestream是在全局范围内声明的。。不是艺术的错。。。。将filestream移动到本地作用域以避免出现问题。这段代码让我担心,它看起来像是传入了一个文件路径,并且一个流被打开到了一个全局变量,如果出现问题,您将调用close,如果您已经关闭了文件流,则无法在不重新分配的情况下重新打开文件流。在这种情况下,此代码是错误的,因为它将始终关闭文件流。调用close后,您应该在此处使用“using”块来调用dispose。写入此块的上下文是正确的,但在替换原始异常时,如果层之间的异常是ok,则应特别小心。。但如果不是的话,那就有点“不”no@krystanhonour我完全同意。