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);
    }
}

// ...

ご覧のとおり、2 つの try ステートメントは異なりますが、2 つの catch ステートメントのセットはまったく同じです。ここで同じことを繰り返さないようにする方法を考えてみましたが、大幅に遅くなったり、見栄えが悪くなったりしない方法は思いつきませんでした。誰かにアイデアがあるかどうか疑問に思っています。

4

3 に答える 3

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);
        }
    }
}   

編集: これを拡張して、コード ブロックを格納し、可能な例外とハンドラーに関連付けるのに役立つクラスを作成できます。一般的な例外ハンドラーのクラスを作成し、それに応じてそれらを参照して、それらをアドホック ハンドラーと混合することもできます。

 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 に答える
0

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 に答える