using
最近、自分のコードでネストされたステートメントのレベルが上がっていることに気付きました。その理由はおそらく、私がより多くの pattern を使用しているためであり、これにより、またはasync/await
の少なくとも 1 つが追加されることがよくあります。using
CancellationTokenSource
CancellationTokenRegistration
using
では、コードがクリスマス ツリーのように見えないように、のネストを減らすにはどうすればよいでしょうか。以前に SO で同様の質問がありました。回答から学んだことをまとめたいと思います。
using
インデントなしで隣接して使用します。偽の例:
using (var a = new FileStream())
using (var b = new MemoryStream())
using (var c = new CancellationTokenSource())
{
// ...
}
これはうまくいくかもしれませんが、多くの場合、いくつかのコードが間using
にあります (たとえば、別のオブジェクトを作成するには時期尚早かもしれません):
// ...
using (var a = new FileStream())
{
// ...
using (var b = new MemoryStream())
{
// ...
using (var c = new CancellationTokenSource())
{
// ...
}
}
}
同じ型 (または にキャストIDisposable
) のオブジェクトを結合して singleusing
にします。例:
// ...
FileStream a = null;
MemoryStream b = null;
CancellationTokenSource c = null;
// ...
using (IDisposable a1 = (a = new FileStream()),
b1 = (b = new MemoryStream()),
c1 = (c = new CancellationTokenSource()))
{
// ...
}
これには上記と同じ制限があり、さらに冗長で読みにくい、IMO.
メソッドをいくつかのメソッドにリファクタリングします。
私が理解している限り、これは好ましい方法です。それでも、私は興味があります.なぜ次のことが悪い習慣と見なされるのでしょうか?
public class DisposableList : List<IDisposable>, IDisposable
{
public void Dispose()
{
base.ForEach((a) => a.Dispose());
base.Clear();
}
}
// ...
using (var disposables = new DisposableList())
{
var a = new FileStream();
disposables.Add(a);
// ...
var b = new MemoryStream();
disposables.Add(b);
// ...
var c = new CancellationTokenSource();
disposables.Add(c);
// ...
}
[更新]一部の内部呼び出しがスローされた場合でも、ネストされたusing
ステートメントが各オブジェクトで呼び出されることを確認するコメントには、かなりの数の有効なポイントがあります。ただし、ややあいまいな問題があります。ネストされた「using」フレームを破棄することによってスローされる可能性のあるすべてのネストされた例外は、最も外側のものを除いて失われます。詳細はこちら。Dispose
Dispose