坚持异常对象是否安全?

时间:2013-02-07 19:53:51

标签: c# .net exception logging

我正在创建一个测试记录器,其中包含有关抛出的任何异常的信息,以便使用GUI正确显示它们。

使用以下构造是否安全:

public class TestLogEntry {
    public System.Exception Exception { get; private set; }

    public TestLogEntry(/*...,*/ System.Exception exception = null) {
        //...

        Exception = exception;
    }
}

或者以下会更好吗?

public class TestLogEntry {
    public string StackTrace { get; private set; }
    public System.Type ExceptionType { get; private set; }
    public string ExceptionMessage { get; private set; }

    public TestLogEntry(/*...,*/ System.Exception exception = null) {
        //...

        if (exception != null) {
            StackTrace = exception.StackTrace;
            ExceptionType = exception.GetType();
            ExceptionMessage = exception.Message;
        }
    }
}

虽然第一种方法更灵活(因为它可以包含其他自定义数据),但我担心的是:

  • 长时间坚持异常对象。
  • 如果异常对象阻止大对象被垃圾回收,则使用大量内存。
  • 在上下文中访问时返回错误值的异常。

Q1。以上问题是否有效?

Q2。异常对象通常会引用很多其他数据吗?

3 个答案:

答案 0 :(得分:4)

您的疑虑是有效的:异常对象可能会保留在任意其他对象上。这在实践中非常罕见。实际上我从未见过使用Exception.Data属性。但我看到Exception派生类使用自定义字段保留了大量内容:WebException具有WebResponse属性!

所以你看到即使像非托管资源这样昂贵的东西,你也可能活着。

我实际上会复制这些信息并丢弃Exception。请务必复制InnerException

另一个问题可能是Exception可变类型。你可以在任何时候改变它的堆栈跟踪。因为这个原因,我想抓住它的状态。

内存使用也很重要。异常有一些可能从未使用过的字段。你可以保存它们。此外,将其字段内联到您的日志消息对象将消除对象标头和对象引用。虽然经常例外,但收益微不足道,但也许值得一试。

答案 1 :(得分:3)

坚持例外是可以的。

一般来说,他们没有太多数据(堆栈跟踪,错误消息和相关数据),但这并不是很多。

异常的一个实例不会影响同一类型的其他实例。

所以:

  

长时间坚持异常对象。

没问题。

  

如果异常对象阻止大对象被垃圾回收,则使用大量内存。

如果您向异常添加大量数据,则只会出现问题 - 如果不这样做,则不是问题。

  

在脱离上下文访问时返回错误值的异常。

不确定这意味着什么 - 背景是什么?例外是一个例外。

答案 2 :(得分:0)

我认为你应该意识到,当你写“长时间”或“很多”时,这些是相对的而不是绝对的,所以没有人能够说出这些问题是否过多。我的10核机器上有2Gb的RAM,而且我部署到Windows服务器,所以内存的影响不会让我感到烦恼。也许你在旧的Windows手机上运行,​​只有几个字节的备用RAM。谁知道?如果您有疑问,请记录您的记忆使用情况,但如果记忆存在问题,我会感到惊讶。

一般来说,对我来说更大的担忧是你可能会想要使用Exceptions作为向用户显示状态消息的方式,这并不酷。例外情况适用于特殊条件。你甚至可能无法有意义地恢复它们,更不用说像往常一样继续。如果要保留记录,可以将异常记录到数据库中(例如使用log4net),但我认为您最好记录它们而不是保留它们。