5

所以我在方法中有以下代码块:(所有变量都是本地的)

// ...

try
{
    if (postXml != null)
        using (StreamWriter writer = new StreamWriter(req.GetRequestStream()))
            writer.Write(postXml.ToString());
}
catch (WebException ex)
{
    HttpWebResponse response = ex.Response as HttpWebResponse;
    if (response != null)
        result = HandleOtherResponse(response, out status);
    else result = HandleBadResponse(ex.ToString(), out status);
}
catch (Exception ex)
{
    result = HandleBadResponse(ex.ToString(), out status);
}

if (result == null)
{
    try
    {
        HttpWebResponse response = req.GetResponse() as HttpWebResponse;
        result = HandleOtherResponse(response, out status);
    }
    catch (WebException ex)
    {
        HttpWebResponse response = ex.Response as HttpWebResponse;
        if (response != null)
            result = HandleOtherResponse(response, out status);
        else result = HandleBadResponse(ex.ToString(), out status);
    }
    catch (Exception ex)
    {
        result = HandleBadResponse(ex.ToString(), out status);
    }
}

// ...

可以看到,两个try语句是不同的,但是两组catch语句是完全一样的。我一直在想一种方法,可以不在这里重复自己,但我还没有真正想到一种方法不会显着变慢或看起来很糟糕。想知道是否有人有任何想法。

4

3 回答 3

5

一种方法是编写一个“安全”的调用方法并将一个函数传递给它:

public T SafeInvocation(Func<T> myMethod)
{
    T result = default(T);

    try
    {
        // Invoke method
        result = myMethod();
    }
    catch
    {
        // Do your common catch here
    }

    return result;
}

为 Action<T> 构建一个额外的重载,这样您就不需要返回类型。然后你可以在别处调用它,将方法作为参数传递给你的方法(Inception?):

SafeInvocation(() => 
{
    if (postXml != null)
        using (StreamWriter writer = new StreamWriter(req.GetRequestStream()))
            writer.Write(postXml.ToString());
}
于 2013-06-26T21:24:26.213 回答
0

您可以将 an 传递给Action处理异常的函数:

private void HandleErrorsFor(Action action)
{
    try
    {
        action();
    }
    catch (Exception ex)
    {
        //repeated exception handling...
    {
}

//...

public void DoSomething()
{
    HandleErrorsFor(() => {
        //try block #1
    });

    HandleErrorsFor(() => {
        //try block #2
    });
}

它更容易阅读并避免重复代码。

于 2013-06-26T21:23:03.967 回答
0

你可以对代表做一些事情并同时覆盖trycatch块:

  static class Program
  {
      delegate void CodeBlock();

      internal delegate void ExceptionCatcher(Exception ex);


    private static void Main()
    {
        CodeBlock b = () => { Console.WriteLine("HELLO WORLD"); };
        CodeBlock error = () => { throw new Exception("Exception thrown"); };
        ExceptionCatcher silence = exception => { };
        ExceptionCatcher e = exception =>
            {
                var currentColor = Console.BackgroundColor;
                Console.BackgroundColor = ConsoleColor.Red;
                Console.WriteLine(exception.Message);
                Console.BackgroundColor = currentColor;
            };

        DRYRunner(b, e);
        DRYRunner(error , e);
        DRYRunner(error , silence);

        Console.ReadLine();
    }

    static void DRYRunner (CodeBlock block, ExceptionCatcher catcher)
    {
        try
        {
            block.Invoke();
        }
        catch (Exception ex)
        {
            catcher(ex);
        }
    }
}   

编辑:扩展它,我们可以创建一个类来帮助包含代码块并将其与其可能的异常和处理程序相关联。您甚至可以创建一类常见的异常处理程序并相应地引用它们,将它们与 ad-hoc 处理程序混合:

 class ExceptionHandledDelegate
{
    public delegate void CodeBlock();

    public delegate void ExceptionCatcher(Exception ex);

    public Dictionary<Type, ExceptionCatcher> ExceptionHandlers;

    public CodeBlock codeBlock { get; set; }

    public void Run()
    {
        try
        {
            codeBlock.Invoke();
        }
        catch (Exception ex)
        {
            var mn = ex.GetType();
            if (ExceptionHandlers.Keys.Contains(mn))
            {
                ExceptionHandlers[mn](ex);
            }
            else throw; 
        }

    }
}
class CommonHandlers
{
    public static void ArgumentHandler(Exception ex)
    {
        Console.WriteLine("Handling an argument exception");
    }

    public static void DivZeroHandler(Exception ex)
    {
        Console.WriteLine("Please don't divide by zero. It upsets the universe.");
    }
}
static class Program
{

    private static void Main()
    {
        var ehd = new ExceptionHandledDelegate
        {
            codeBlock = () => { throw new ArgumentException("An argument exception has been thrown"); },
            ExceptionHandlers = new Dictionary<Type, ExceptionHandledDelegate.ExceptionCatcher>
            {
                {typeof (ArgumentException), CommonHandlers.ArgumentHandler},
                {typeof (DivideByZeroException ),CommonHandlers.DivZeroHandler},
                {typeof (Exception), exception => Console.WriteLine("An exception has been thrown")}
            }
        };
        ehd.Run();
        ehd.codeBlock = () => { throw new Exception("An exception has been thrown"); };
        ehd.Run();
        ehd.codeBlock = () =>{var denom = 0; Console.WriteLine(100 / denom);};
        ehd.Run();
        Console.ReadLine();
    }
}
于 2013-06-26T21:32:09.810 回答