WinForm中的异常处理

3
我是一名C#编程新手。在使用表单构建应用程序时,我遇到了一个小问题。我将尽力以我的能力和经验来恰当地解释它。问题出现在我试图处理由在Form1中实例化的Class1引起的异常时。假设我在Class1中有一个函数"public int Calc(int a, int b)"。在Form1中,我实例化了这个类来调用其"Calc"函数。如果我想要向用户展示一个错误信息(例如:除以零),我必须将函数调用放入try/catch语句块中:
//Form1:
Class1 C1 = new Class1();
int a = 5;
int b = 0;
int c = 0;

try{
   c = C1.Calc(a,b)
}
catch(DivideByZeroException e)
{
   // some error handling code
}

我认为这个例子不符合正确的面向对象编程技术,因此我决定直接在Class1中添加try/catch元素:

//Class1:

public int Calc(int a, int b)
{
    int c = 0;
    try{
      c = a/b;
    }
    catch(DivideByZeroException e)
    {
      // .........
    }
    return c;
}

问题是,如何将消息(DivideByZeroException e)传递到我的Form1中,以便能够处理并发送消息。我不想在Form1中创建一些静态函数,只是为了从Class1中访问MessageBox类,因为这在正确的OOP功能和Class1的可重用性方面没有意义。我已经阅读了关于事件和委托的文章(我理解它们是类似于C ++的简单函数指针),但这有点令人困惑,我无法将此技术应用于我的代码中。您能否提供一个简单的例子,指引我走向正确的方向。
谢谢各位。
Cembo
5个回答

7

正确的技巧是第一步。如果你无法在函数内处理它,那么你就没有任何理由去尝试。将异常处理放置在可以处理异常并使程序能够继续运行(或优雅地退出),并以适当的方式通知用户错误的位置。


3

我建议你在应用程序的 Program.cs 文件中实现以下代码:

    [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)
    {
        // Handle your exception here...
        MessageBox.Show(string.Format("There is an error\n{0}", e.Exception.Message));
    }

这将捕获整个应用程序中未处理的异常。

1
为了让它冒泡到调用 UI 的范围内,你需要在捕获异常后抛出异常,或者更好的方法是根本不要抛出异常——因为如果必要的话,除以零会导致 CLR 抛出异常。在这里,你可以进行简单的检查,而 Calc API 调用仍然可能会抛出异常。
例如,在 Calc 调用之前,只需检查数据即可:
if (a > 0 && b > 0)
{
    var result = Calc(a, b);
}
else 
{
    //tell the user to input valid data
}

Calc方法中,您可以进行类似的检查并抛出相关异常:
public int Calc(int a, int b)
{
    if (a <= 0) throw new ArgumentException("appropriate message here");
    if (b <= 0) throw new ArgumentException("appropriate message here");
    ...
}

这里的想法是防止除以零,但在你的情况下可能有点过度,因为前面的示例向你展示了可以基本上提供相同的行为,但现在你需要捕获异常:

try
{
    var result = Calc(a, b);
}
catch //use appropriate exception catches
{
     //tell the user to input valid data
}

我喜欢这个,好的防御性编码,即使你说在这种情况下有点过度 :) +1 - AidanO

0
public int Calc(int a, int b)
    {
        int c = a/b;
    }

使用任何你需要的逻辑,保持简单明了。

然后像第一次处理错误一样,在表单内部处理错误。


-4

一个简单的方法是将你的方法更改为以下内容

public int Calc(int a, int b, out string error)
{
    error = string.empty;
    int c = 0;
    try
    {
      c = a/b;
    }
    catch(DivideByZeroException e)
    {
         error = e.ToString();
    }
    return c;
}

现在在调用者中,您可以进行检查

string error; 
int res = Calc( 1, 2, out error);
if(!string.isnullorempty(error)
{
    //error has occured
    messagebox.show(error);
}
else
{
    //no error
    // you can proceed noramlly
}

1
-1 这是错误代码通过返回值出现了严重问题。 - siride
1
现在调用 Calc 的任何函数都必须显式地处理错误(通过打印消息或类似方式)或将其传递给调用者。现在整个链路都必须传递错误消息。异常允许您在适当的位置处理错误,而不必将其传递到整个调用链中(容易出错且繁琐)。 - siride

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接