在邮件中包装异常而不抛出异常

时间:2015-03-23 16:33:38

标签: c#

我正在编写一个服务,其中的方法不能抛出异常但应该返回一个通用的Message - 对象,其中包含方法调用的实际结果和异常(如果有的话)。这个Message类看起来像这样:

public class Message<T>
{
    private List<Exception> exceptions = new List<Exception>();

    public T Result { get; set; }

    public void AddException(Exception x)
    {
        this.exceptions.Add(x);
    }

    public bool HasExceptions
    {
        get
        {
            return this.exceptions.Count > 0;
        }
    }

    public IEnumerable<Exception> Exceptions
    {
        get
        {
            foreach (var exception in this.exceptions)
                yield return exception;
        }
    }
}

通常,服务方法的实现如下所示:

public Message<int> MyServiceMethod()
{
    var msg = new Message<int>();

    try
    {
        // do something useful here
        msg.Result = 42;
    }
    catch (Exception x)
    {
       msg.AddException(x);
    }

    return msg;
}

然后,调用者可以在必要时处理异常。

var msg = service.MyServiceMethod();
if (msg.HasExceptions)
{
   // Handle exceptions here
}

现在我有一个带有参数的服务方法,该参数必须在一定范围内。因为如果参数超出范围我觉得用ArgumentOutOfRangeException回答是很自然的,我实现了这样:

public Message<int> MyOtherServiceMethod(int arg)
{
    var msg = new Message<int>();

    if (arg < 1)
    {
        msg.AddException(new ArgumentOutOfRangeException("arg", "Argument must be greater than 0"));
        return msg;
    }

    // ...
    return msg;
}

基本上这是有效的。我唯一缺少的是异常的堆栈跟踪。这不是问题,因为在我的场景中我不需要这样做。但它让我想知道,还有其他任何副作用吗?#34;使用异常但不抛出时可能会造成麻烦?

2 个答案:

答案 0 :(得分:0)

您应该使用一些以messageexception作为参数的构造:

try
{
    // do something useful here
}
catch (Exception x)
{
   throw YourPreferredException(some_message, x);
}

这会使x可用作yourPreferredException.InnerException属性。

此外,我不认为让方法返回Message并在中运行try/catch是一个很好的设计选择(应该反过来说。)

答案 1 :(得分:0)

我会说这并不是C#中异常的预期用途。如果您需要自定义消息,那么您只需使用接收消息的Exception构造函数和另一个类型为Exception的实例,这将为您提供一个新的异常,其中包含您的自定义消息以及原始异常集作为实例InnerException属性。你只需要在这里重新发明一些定制的消息&#39;类。如果您要做的只是返回一条消息(就像您不想抛出那样),那么您应该使用异常Message属性并将其分配给某个字符串或直接返回该字符串。

以下是一些处理错误的惯用示例;

Message ret = new Message();
try
{}
catch (Exception e)
{
    ret.ErrorPropertyOfTypeString = e.Message;
}
return ret;


Message ret = new Message();
try
{}
catch (Exception e)
{
    throw new Exception("My custom message here", e);
}
return ret;

无论你做什么,上面两种模式中的一种都应该用来代替。