C# 我应该处理哪些例外情况

C# 我应该处理哪些例外情况,c#,.net,exception,design-patterns,try-catch,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>

我有以下代码:

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


        }
public void OpenFile(字符串文件名)
{
如果(文件名==null)
抛出新ArgumentNullException(“文件名”,“OpenFile:文件名为null”);
List readItems=new List();
使用(StreamReader=新StreamReader(文件名))
{
弦线;
int批处理项目;
而((line=reader.ReadLine())!=null)
{
if(内部特里帕尔斯(行,外批项目))
{
readItems.Add(batchItem);
}
}
}
currentfile=文件名;
FileInfo f=新的FileInfo(文件名);
锁定(锁定对象)
{
TextWriter=f.AppendText();
TextWriter.AutoFlush=true;
}
如果(readItems.Count>0)
文件打开(readItems);
}
我正在尝试检测可能的问题,例如/Filename为null

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

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

我知道这听起来很傻,但我想知道我是否应该为我抛出的异常设置显式捕获,然后设置一个常规异常捕获,无论是
catch(exception ex)
,还是在上面的代码周围设置一个try-catch并重新调用一个自定义异常。否则,我的try/catch块有大约12个独立的catch语句

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

始终确保将一般异常即SystemException/ApplicationException/exception catch子句放在最后。所以,为显而易见的事情做好准备。在您的例子中,SecurityException、FileNotFound、PathNotFound等异常。请查看MSDN文档中的这些API以及它们引发的各种异常

生成泛型异常的问题是,您永远不知道实际问题是什么,即使FxCop对此给出了警告。如果catch子句更多,则没有问题,但请确保拆分并捕获异常。例如,如果我们在不同的场合打开两个文件,那么就分别捕获它们,而不是一个

我是否也应该捕获 StreamReader构造函数和FileInfo构造函数


简而言之:知道抛出了这些异常,您能做一些合理的事情吗?如果是的话,抓住他们并去做。如果没有,就让它中断。

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

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
,但是我们如何处理它呢?显然,这段代码已经无能为力了,因为确实发生了一些异常情况。我们可以让异常冒泡到下一层,因为我们在这里做不了什么有意义的事情。

埃里克·利珀特关于不同类型的异常以及正确处理异常的方法的文章必须如此。@FrédéricHamidi但在StreamReader/FileInfo的场景中,我无能为力。如果我自己检查文件名是否无效,我会自己抛出异常并捕获它,因此我不会真正阻止任何事情