在.Net / C#中抛出多个异常 [英] Throwing multiple exceptions in .Net/C#

查看:244
本文介绍了在.Net / C#中抛出多个异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我处理的应用程序中,任何业务逻辑错误导致抛出异常,并且调用代码处理异常。该模式在整个应用程序中使用,并且工作良好。



我有一种情况,我将尝试从业务层内部执行一些业务任务。对此的要求是,一个任务的失败不应该导致进程终止。其他任务仍然可以执行。换句话说,这不是原子操作。我所遇到的问题是,在操作结束时,我希望通过调用代码通过抛出异常来通知异常或异常。考虑以下伪代码片段:

  function DoTasks(MyTask [] taskList)
{
foreach (TaskList中的MyTask任务)
{
try
{
DoTask(task);
}
catch(Exception ex)
{
log.add(ex);
}
}

//如果发生任何异常,我想扔东西
}

我该怎么办?我在职业生涯中遇到过这种模式。在过去,我保存了所有异常的列表,然后抛出一个包含所有捕获的异常的异常。这似乎不是最优雅的方法。重要的是保留尽可能多的细节从每个例外提交给呼叫代码。



想法?






编辑:解决方案必须以.Net 3.5编写。我不能使用任何beta库,或者 Bradley Grainger (下))提到的.Net 4.0中的AggregateException将是一个很好的解决方案,用于收集异常

解决方案

.NET的任务并行库扩展(其中将成为.NET 4.0的一部分)遵循其他答案中建议的模式:收集所有引入AggregateException类的异常。



通常总是抛出相同的类型(无论是从小孩工作还是其他工作都有一个例外),处理异常的调用代码更容易编写。



在.NET 4.0 CTP, AggregateException 有一个公共构造函数(取$ IEnumerable< Exception> );它可能是您的应用程序的一个不错的选择。



如果您要定位.NET 3.5,请考虑克隆 System.Threading的部分。您在自己的代码中需要的AggregateException 类,例如一些构造函数和InnerExceptions属性。 (您可以将克隆放在程序集中的 System.Threading 命名空间中,如果您公开暴露,则可能会导致混淆,但稍后会将其升级到4.0)。当.NET 4.0发布时,您应该能够通过从项目中删除包含克隆的源文件,将项目更改为目标新的框架版本和重建,从而升级到框架类型。当然,如果你这样做,你需要仔细跟踪这个类的更改,因为Microsoft发布了新的CTP,这样你的代码就不会变得不兼容。 (例如,这似乎是一个有用的通用类,他们可以将它从 System.Threading 移动到 System 。)在最坏的情况下,您可以重命名类型并将其移回自己的命名空间(这对大多数重构工具来说非常简单)。


In an application I work on, any business logic error causes an exception to be thrown, and the calling code handles the exception. This pattern is used throughout the application and works well.

I have a situation where I will be attempting to execute a number of business tasks from inside the business layer. The requirement for this is that a failure of one task should not cause the process to terminate. Other tasks should still be able to execute. In other words, this is not an atomic operation. The problem I have is that at the end of the operation, I wish to notify the calling code that an exception or exceptions did occur by throwing an exception. Consider the following psuedo-code snippet:

function DoTasks(MyTask[] taskList)
{
  foreach(MyTask task in taskList)
  {
    try
    {
       DoTask(task);
    }
    catch(Exception ex)
    {
        log.add(ex);
    }
  }

  //I want to throw something here if any exception occurred
}

What do I throw? I have encountered this pattern before in my career. In the past I have kept a list of all exceptions, then thrown an exception that contains all the caught exceptions. This doesn't seem like the most elegant approach. Its important to preserve as many details as possible from each exception to present to the calling code.

Thoughts?


Edit: The solution must be written in .Net 3.5. I cannot use any beta libraries, or the AggregateException in .Net 4.0 as mentioned by Bradley Grainger (below) would be a nice solution for collection exceptions to throw.

解决方案

The Task Parallel Library extensions for .NET (which will become part of .NET 4.0) follow the pattern suggested in other answers: collecting all exceptions that have been thrown into an AggregateException class.

By always throwing the same type (whether there is one exception from the child work, or many), the calling code that handles the exception is easier to write.

In the .NET 4.0 CTP, AggregateException has a public constructor (that takes IEnumerable<Exception>); it may be a good choice for your application.

If you're targeting .NET 3.5, consider cloning the parts of the System.Threading.AggregateException class that you need in your own code, e.g., some of the constructors and the InnerExceptions property. (You can place your clone in the System.Threading namespace inside your assembly, which could cause confusion if you exposed it publicly, but will make upgrading to 4.0 easier later on.) When .NET 4.0 is released, you should be able to "upgrade" to the Framework type by deleting the source file containing your clone from your project, changing the project to target the new framework version, and rebuilding. Of course, if you do this, you need to carefully track changes to this class as Microsoft releases new CTPs, so that your code doesn't become incompatible. (For example, this seems like a useful general-purpose class, and they could move it from System.Threading to System.) In the worst case, you can just rename the type and move it back into your own namespace (this is very easy with most refactoring tools).

这篇关于在.Net / C#中抛出多个异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆