我应该处理什么例外

时间:2012-04-03 08:43:43

标签: c# .net exception design-patterns try-catch

我有以下代码:

        public void OpenFile(string FileName)
        {
            if (FileName == null)
                throw new ArgumentNullException("FileName", "OpenFile: Filename is null");


            List<int> readItems = new List<int>();
            using (StreamReader reader = new StreamReader(FileName))
            {
                string line;
                int batchItem;
                while ((line = reader.ReadLine()) != null)
                {
                    if (int.TryParse(line, out batchItem))
                    {
                        readItems.Add(batchItem);
                    }
                }
            }

            CurrrentFile = FileName;
            FileInfo f = new FileInfo(FileName);
            lock (LockObject)
            {
                TextWriter = f.AppendText();
                TextWriter.AutoFlush = true;
            }

            if (readItems.Count > 0)
                FileOpened(readItems);


        }

我正在尝试检测可能的问题,例如/ Filename为null。

在捕获和记录异常的类中,我显然有catch(ArgumentNullException ex)

我是否还应该捕获StreamReader构造函数和FileInfo构造函数引发的可能异常?

我知道这听起来很傻但是我想知道我是否应该明确捕获我正在抛出的异常然后一般异常捕获它是catch(Exception ex)还是尝试捕获上面的代码并重新抛出自定义异常。否则我的try / catch块有大约12个单独的catch语句!

4 个答案:

答案 0 :(得分:4)

通常,如果您遵循一些简单的规则,则可以大大简化您的异常处理代码。

<强> 1。只捕获和处理您实际上可以

的异常

如果你无法从异常中恢复,那么你根本不应该抓住它。让异常气泡达到最高点(通常是用户界面)。

当你捕获异常时,你应该捕获非常具体的异常,并尽可能避免一般的异常处理。

try
{
   DoSomeStuff();
}
catch(HolyCrapItBlewedUpException ex)
{
   RecoverFromExplosion();
}
catch(Exception ex)
{
   //I really have no idea what happened, and I can't do
   // anything about it, but I'm going to catch the
   // exception anyway cause it makes me feel better
}

以上规则有 咳嗽 例外情况,但这会将我们带入第二条规则。

<强> 2。仅使用通用异常处理进行日志记录和实现隐藏

既然你应该让你的例外泡沫一直到最高层,那么任何使它成为顶层的东西都是一个bug。此时,您应该记录该异常并向用户显示一些友好的消息。

try
{
   DoSomeStuff();
}
catch(Exception ex)
{
   //At this point it's a bug... we need to squash it!
   LogException(ex);
   ShowUserRecoveryOptions();
}

您可能想要执行此操作的另一个地方是为了维护API的合同,并隐藏实现细节。如果最终用户正在调用方法,他们可能不需要知道发生的每个可能的问题,只是它不起作用。

public void MakeMeASandwich()
{
   try
   {
      MakeCallerASandwich();
   }
   catch(SecurityException ex)
   {
      //It's still best to distinguish between certain exceptions
      // as long as it makes sense to the caller.
      throw new NoIWillNotMakeYouASandwichException(ex);
   }
   catch(Exception ex)
   {
      throw new SorryICantMakeYouASandwichException(ex);
   }
}

第3。避免像瘟疫一样的例外情况!

例外情况应该是......非常......在大多数情况下,您应该能够通过简单地提前编码来避免异常。一个真正的例外应该代表你无法预测会发生的事情。一个简单的例子是检查文件是否存在。

try
{
   File.Open("blah.txt");
}
catch(FileNotFoundException ex)
{
   File.Create("blah.txt");
}

在那个例子中,我知道文件可能不存在......所以我应该编写代码来确保案例几乎永远不会发生。

var fileName = "blah.txt";

if(!File.Exists(fileName))
   File.Create(fileName);

File.Open(fileName);

现在,仍然可以将FileNotFoundException扔到这里,但我们将如何处理呢?很明显,这段代码不再对它做任何事情,因为发生了真正的 EXCEPTIONAL 。我们可以让异常泡到下一层,因为我们在这里没有任何意义。

答案 1 :(得分:1)

始终确保将您的常规异常viz SystemException / ApplicationException / Exception catch子句放在最后。所以要做好准备。在你的情况下SecurityException,FileNotFound,PathNotFound等异常。请查看MSDN文档以获取这些API以及它们引发的各种异常。

制作一般异常的问题是你永远不知道究竟是什么问题,即使FxCop也会发出警告。如果你的catch子句更多,没问题,但只要确保你拆分并捕获异常。例如,如果我们在不同的场合打开2个文件,那么分别抓住每个文件而不是一个。

答案 2 :(得分:1)

  

我是否也应该抓住可能的例外情况   StreamReader构造函数和FileInfo构造函数?

保持简短:你知道那些异常被抛出,你能做些合理的事情吗?如果是的话,抓住它们就行了。如果没有,就让它破裂。

答案 3 :(得分:0)

使用try catch 如果有错误,你可以在catch部分捕获它。先使用特定异常,稍后再使用一般异常。