How to fire multiple exceptions?

Asked

Viewed 245 times

6

foreach (Foo el in arr) {
    // ...
    Validate(el);
    // ...
}

In the example code, when the foreach is executed, an exception can be triggered from the function Validate which will be treated on who called the method containing the loop.

The exceptions triggered by Validate has to be handled by the user. The most convenient would be for the user to know all the errors that were played to correct them before re-running the function that contains the loop. For that, I’d have to do something like:

List<Exception> errors = new List<Exception>();

foreach (Foo el in arr) {
    // ...

    try {
        Validate(el);
    } catch(Exception e) {
        errors.Add(e);
    }

    // ...
}

if(erros.Any()) {
    throw errors; // somente objetos do tipo Exception podem ser disparados com throw.
}

How I fire multiple exceptions?

  • 3

    I’m not sure I understand the explanation of the problem. The conclusion of what I would have to do to solve it and perhaps that is why the question itself does not seem to make sense and the answer would be "no". Maybe because you don’t understand the problem you can’t see the motivation to try this.

  • 1

    Should exceptions be used for flow control? (https://answall.com/a/48458/41056)

2 answers

10


This seems to me a conceptual error in the code.

Apparently you are using exceptions to treat validations and this is not only wrong as it is very bad, it is an extreme misuse of the exception mechanism.

Leaving this aside the short answer to your question is: Is not possible.

Exceptions are for, as the name says, exceptional cases and not for data validation or similar tasks.

Assuming you don’t want to fix the code and stop using these exceptions, the most you can do is pass this list of exceptions to the GUI layer and there do something to show the desired messages (or do what you like).

But in this way, it is not possible to capture them using a block catch.

It is still possible to fire a AggregateException based on the list of exceptions and capture it. Something like:

To fire:

if(erros.Any()) {
    throw new AggegateException("Mensagem", errors);
}

To capture:

catch (AggregateException ae) 
{
    ae.Handle((x) =>
    {
        // Todas as exceções dentro de 'ae' passarão por este bloco
        return true; // Isso impede a parada do código
    });
}

It might be interesting to read these publications:


Functional code of the example with AggregateException. See working on . NET Fiddle.

using System;
using static System.Console;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        try
        {
            FazerAlgo();
        }
        catch (AggregateException ae)
        {
            ae.Handle((ex) =>
                      {
                          WriteLine(ex.Message);
                          return true;
                      });
        }
    }

    static void FazerAlgo()
    {
        throw new AggregateException("", new List<Exception>
                                     {
                                         new Exception("Erro 1"),
                                         new Exception("Erro 2")
                                     });
    }
}
  • Cool. Can you talk a little bit more about not handling exceptions for validation? For example, my method Gravar, class, call the method Validar, class as well, as my view would be aware of the error that occurred to interrupt the flow and show the validation error?

  • 1

    @vnbrs You need to develop with this in mind. There are many techniques. For example, in ASP.NET MVC, controller validations are made based on annotations (attributes) which are defined in the classes. There is Fluent validation and so on. About these two methods being in the same class: I cannot say that this is wrong or that it will not work, but the validation should be closer to the UI and less close to the functioning. If you start to separate the responsibilities and distribute them between the "layers" of the application you will notice that it is easier to do this kind of validation.

8

If you really want to throw several exceptions at once for the code caller, use the class AggregateException, she gets a list of Exception.

I adapted your code as example:

List<Exception> errors = new List<Exception>();

foreach (Foo el in arr) {
    // ...

    try {
        Validate(el);
    } catch(Exception e) {
        errors.Add(e);
    }

    // ...
}

if(erros.Any()) {
    throw new AggregateException(
        "Vários erros ocorreram durante a execução do método.",
        errors)
}
  • I voted for the answer because it seems to me that it answers the question, I just want to say that I find this very rare to be useful, almost always has gambiarra in this.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.