C# 如何分解try/catch代码?

C# 如何分解try/catch代码?,c#,C#,我有一个C代码,它使用一个可以抛出异常的外部库。 在代码的三个部分中,我希望以以下方式处理这些异常: try { CallOtherLibrary(); } catch(ExceptionA) { ProcessErrorA(); } catch(ExceptionB) { ProcessErrorB(); } 现在我认为复制粘贴这个代码是一种代码气味。 一种可能的修复方法是创建一个将操作作为参数的方法,并执行try/catch。但它迫使我复制调用try/catch的每个方法

我有一个C代码,它使用一个可以抛出异常的外部库。 在代码的三个部分中,我希望以以下方式处理这些异常:

try {
   CallOtherLibrary();
}
catch(ExceptionA) {
   ProcessErrorA();
} catch(ExceptionB) {
   ProcessErrorB();
}
现在我认为复制粘贴这个代码是一种代码气味。 一种可能的修复方法是创建一个将操作作为参数的方法,并执行try/catch。但它迫使我复制调用try/catch的每个方法,这会导致更多代码,可读性降低

考虑到我无法更改外部库的行为,处理此问题的干净方法是什么?

您可以创建一个Dictionary exceptionHandlers,然后调用 catch块中的exceptionHandlers[exception.GetType]

    void ProcessErrorA() { }

    void Main() 
    {
        Dictionary<Type, Action> exceptionHandlers = new Dictionary<Type, Action>();
        exceptionHandlers.Add(typeof(NullReferenceException), ProcessErrorA);

        try{}
        catch (Exception e) 
        {
            if (exceptionHandlers.ContainsKey(e.GetType()))
            {
                exceptionHandlers[e.GetType()]();
            }
            else 
            {
                // We don't have any handler for this exception. 
            }
        }
    }
您可以创建一个字典exceptionHandlers,然后调用 catch块中的exceptionHandlers[exception.GetType]

    void ProcessErrorA() { }

    void Main() 
    {
        Dictionary<Type, Action> exceptionHandlers = new Dictionary<Type, Action>();
        exceptionHandlers.Add(typeof(NullReferenceException), ProcessErrorA);

        try{}
        catch (Exception e) 
        {
            if (exceptionHandlers.ContainsKey(e.GetType()))
            {
                exceptionHandlers[e.GetType()]();
            }
            else 
            {
                // We don't have any handler for this exception. 
            }
        }
    }

您正在寻找外星人库的包装。在C中,这通常是通过使用一个接口和一个充当/的方法来完成的

您创建了一个充当适配器的新类,实现了适配器接口,在实现的方法中,您将获得问题中提到的代码。然后用对新创建的适配器的方法的调用替换原始代码,并在代码库中使用该方法


为您不拥有的库安装适配器并使用此适配器的好处是,如果所述外部库的方法签名将来发生更改,则不必重写您自己的逻辑,而只需在适配层中更改它,您就可以重新设置了。

您正在寻找外来库的包装器。在C中,这通常是通过使用一个接口和一个充当/的方法来完成的

您创建了一个充当适配器的新类,实现了适配器接口,在实现的方法中,您将获得问题中提到的代码。然后用对新创建的适配器的方法的调用替换原始代码,并在代码库中使用该方法


为您不拥有的库安装适配器并使用此适配器的好处是,如果所述外部库的方法签名将来发生更改,则不必重写您自己的逻辑,而只需在自适应层中更改它,您就可以重新设置了。

也许您可以做类似这样的事情,以适应自己的使用:

class Program
{
    public int Divide_InExternalLib(int a, int b)
    {
        Console.WriteLine(string.Format("a={0}, b={1}", a, b));
        int result = a / b;
        Console.WriteLine(string.Format("Result = {0}", result));
        return result;
    }


    public void CallExternalFunction(Action funct)
    {
        try
        {
            funct.Invoke();
        }
        catch (Exception ex)
        {
            Console.WriteLine(string.Format("Exception caught: {0}", ex.ToString()));
        }
    }

    static void Main(string[] args)
    {
        var p = new Program();
        int a = 6;
        int b = 2;
        p.CallExternalFunction(() => { p.Divide_InExternalLib(a, b); });
        b = 0;
        p.CallExternalFunction(() => { p.Divide_InExternalLib(a, b); });

        Console.ReadLine();
    }
}
输出

a=6, b=2
Result = 3
a=6, b=0
Exception caught: System.DivideByZeroException: Attempted to divide by zero.
   at GenericExceptionHandling.Program.Divide_InExternalLib(Int32 a, Int32 b) in
 c:\users\siebiers\documents\visual studio 2015\Projects\GenericExceptionHandlin
g\GenericExceptionHandling\Program.cs:line 16
   at GenericExceptionHandling.Program.<>c__DisplayClass2_0.<Main>b__1() in c:\u
sers\siebiers\documents\visual studio 2015\Projects\GenericExceptionHandling\Gen
ericExceptionHandling\Program.cs:line 41
   at GenericExceptionHandling.Program.CallExternalFunction(Action funct) in c:\
users\siebiers\documents\visual studio 2015\Projects\GenericExceptionHandling\Ge
nericExceptionHandling\Program.cs:line 26

也许你可以做一些像这样的事情来适应自己的使用:

class Program
{
    public int Divide_InExternalLib(int a, int b)
    {
        Console.WriteLine(string.Format("a={0}, b={1}", a, b));
        int result = a / b;
        Console.WriteLine(string.Format("Result = {0}", result));
        return result;
    }


    public void CallExternalFunction(Action funct)
    {
        try
        {
            funct.Invoke();
        }
        catch (Exception ex)
        {
            Console.WriteLine(string.Format("Exception caught: {0}", ex.ToString()));
        }
    }

    static void Main(string[] args)
    {
        var p = new Program();
        int a = 6;
        int b = 2;
        p.CallExternalFunction(() => { p.Divide_InExternalLib(a, b); });
        b = 0;
        p.CallExternalFunction(() => { p.Divide_InExternalLib(a, b); });

        Console.ReadLine();
    }
}
输出

a=6, b=2
Result = 3
a=6, b=0
Exception caught: System.DivideByZeroException: Attempted to divide by zero.
   at GenericExceptionHandling.Program.Divide_InExternalLib(Int32 a, Int32 b) in
 c:\users\siebiers\documents\visual studio 2015\Projects\GenericExceptionHandlin
g\GenericExceptionHandling\Program.cs:line 16
   at GenericExceptionHandling.Program.<>c__DisplayClass2_0.<Main>b__1() in c:\u
sers\siebiers\documents\visual studio 2015\Projects\GenericExceptionHandling\Gen
ericExceptionHandling\Program.cs:line 41
   at GenericExceptionHandling.Program.CallExternalFunction(Action funct) in c:\
users\siebiers\documents\visual studio 2015\Projects\GenericExceptionHandling\Ge
nericExceptionHandling\Program.cs:line 26

提供一个公共异常处理函数

static void Main(string[] args)
        {
            try
            {
                CallOtherLibrary();
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
        }


        private static void HandleException(Exception ex)
        {
            if (ex is ExceptionA)
            {
                ProcessErrorA();
            }
            else if (ex is ExceptionB)
            {
                ProcessErrorB();
            }
        }

提供一个公共异常处理函数

static void Main(string[] args)
        {
            try
            {
                CallOtherLibrary();
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
        }


        private static void HandleException(Exception ex)
        {
            if (ex is ExceptionA)
            {
                ProcessErrorA();
            }
            else if (ex is ExceptionB)
            {
                ProcessErrorB();
            }
        }

您是否要执行完全相同的代码来响应完全相同的异常,只是它发生在对另一个库的不同调用期间?我的意思是,ExceptionA在所有情况下都有相同的响应吗?全局异常处理程序可能会有所帮助,如果它适合您的上下文,那么异常处理与日志记录等类似。您是否要执行完全相同的代码来响应完全相同的异常,只是它发生在对另一个库的不同调用期间?我的意思是,ExceptionA在所有情况下都有相同的响应吗?全局异常处理程序可能会有所帮助,如果它适合您的上下文,那么异常处理与日志记录等类似。