简体   繁体   English

在C#中处理异常的最佳实践是什么?

[英]What are best practices for handling exceptions in C#?

I have following code in my web page: 我的网页中有以下代码:

btnTest_Click(object sender, EventArgs e)
{
    ...
    bool ret=myFunc(...);
    if (ret)
    {...}
    else
    {
        lblStatus.Text="Some Text";
        lblStatus.Visible=true;
    }
}

private bool myFunc(...)
{
    bool ret=false;
    try
    {
        ...
        ret=true;
    }
    catch (Exception ex)
    {
        lblStatus.Text="Other Text";
        lblStatus.Visible=true;
    }
    return ret;
}

If an exception occurs in myFunc, the lblStatus always shows "Some Text" not "Other Text". 如果myFunc中发生异常,则lblStatus始终显示“某些文本”而不​​是“其他文本”。 That means the catch block in myFunc doesn't really mean anything. 这意味着myFunc中的catch块实际上没有任何意义。 I wonder how to fix this code to handle the exception better? 我想知道如何修复此代码以更好地处理异常?

update: maybe my example is not very good. 更新:也许我的榜样不是很好。 But I main purpose is to ask best practices for exceptions handling between calling and being called functions. 但是我的主要目的是询问最佳实践,以了解调用和被调用函数之间的异常处理。

Why is your called function setting the label text on exception and the caller setting it on success? 为什么您的被调用函数将标签文本设置为异常,而调用方将其设置为成功?

That's something of a mixed metaphor. 那是一个混杂的隐喻。 Let one party be responsible for UI (separation of concerns) while the other is responsible for doing work. 让一方负责UI(关注点分离),而另一方负责工作。 If you want your called function to be fault tolerant try something like this: 如果希望被调用的函数具有容错能力,请尝试以下操作:

private bool myFunc(...)
{
  bool ret ;
  try
  {
    ...
    ret=true;
  }
  catch
  {
    ret = false ;
  }
  return ret;
}

Then your caller can do something like: 然后,您的呼叫者可以执行以下操作:

bool success = myFunc(...) ;
lblStatus.Text = success ? "Some Text" : "Other Text" ;
lblStatus.Visible = success ;

if ( success )
{
  // do something useful
}

It displays "Some Text" because, when an exception occurs in myFunc , it returns false. 它显示“ Some Text”,因为当myFunc发生异常时,它返回false。 Then you go into the else block of the btnTest_Click method, where you set lblStatus.Text to "Some Text" again. 然后进入btnTest_Click方法的else块,在此处将lblStatus.Text再次设置为“ Some Text”。

So, basically, you're setting the label's text to "Other text" and then to "Some Text". 因此,基本上,您将标签的文本设置为“其他文本”,然后设置为“某些文本”。

Your catch clause is doing a lot. 您的catch子句正在做很多事情。 It catches every exception and "forgets it" suppressing it to the rest of the call stack. 它捕获每个异常并“忘记”异常,将其抑制到调用堆栈的其余部分。 This can be perfectly fine but i'll try to explain your options: 可以很好地解决问题,但我将尝试说明您的选择:

You usually have 3 options: 您通常有3个选择:

  1. Do not care about exceptions and let code above you handle it 不在乎异常,让上面的代码处理它
  2. Care to log the exception and let it propagate 小心记录异常并使其传播
  3. The exception has its meaning in a given context and should not be propagated (this is your scenario) 异常在给定的上下文中具有其含义,因此不应传播(这是您的情况)

I use all of them. 我全部使用。

Option 1 选项1

You can just implement your function and if an exception occurs then it means some fault occurred and you just want your application to fail (at least to a certain level) 您可以只实现您的功能,如果发生异常,则意味着发生了一些错误,并且您只是希望您的应用程序失败(至少到一定程度)

Option 2 选项2

Some exception occurs and you'll want to do one of two (or even both) 发生某些异常,您需要执行两个(或什至两个)之一

  • log the error 记录错误
  • change the exception to another one more meaningful to the caller 将异常更改为对调用者更有意义的另一个异常

Option 3 The exception is expected and you know how to completely react to it. 选项3该异常是预料之中的,您知道如何完全对其进行反应。 For instance, in your case, i tend to believe you do not care about the type of exception but want a "good default" by setting some controls to a given text. 例如,在您的情况下,我倾向于认为您不在乎异常的类型,而是希望通过对给定的文本设置一些控件来实现“良好的默认设置”。

conclusion 结论

There are no silver bullets. 没有银弹。 Use the best option for each scenario. 为每种情况使用最佳选项。 Nevertheless catching and "suppressing" catch(Exception ex) is rare and if seen often it usually means bad programming. 然而,捕获和“抑制” catch(Exception ex)很少见,如果经常看到,通常意味着不好的编程。

The exception handling is just fine. 异常处理就可以了。 The problem with your code is that you are putting the "Some Text" string in the label if the return value is false , and that is when there was an exception, so it will replace the message from the catch block. 代码的问题是,如果返回值为false ,那就是在出现异常的情况下,将"Some Text"字符串放入标签中,因此它将替换catch块中的消息。

Switch the cases: 切换案例:

if (ret) {
  // it went well, so set the text
  lblStatus.Text="Some Text";
  lblStatus.Visible=true;
} else {
  // an exception occured, so keep the text set by the catch block
}

This is a complex question so I will try to break it down 这是一个复杂的问题,所以我将尝试将其分解

  1. In terms of functions I would try to stick to the Single Responsibility Principal. 在功能方面,我会尽量坚持“单一责任主体”。 It should do one, well defined thing. 它应该做一件明确的事情。
  2. Exceptions should be that, exceptional. 例外应该是例外。 It is then preferable to try not to incur exceptions but obviously to deal with them as and when. 因此,最好不要产生异常,而应在一定时间内处理它们。 For example it is better to test a variable as being null before attempting to use it (which would throw an exception). 例如,最好在尝试使用变量之前将其测试为null (这将引发异常)。 Exceptions can be slow (especially if a lot are thrown) 异常可能很慢(尤其是抛出很多异常时)
  3. I would say that the question of WHERE you handle the exception is down to whose responsibility the exception is. 我要说的是,您在哪里处理异常的问题归结于异常是谁的责任。 If myFunc were to access a remote server and return a status of true or false you'd expect it to handle its own IO exception. 如果myFunc要访问远程服务器并返回true或false状态,则希望它能够处理自己的IO异常。 It would probably not handle (or rethrow) any parameter problems. 它可能不会处理(或重新抛出)任何参数问题。 This relates to point 1. It is the functions responsibility deal with the connection process, not to provide the correct parameters. 这与第1点有关。功能职责是处理连接过程,而不是提供正确的参数。 Hiding certain exceptions can cause problems if other people (or a forgetful you) tries to use the code at a later date. 如果其他人(或健忘的人)以后尝试使用该代码,则隐藏某些异常可能会导致问题。 For example in this myFunc which makes a connection, should you hide parameter exceptions you may not realise you have passed in bad parameters 例如,在建立连接的myFunc中,如果您隐藏参数异常,则可能不会意识到自己传递了错误的参数

If you want to be informed of encountering a specific type of error inside one of your functions, I'd recommend inheriting Exception and creating your own exception class. 如果要通知您在其中一个函数中遇到特定类型的错误,建议您继承Exception并创建自己的异常类。 I'd put a try-catch block inside your btnTest_Click() handler, and then I'd look to catch your custom exception class. 我会在btnTest_Click()处理程序中放入try-catch块,然后查找您的自定义异常类。 That way, you won't lose the opportunity to detect any errors happening inside your myFunc() function. 这样,您将不会失去检测myFunc()函数内部发生的任何错误的机会。

I usually setup an error handling system. 我通常会设置一个错误处理系统。 Here's a simple way, but this can be wrapped up into a base class. 这是一个简单的方法,但是可以将其包装为一个基类。 I can show you that if you need. 如果需要的话,我可以告诉你。

List<string> _errors;

void init()
{
 _errors = new List<string>();
}

protected void Page_Load(object sender, EventArgs e)
{
  init();
}

btnTest_Click(object sender, EventArgs e)
{
    ...
    var result = myFunc(...);
    if (result)
    {...}
    else
    {
        if (_errors.Count > 0)
        {
          var sb = new StringBuilder("<ul>");
          foreach (string err in _errors)
          {
            sb.AppendLine(string.Format("<li>{0}</li>", err));
          }
          sb.AppendLine("</ul>");
          lblStatus.Text=sb.ToString();//Make this a Literal
        }
    }
}

private bool myFunc(...)
{
    var result = true;
    try
    {
        ...
        ...        
    }
    catch (Exception ex)
    {
        result = false;
        _errors.Add(ex.Message);
    }
    return result;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在C#中实现自定义异常的行业标准最佳实践是什么? - What are industry standard best practices for implementing custom exceptions in C#? 在C#中处理异常的良好做法 - Good practices when handling Exceptions in C# 使用事务和错误处理从 C# 在 oracle 表中上传批量数据的最佳实践是什么? - What are the best practices to upload bulk data in oracle table from C# using transaction and error handling? 在C#中从SQL捕获异常的最佳实践 - Best practices for catching exceptions from SQL in C# c#+ WebForms + static - 最佳实践是什么? - c# + WebForms + static — what are the best practices? C#处理异常和异常的数据错误和警告的最佳实践 - C# What is best practise for handling Data Errors and Warnings as opposed to Exceptions 使用XML注释记录C#代码的最佳实践是什么? - What Are Best Practices For Documenting C# code with XML comments? 在C#中捕获COM异常的最佳实践是什么? - What are the best practices on catching COM-exception in C#? C#中算术溢出检查的最佳实践是什么? - What are best practices for arithmetic overflow checking in C#? C#中最重要的优化性能最佳实践是什么 - What are the most important optimizing performance best practices in C#
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM