5

try..catch.finallyブロックをどのようにフォーマットしていますか? 特に、少量のコードだけをラップすると、すべてが吹き飛ばされ、コードがかなり読みにくく、見苦しくなります。

そのような:

try
{
     MyService service = new Service();
     service.DoSomething();
     return something;
}
catch (Exception ex)
{
     LogSomething();
     return somethingElse;
}
finally
{
     MarkAsComplete();
     service.Dispose();
}

これらの 7 行のコードは、16 行の混乱に変わりました。

より良いtry..catch..finallyフォーマットに関する提案はありますか?

4

11 に答える 11

6

実際、これは私にとって非常によく読めます。実際のコードがこれによく似ている場合、私はそれについて心配する必要はありません。何が起こっているかは非常に明確です。

実際のコードがより複雑な場合は、ブロックを適切な名前のメソッドに分割することを検討してください。

于 2009-06-02T00:32:57.550 に答える
5

using明示的な の代わりにブロックを使用できますDispose()。または、破棄する前に null をチェックする必要がある可能性がありusingます。ブロックがそれを行います。残念ながら、ネストが増加します =/

try
{
     using(MyService service = new MyService()) 
     {
        service.DoSomething();
        return something;
     }
}
catch (SpecificException ex)
{
     LogSomething(ex);
     return somethingElse;
}
finally
{
     MarkAsComplete();
}
于 2009-07-15T22:30:58.920 に答える
4

まあ、それでいいと思います。これのいくつかは、中括弧の配置に関する議論に巻き込まれます。あなたはこれを行うことができます:

try {
  //
} catch(Exception ex) {
  //
} finally {
  //
}

私はあなたが持っているものを好みます。ただし、return ステートメントが 1 つだけになるようにコードを修正することを検討することをお勧めします。私はそれが少し良いデザインだと思います。

于 2009-06-02T00:31:36.977 に答える
2

同じ行に括弧を付けてコードをフォーマットします。

try {
   MyService service = new Service();
   service.DoSomething();
   return something;
} catch (Exception ex) {
   LogSomething();
   return somethingElse;
} finally {
   MarkAsComplete();
   service.Dispose();
}

より多くの間隔が必要な場合は、空白行を追加することを好みます。これは、コードの論理ブロック間の区切りとしても機能します。

于 2009-06-02T00:32:03.793 に答える
2

コンテナー (非常にスマートな工場) とアドバイス (煩雑な詳細をすべて処理するため) について考えるかもしれません。

Dear Mr. Container Sir,
Whenever I request from you an instance object of the interface ISomething,
    please construct for me an instance of the concrete class SomethingImpl;
    in addition, please see to it (however you do it) that, whenever I call a
    method on this instance, it is wrapped within a complicated and messy try-
    catch-finally which logs exceptions and mark calls as completed. That way,
    all I have to do is write the business logic that goes into the SomethingImpl
    and I don't have to worry about all the messy infrastuctural details.
Sincerely,
Mr. Agile.

これは、コードで次のように表示される場合があります。

//a class that knows how to take care of the messy infrastructure details
public class MyMessyInterceptor : IInterceptor {
    public void Intercept(IInvocation invocation) {
        //handle the messy details of continuing with the method-invocation,
        //but within a try-catch-finally that includes exception handling and
        //call logging.
    }
}

//a function that will configure a container (very smart factory)
public IContainer CreateContainer() {
    var builder = new ContainerBuilder();

    //tell the container-builder about the interceptor
    builder
        .Register(c => new MyMessyInterceptor())
        .Named("keep-my-code-clean")
    ;

    //tell the container what to do when you ask it for a ISomething
    builder
        .Register<SomethingImpl>()
        .As<ISomething>()
        .InterceptedBy("keep-my-code-clean")
    ;

    return builder.BuildContainer();
}

//some function out there in your code somewhere that needs to make a
//service call; there's hundreds of functions out there just like this
//in your code, and they all just got much simpler
public object GottaGoDoSomething() {
    //find the container
    var container = GetTheSingletonContainerObject();
    //ask for an instance of ISomething - it knows to provide a
    //SomethingImpl wrapped in an interceptor that takes care of all
    //the logging and exception handling
    var something = container.resolve<ISomething>();
    //call the big method
    return something.DoSomething();
    //magically (not really), the exception handling and logging are
    //already taken care of
}

インターセプター クラスの作成は 1 回だけ行われます。各インターセプターとサービス クラスの登録も 1 回だけ行われます。コンテナー (非常にスマートな工場) のセットアップは確かに複雑です。

ただし、コード内でサービス オブジェクトを使用する必要があり、その使用を例外処理やロギングなどの複雑で厄介なインフラストラクチャの詳細に埋め込む必要がある場所はすべて、非常にクリーンで非常に単純になりました。は 1 つしかありませんCreateContainerが、何百もの があるGottaGoDoSomethingため、少し複雑ですが、非常に簡単です。

(注: このコード例では、Autofac コンテナー フレームワークと Castle インターセプター フレームワークを使用しています。これは依存性注入パターンではなく、サービス ロケーション パターンの例であることは承知していますが、要点はインターセプターを説明し、インターセプターを登録することでした。コンテナー (依存性注入を説明するためのものではありません)。

于 2009-06-02T01:04:31.963 に答える
1

空白。最低限として、すべての return ステートメントの前と、コードの「作業を行う」セクションと「変数を作成する」セクションの間に、常に 1 行の空白を挿入します。

try
{
     MyService service = new Service();

     service.DoSomething();

     return something;

 }
catch (Exception ex)
{
     LogSomething();

     return somethingElse;

}
finally
{
     MarkAsComplete();
     service.Dispose();
}

ずっといい。

于 2009-06-02T00:29:58.413 に答える
0

私も、あなたがもともと持っていたものが好きです。.cs ファイル内の物理的な行は、コストがかからず、最終的な出力コードを変更しません。したがって、あなたやあなたのチームに最高の読みやすさを提供するために必要なものをすべて使用してください。

実際、コードを作成するときは、ここに示した 16 行よりも多くの行を使用して、自分自身または他の人のためにコメントを追加するようにしてください。

追加することで

// a comment that says what's going on

多くの場合、6 か月後にこの Try.Catch に戻ったときに、この Try.Catch が何をするべきかを思い出すことができます。

于 2009-06-02T01:14:22.537 に答える
0

あなたのフォーマットもよく読めると思います。私の提案は、catchステートメントを控えめに使用することです。実際に何かをキャッチする必要がある場合にのみ使用してください。それ以外の場合は、プログラムの他の部分に例外を処理させることができます。「早期に失敗する」というコンセプト全体。

try
{
    //do something that may throw an exception.
}
finally
{
    //handle clean up.
}

//let a method further down the stack handle the exception.
于 2009-06-02T00:48:33.073 に答える
0

個人的には、コードで前のスタイルに従う傾向があります...コメントを書く余地があり、ロジックの流れをよりよく示します。

私は横向きのワイドスクリーンを持っているので、空白を使用するとさまざまな列をうまく並べることができ、それほど多くの画面領域があるため、それほど害はありません...

try { // getting a service

     MyService service = new Service();
     service.DoSomething();

     return something;

}

catch (Exception ex) { // the fact that a service might be full/timedout

     LogSomething();

     return somethingElse;

} 

finally { // remove any resources the service may still hold.

     MarkAsComplete();
     service.Dispose();

}
于 2009-06-02T01:02:30.207 に答える
0

私は常に、すべての try catch ブロックをリファクタリングして、独自のメソッドにカプセル化しようとしています。

これにより、常にすべてが読みやすくなるように思われます。さらに、メソッドが 1 つのことだけを行うようにすることは、プログラミングの良い実践です。おそらく、try-catch-finally ステートメントの上下にコードがある場合、複数のことを行っていることになります。

于 2009-09-15T18:05:06.227 に答える