19

C#にはusing、特にIDisposableオブジェクト用のステートメントがあります。おそらく、usingステートメントで指定されたオブジェクトは、決定論的に解放されるべきある種のリソースを保持します。

ただし、プログラミングには、開始と終了が明確であるが、固有の言語サポートがない設計が多数あるように思われます。このusing構成は、コードエディターの組み込み機能を使用して、少なくともそのような設計または操作の範囲を明確かつ自然に強調する機会を提供します。

私が念頭に置いているのは、「開始」と「結合」を伴う非同期コード実行など、さまざまな種類がありますが、頻繁にBeginXXX()andメソッドで開始する種類の操作です。EndXXX()

この素朴な例を見てください。

webDataOperation.Start();
GetContentFromHardDrive();
webDataOperation.Join();
// Perform operation that requires data from both sources

代わりに、StartメソッドIDisposable.Disposeが結合操作を実行するメソッドを持つオブジェクトを返した場合はどうなりますか。

using(webDataOperation.Start()) {
    GetContentFromHardDrive();
}
// Perform operation that requires data from both sources

または、さらに良いことに、私が特に念頭に置いていたのは、高度に特殊化されたグラフィックブリッティングを実行し、Begin()andEnd()メソッド(DirectXおよびXNAにも存在するデザイン)を持つオブジェクトがあります。その代わり...

using(blitter.BlitOperation()) {
    // Do work
}
// Use result

より自然で読みやすいように見えますが、意図しない目的でIDisposableインターフェイスとステートメントを使用しているため、お勧めできませんか?using言い換えれば、これは直感的でない方法でオペレーターをオーバーロードすることと同等でしょうか?

4

6 に答える 6

20

これは完全に受け入れられる方法です。これらは因数分解型と呼ばれ、フレームワーク設計ガイドラインではこれを行うことを推奨しています。

基本的に、型が特定の有効期間で操作をラップする場合、IDisposableとusingステートメントを使用することを検討するのが適切です。

私は実際にこの特定のトピックについてここでもブログを書きました。

于 2009-07-07T23:54:35.630 に答える
12

反対することをお勧めします。私の考えでは、コードはコンパイラではなく、コードの管理者と効果的にやり取りするためのものであり、管理者の理解を念頭に置いて作成する必要があります。リソース、通常は管理されていないリソースを破棄するためだけに「使用」を使用しようとしています。

私は少数派です。ほとんどの人は、「例外がスローされた場合でもクリーンアップコードを実行したい」という汎用目的として「使用」を使用しているようです。

(1) 「try-finally」と呼ばれるそのためのメカニズムが既にある、(2) 意図されていない目的で機能を使用する、(3) クリーンアップ コードの呼び出しが重要ですが、なぜ呼び出された時点で表示されないのでしょうか? 大事なら見てもらいたい。

于 2009-07-08T05:51:19.460 に答える
6

できるからといって(またはPhil Haackが大丈夫だと言っているから)、そうすべきだという意味ではありません。

基本的な経験則:私があなたのコードを読んで、それが何をしているのか、そしてあなたの意図が何であったのかを理解できれば、それは受け入れられます。一方、何をしたのか、なぜそれをしたのかを説明する必要がある場合は、コードを保守している後輩の開発者をつまずかせるでしょう。

より良いカプセル化でこれを達成できる他の多くのパターンがあります。

結論:この「テクニック」はあなたに何も買わず、他の開発者を混乱させるためだけに機能します。

于 2009-07-08T00:12:42.087 に答える
5

これは一般的なパターンですが、個人的には、匿名のデリゲートやラムダを使用してはるかに明白な方法で同じ効果を達成できる場合、そのように IDisposable を悪用する言い訳はないと思います。すなわち:

blitter.BlitOperation(delegate
{
   // your code
});
于 2009-07-08T00:05:47.870 に答える
2

IDisposableは、意図された目的にのみ使用する必要があると思います。つまり、保守性が重要な場合です。

于 2009-07-07T23:53:58.363 に答える
0

実際、特定のコードブロックの最後でアクションをトリガーしたいいくつかのプロジェクトでそれを使用しました。

Wes Deyer は、彼の LINQ to ASCII Art プログラムでそれを使用しました。彼はそれをアクション ディスポーザブルと呼びました (Wes は C# コンパイラ チームで働いています - 私は彼の判断を信頼します :D):

http://blogs.msdn.com/wesdyer/archive/2007/02/23/linq-to-ascii-art.aspx

class ActionDisposable: IDisposable
{
    Action action;

    public ActionDisposable(Action action)
    {
        this.action = action;
    }

    #region IDisposable Members

    public void Dispose()
    {
        this.action();
    }

    #endregion
}

これで、関数からそれを返すことができ、次のようにすることができます:

using(ExtendedConsoleWriter.Indent())
{
     ExtendedConsoleWriter.Write("This is more indented");
}

ExtendedConsoleWriter.Write("This is less indented");
于 2009-07-07T23:58:50.117 に答える