3

我正在创建一个测试记录器,其中将包含有关引发的任何异常的信息,以便它们可以使用 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。异常对象通常会引用很多其他数据吗?

4

3 回答 3

4

您的担忧是正确的:异常对象可能会保留任意其他对象。这在实践中非常罕见。其实我从来没有见过Exception.Data使用的财产。但是我已经看到Exception派生类使用自定义字段持有一些重要的东西:WebException有一个WebResponse属性!

因此,您会发现,即使是像非托管资源这样昂贵的东西,您也可能会保持活力。

我实际上会复制信息并丢弃Exception. 记得也要复制InnerException.

另一个问题可能Exception可变类型。你可以随时抛出它来改变它的堆栈跟踪。出于这个原因,我想捕获它的状态。

同样重要的是内存使用。异常有一些可能从未使用过的字段。你可以保存它们。此外,将其字段内联到您的日志消息对象中将消除对象标头和对象引用。一个小小的收获,但在频繁出现异常的情况下可能值得一试。

于 2013-02-07T19:56:46.890 回答
3

坚持例外是好的。

一般来说,它们不会保存太多数据(堆栈跟踪、错误消息和相关数据),但这并不多。

并且一个异常实例不会影响其他实例,即使是相同类型的实例。

所以:

长时间持有异常对象。

没问题。

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

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

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

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

于 2013-02-07T19:56:18.573 回答
0

我认为您应该意识到,当您写“延长”或“很多”时,这些是相对而非绝对的术语,因此没有人能够说出这些担忧是否过多。我的 10 核机器上有 2Gb 的 RAM,并且我部署到 Windows 服务器,所以内存影响丝毫不会打扰我。也许您正在使用只有几个字节的备用 RAM 的旧 Windows 手机上运行。谁知道?如果您有疑问,请分析您的内存使用情况,但如果内存是一个问题,我会感到惊讶。

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

于 2013-02-07T20:02:28.597 回答