在C#中,重复使用异常处理逻辑的最佳方法是什么?

5

我有两个函数,它们的逻辑不同但异常处理基本相同:

public void DoIt1  // DoIt2 has different logic but same exception handling
{
    try
       ... DoIt1 logic
    catch (MySpecialException myEx)
    {
       Debug.WriteLine(myEx.MyErrorString);
       throw;
    }
    catch (Exception e)
    {
       Debug.WriteLine(e.ToString());
       throw;
    }
}

由于DoIt1和DoIt2是从外部调用的,因此无法使用单个入口点。对于异常块的复制/粘贴是否是最佳方法?

5个回答

6

这取决于...如果有很多共性,你可以将要做的事情作为参数传递 - 无论是接口还是委托:

void Foo(Action thingToDo) {
    if(thingToDo == null) throw new ArgumentNullException("thingToDo");
    try {
        thingToDo();
    } catch {...} // lots of
}

并像这样调用:

Foo(delegate { /* logic A */ });

Foo(delegate { /* logic B */ });

5

尝试:

public static class Catching<TException> where TException : Exception
{
    public static bool Try<T>(Func<T> func, out T result)
    {
        try
        {
            result = func();
            return true;
        }
        catch (TException x) 
        {
            // log exception message (with call stacks 
            // and all InnerExceptions)
        }

        result = default(T);
        return false;
    }

    public static T Try<T>(Func<T> func, T defaultValue)
    {
        T result;
        if (Try(func, out result))
            return result;

        return defaultValue;
    }
}

例子:

int queueSize = Catching<MyParsingException>
    .Try(() => Parse(optionStr, "QueueSize"), 5);

如果Parse抛出MyParsingException,则queueSize将默认为5,否则将使用从Parse返回的值(或任何其他异常将正常传播,这通常是您想要的意外异常)。
这有助于避免打断代码流程,并且集中了您的日志记录策略。
您可以编写特殊版本的此类异常包装以处理特殊情况,例如捕获一组特定的三个异常,或其他任何情况。

2

如果你想要更极端的解决方案,可以尝试使用面向切面编程技术和工具,如PostSharpMicrosoft Policy Injection Block。这样,你可以定义一个切面来处理异常,并将其编织到需要它的代码中的所有位置。


1

如果您只想记录异常消息和项目,而不在catch块中进行特殊处理,可以创建一个基于反射的对象记录器,并将异常作为参数传递。这样做,您就不需要很多catch块。

如果您是代码的所有者,可以将日志记录过程放在MySpecialException的构造函数中,删除catch块并使代码更清晰。


0
你可以有类似这样的代码:
public static class ErrorHandler
{

    public static void HandleMyException(MyException myEx)
    {
        Debug.WriteLine(myEx.MyErrorString);
        throw;
    }

    public static void HandleException(Exception myEx)
    {
        Debug.WriteLine(e.ToString());
        throw;
    }

}

或者,在这种特定情况下,使用更通用的函数,例如:

public static class ErrorHandler
{

    public static void WriteAndThrow(string msg)
    {
        Debug.WriteLine(msg);
        throw;
    }

}

重载在运行时不起作用,每个DoIt中有多个catch正是需要避免的。 - Sergey Aldoukhov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接