2009-10-08 16 views
7

あなたはのようにブラシとペンを持っている場合:使い捨てオブジェクトを扱うにはどうすればいいですか?

Brush b = new SolidBrush(color); 
Pen p = new Pen(b); 

などのようにそれらを配置:

b.Dispose(); 
p.Dispose(); 

それがあった場合はどのようにそれを配置します:作成し

Pen p = CreatePenFromColor(color)あなたのためのブラシとペン?私はこの方法の中にブラシを置くことはできません、そうですか?

使い捨てオブジェクトでは使用しない方法ですか?

EDIT:どういう意味ですか、ブラッシュをどのように処分しますか?

+0

o.O私はブラシとペンがIDisposableを実装していることを知らなかった... –

+0

lol、それは確かにあります。 –

+0

しかし、このブラシは実際にどこで参照されていますか?あなたがペンの結果を返すだけの場合、なぜ(そしてどこで)それを作成していますか? – Groo

答えて

9

Brushインスタンスを破棄する作業はCreatePenFromColorメソッドの仕事です。一見しただけでは分かりませんが、Penクラスの実装を掘り下げれば、渡されたBrushインスタンスには保持されません。代わりに、それを使っていくつかの値を計算するだけです。したがって、BrushインスタンスがCreatePenFromColorの呼び出しを超えて存続する理由はなく、このメソッドはインスタンスを破棄する必要があります。

+0

ジャレッドに感謝、私はそれを知らなかった。 –

+0

これは必ずしも真実ではありません。 Penコンストラクタはブラシのハンドルを 'GdipCreatePen2'に渡します。私は 'GdipCreatePen2'が生き続けるためにブラシを必要としているのかどうか分かりません(関数はほとんど文書化されていません)。ブラシはイメージを持つ 'TextureBrush'であることを覚えておいてください。そして、あなたはブラシを処分できるようにペンがメモリ内にイメージの別のコピーを作ることを望んでいません。 – SLaks

+1

@Slaks、GdipCreatePen2 AFAIKはそれを生き続ける必要はありません。私は非常に限られたドキュメントを掘って、それを維持するのではなく、ペンをセットアップする必要があります。 – JaredPar

6

完了したら、それを処分する必要があります。例えば

、あなたはこのようにそれを呼び出すことができます。

using (Pen p = CreatePenFromColor(color)) 
{ 
    // do something 
} 

方法は、IDisposableのオブジェクトを返す場合、それを処分するためにあなたの義務です。

[編集]私はペン(ブラシb)コンストラクタを使用しています。

a。この場合、Penはコンストラクタの後にBrushインスタンスを必要としないため、メソッドは次のようになります。

public Pen CreatePenFromColor(Color c) 
{ 
    using (Brush b = new SolidBrush(c)) 
    { return new Pen(b); } 
} 

b。単にPen(Color color)を使用しないのはなぜですか?

public Pen CreatePenFromColor(Color c) 
{ 
    return new Pen(c); 
} 

c。 (コメントに関して)もしペンが内部的にブラシへの参照を保持するならば、ペンを使い終える前にそれを処分することはできません。

public class PenHelper : IDisposable 
{ 
    private readonly Brush _brush; 
    public PenHelper(Color color) 
    { 
     _brush = new SolidBrush(color); 
    } 

    public Pen CreatePen() 
    { 
     return new Pen(_brush); 
    } 

    public void Dispose() 
    { 
     _brush.Dispose(); 
    } 
} 

をし、このようにそれを使用します:

using (PenHelper penHelper = new PenHelper(Color.Black)) 
{ 
    using (Pen pen = penHelper.CreatePen()) 
    { 
      // do stuff 
    } 
} 

免責事項:IDisposableをは、ガイドラインに従って実装されていませんが、その場合、私は私のために仕事をするだろうクラスのために行くだろうむしろデモンストレーションのためだけです。また、サンプル全体は、必要なときに参照をカプセル化する方法を示すためにのみ使用されます。もちろんペン(色)に行ってください。

+0

+1「ペンを作成するためにブラシを作成するのはなぜですか? –

+0

ありがとうございます。あなたの例では、Penが返されるとすぐにブラシbが処分されます。 Penが内側のブラシbへの参照を持っていたら、それは例を投げますか?ただ疑問に思う。 –

+0

拡張例ありがとう。 –

0

メソッドがIDisposableインスタンスをハンドオフすると同時に、ライフタイム管理責任をハンドオーバーしています。

使用後にオブジェクトを処分するのは、呼び出し元の責任です。そのオブジェクトに他のIDisposableオブジェクトが含まれている場合、コンベンションでは、コンテナ内にその子を正しく処分する必要があります。そうでなければ、コンテナ内のバグを意味します。

具体的な例では、ペンを配置するときに内部Brushインスタンスを処分することを期待する必要があります。

+0

色も使い捨てですか? –

+1

いいえ、Colorは構造体です。 – Groo

+1

@ Joan Venge: 'Typo' - あなたのコメントと同時に修正しました... –

2

問題には一般的な解決策はありません。

具体的な例では、PenにはColorを直接受け取るコンストラクタがあるため、問題はありません。

いくつかのクラスは、コンストラクタパラメータ自体(特にストリーム関連のクラス)を破棄します。リフレクターの各クラスをチェックしてください。

返すクラスがComponentから継承する場合は、Disposedイベントにハンドラを追加できます。

返すクラスが封印されていない場合は、継承したバージョンを作成して、作成したオブジェクトも破棄することができます。

最後に、本当にしたい場合、返すオブジェクトを含むラッパークラスを作成し、コンストラクターパラメーターを破棄することができます。しかし、それは非常に混乱し、私はそれをお勧めしません。

+0

ペンは色を直接取ることができませんでした。面白いのは、ブラシとペンを別々に作成してから、ペンをペイントするだけのコードがたくさんあるからです。 –

+0

あなたはこの答えを受け入れるべきです。 – SLaks

+0

はい、あります。そこにクリーンな一般的な解決策はありません。 – SLaks

1

グラフィックス関連のクラスの多くで私のオタクの1つは、そのような問題を処理するための一貫したパターンがないということです。本当に必要なのは、部分参照カウントを実装する手段です。 COMスタイルでは、参照を渡す際に参照カウントを常にバンプする必要がありますが、IDisposableグラフィックスオブジェクトでは、同じ基本リソースを共有する別のインスタンスを要求することができます。リソース自体は、参照カウンタを持つ共有オブジェクトにカプセル化されます。別の参照インスタンスを作成すると、カウンタがインクリメントされます。参照しているインスタンスでDisposeを呼び出すと、それをデクリメントします。これにより、参照カウントのオーバーヘッドの95%が回避され、利益の99%は保持されます。

関連する問題