保留重新抛出的异常的类型

时间:2010-03-02 16:57:51

标签: c# .net exception-handling

我正在编写一个对多个流执行操作的类。这是我现在正在做的一个例子

Dictionary<int, int> dict = new Dictionary<int, int>(_Streams.Count);
for (int i = 0; i < _Streams.Count; i++)
{
    try
    {
        dict.Add(i, _Streams[i].Read(buffer, offset, count));
    }
    catch (System.IO.IOException e)
    {
        throw new System.IO.IOException(String.Format("I/O exception occurred in stream {0}", i), e);
    }
    catch (System.NotSupportedException e)
    {
        throw new System.NotSupportedException(String.Format("The reading of the stream {0} is not supported", i), e);
    }
    catch (System.ObjectDisposedException e)
    {
        throw new System.ObjectDisposedException(String.Format("Stream {0} is Disposed", i), e);
    }
}
int? last = null;
foreach (var i in dict)
{
    if (last == null)
        last = i.Value;
    if (last != i.Value)
        throw new ReadStreamsDiffrentExecption(dict);
    last = i.Value;
}
return (int)last;

我想将我的代码简化为

Dictionary<int, int> dict = new Dictionary<int, int>(_Streams.Count);
for (int i = 0; i < _Streams.Count; i++)
{
    try
    {
        dict.Add(i, _Streams[i].Read(buffer, offset, count));
    }
    catch (Exception e)
    {
        throw new Exception(String.Format("Exception occurred in stream {0}", i), e);
    }
}
int? last = null;
foreach (var i in dict)
{
    if (last == null)
        last = i.Value;
    if (last != i.Value)
        throw new ReadStreamsDiffrentExecption(dict);
    last = i.Value;
}
return (int)last;

但是,如果有人试图捕获特定的异常,我的包装器将隐藏Read抛出的异常。如何保留异常类型,添加我的额外信息,但不需要为try块中的每个可能的意外事件编写处理程序。

5 个答案:

答案 0 :(得分:3)

我建议完全抓住这些例外......

您添加的信息(大部分)可以从stackdump收集。

您可以使用catch-and-wrap转换为特定于库的异常:

 catch (Exception e)
 {
    throw new ReadStreamsErrorExecption(
      String.Format("Exception occurred in stream {0}", i), e);
 }

答案 1 :(得分:1)

我认为您在处理异常时遇到了一些问题。

  1. 你不应该抛出基本的Exception类,而是更具体的东西,以便他们可以处理它。
  2. id值是否真的从诊断功能“有价值”?
  3. 我会检查你在做什么,看看你是否真的需要包装异常。

答案 2 :(得分:1)

我发现第一个版本的可读性更好,而且我的眼睛更具表现力。这就是应该如何编写异常处理。

答案 3 :(得分:1)

一般来说,我从Eric Lipperts博客中获取的规则是,如果您要对此做些什么,您应该只捕获异常。

在这里,您只需使用新消息重新抛出异常。只是让客户端自己处理异常,除非您尝试从错误中恢复。在这种情况下添加

throw;

如果您需要冒泡异常备份,因为无法处理它。

答案 4 :(得分:1)

一个鲜为人知的.NET技巧是你可以在不包装它的情况下向异常添加信息。每个例外都有一个.Data字典,您可以填写其他信息,例如

try
{
   ...
}
catch (FileNotFoundException ex)
{
   ex.Data.Add("filename", filename);
   throw;
}

现在,在您的顶级异常处理代码中,您可以将异常及其关联的字典转储到日志文件或异常数据库中,从而获得比以前更多的信息。

在ASP.NET应用程序中,您可能希望在让应用程序错误处理程序接受之前,将URL,用户名,引用者,cookie的内容,...添加到.Data字典中。< / p>