Основной вопрос по три-ловли с мульти-ловлей - PullRequest
2 голосов
/ 21 октября 2019

Хочу отловить исключение на разных шагах. Посмотрите на код ниже. Допустим, каждая функция Procedure1, Procedure2, ..., Procedure6 может выдавать различные виды исключений (могут перекрываться!). И если исключение произошло на шаге 1-3, я хочу выбросить вновь определенное исключение ex1 и шаг 4-6 ex2.

public void TestFunc(){
    try{
        var res1 = Procedure1();
        var res2 = Procedure2(res1);
        var res3 = Procedure3(res2);
        var res4 = Procedure4(res3);
        var res5 = Procedure5(res4);
        Procedure6(res5);
    }
    catch{
        // if error/exception occurs in step 1-3 throw exception 1
    }
    catch{
        // if error/exception occurs in step 4-6 throw exception 2
    }
}

Я прочитал https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/try-catch, но на самом делене понял смысла.

Если все шаги выдают разные исключения, то я могу поймать разные. Но исключения для разных шагов могут совпадать. Поэтому я не могу точно сказать, какой это шаг из сообщения об исключении. (Да, это можно преодолеть, добавив дополнительную информацию в сообщения об исключениях, но, опять же, я действительно не хочу изменять другие функции.)

Один из способов, которым я могу придумать, - это разбить TestFunc на две части. кусок, но опять же я действительно не хочу этого делать, так как это нарушает целостность функции.

И если мы разделим шаги на два try, редактор покажет сообщение res3 does not exist in the context. Это разумно, поскольку {} разделяет контекст.

public void TestFunc(){
    try{
        var res1 = Procedure1();
        var res2 = Procedure2(res1);
        var res3 = Procedure3(res2);
    }
    catch{
        // if error in step 1-3 throw exception 1
    }
    try{
        var res4 = Procedure4(res3); // error, res3 cannot be found in the context
        var res5 = Procedure5(res4);
        Procedure6(res5);
    }
    catch{
        // if error in step 4-6 throw exception 2
    }
}

Ответы [ 3 ]

3 голосов
/ 21 октября 2019

Я предлагаю вложенный конструкция

   try {
        var res1 = Procedure1();
        var res2 = Procedure2(res1);
        var res3 = Procedure3(res2);

        try { 
            var res4 = Procedure4(res3);
            var res5 = Procedure5(res4);

            Procedure6(res5); 
        }
        catch {
            // Specific exceptions if error/exception occurs in step 4-6 
        }   
    }
    catch {
        // Exceptions within res1...res3
        // Unspecific Exceptions within steps 4-6
    }
0 голосов
/ 21 октября 2019

Когда вы начинаете писать код с таким уровнем обработки ошибок, он обязательно становится очень многословным, и большая часть вашего кода заканчивается обработкой ошибок. Вы должны принять это.

Один из способов сделать это, как вы уже описали:

Res1 res1;
try
{
    res1 = Procedure1();
}
catch ....

Res2 res2;
try
{
    res2 = Procedure2(res1);
}
catch ....

В качестве альтернативы, вы можете написать процедуры в их собственных вспомогательных методах, которые обрабатывают их обработку ошибок:

private Res1 HandleProcecure1()
{
    try
    {
        return Procedure1();
    }
    catch ....
}

private Res2 HandleProcecure2(Res1 res1)
{
    try
    {
        return Procedure2(res1);
    }
    catch ....
}

...

var res1 = HandleProcedure1();
var res2 = HandleProcedure2(res1);

Если не существует методов, которым требуется точно одинаковая обработка исключений, лично я предпочитаю не пытаться группировать их. Дайте каждому свой набор catch операторов и напишите несколько вспомогательных методов, что означает, что вы не должны писать одни и те же вещи внутри каждого из них.

0 голосов
/ 21 октября 2019

Просто объявите переменные вне try:

public void TestFunc(){
    // declare all variables here
    ResultType res1, res2, res3, res4, res5;
    try{
        res1 = Procedure1();
        res2 = Procedure2(res1);
        res3 = Procedure3(res2);
    }
    catch{
        // if error in step 1-3 throw exception 1
    }
    try{
        res4 = Procedure4(res3); // error, res3 cannot be found in the context
        res5 = Procedure5(res4);
        Procedure6(res5);
    }
    catch{
        // if error in step 4-6 throw exception 2
    }
}
...