クラスの新しいインスタンスを破棄するには、「使用」の使用を強制する必要があります。
public class MyClass : IDisposable
{
...
}
using(MyClass obj = new MyClass()) // Force to use "using"
{
}
クラスの新しいインスタンスを破棄するには、「使用」の使用を強制する必要があります。
public class MyClass : IDisposable
{
...
}
using(MyClass obj = new MyClass()) // Force to use "using"
{
}
オブジェクトが確実に廃棄されるようにする必要があるという事実は、設計上の欠陥を示しています。処分が礼儀正しくまたは効率的なことであれば問題ありませんが、意味的には必要ありません。
using
ステートメントを介してオブジェクトが破棄されることを強制する方法はありません。ただし、できることは、オブジェクトが破棄されたかどうかを示すフラグをオブジェクトに保持してから、そのフラグをチェックするファイナライザーを作成することです。ファイナライザーがオブジェクトが破棄されなかったことを検出した場合、ファイナライザーに、たとえばフェイルファストを介してプロセスを終了させることができます。つまり、オブジェクトの破棄を怠ったユーザーを厳しく罰するため、バグを修正するか、オブジェクトの使用を停止する必要があります。
それは私をいい、良い、または礼儀正しいとは思わないが、オブジェクトを処分しなかった場合のひどい、ひどい結果が何であるかを知っているのはあなただけだ。あなたの狂った規則に従わなかった人々に罰を適用することが、彼らが規則に従わなかった結果と一緒に暮らすよりも良いかどうかはあなたが決めることです。
それは醜いですが、あなたはこのようなことをすることができます:
public sealed class DisposableClass : IDisposable
{
private DisposableClass()
{
}
public void Dispose()
{
//Dispose...
}
public static void DoSomething(Action<DisposableClass> doSomething)
{
using (var disposable = new DisposableClass())
{
doSomething(disposable);
}
}
}
FXCopがそのルールを強制できるのだろうか?
using ステートメントは、コンパイラが次から変換する省略形です。
(using DisposableObject d = new DisposableObject()){}
の中へ:
DisposableObject d = new DisposableObject()
try
{
}
finally
{
if(d != null) d.Dispose();
}
そのため、オブジェクトの Dispose を呼び出す try/finally ブロックの記述を強制できるかどうかについて多かれ少なかれ質問しています。
いいえ、それはできません。強制的に破棄を呼び出すことさえできません。あなたができる最善のことは、ファイナライザーを追加することです。オブジェクトが破棄されるとファイナライザーが呼び出され、それはランタイム次第であることに注意してください。
いいえ、できません。ここでできることは、クラスのファイナライザーで dispose メソッドを呼び出すことです (実際に dispose メソッドを呼び出す場合は、その使用を抑制することができます)。そうすれば、コードで明示的に行われなければ起動します。
このリンクは、ファイナライザー/破棄パターンを実装する方法を示しています。
取得したリソースが適切に廃棄されるようにする手法であるRAIIを調べる必要があります。
つまり、Dispose
メソッドを(経由using
または直接)強制的に呼び出せない場合は、そのコンテンツを、デストラクタなど、呼び出される別のメソッド内に配置できます。
IDisposable
以下のように実装するのが一般的なパターンです。
// Implement IDisposable.
// Do not make this method virtual.
// A derived class should not be able to override this method.
public void Dispose()
{
Dispose(true);
// This object will be cleaned up by the Dispose method.
// Therefore, you should call GC.SupressFinalize to
// take this object off the finalization queue
// and prevent finalization code for this object
// from executing a second time.
GC.SuppressFinalize(this);
}
// Dispose(bool disposing) executes in two distinct scenarios.
// If disposing equals true, the method has been called directly
// or indirectly by a user's code. Managed and unmanaged resources
// can be disposed.
// If disposing equals false, the method has been called by the
// runtime from inside the finalizer and you should not reference
// other objects. Only unmanaged resources can be disposed.
private void Dispose(bool disposing)
{
// Check to see if Dispose has already been called.
if(!this.disposed)
{
// If disposing equals true, dispose all managed
// and unmanaged resources.
if(disposing)
{
// Dispose managed resources.
component.Dispose();
}
// Call the appropriate methods to clean up
// unmanaged resources here.
// If disposing is false,
// only the following code is executed.
// TODO: write code
}
disposed = true;
}
// Use C# destructor syntax for finalization code.
// This destructor will run only if the Dispose method
// does not get called.
// It gives your base class the opportunity to finalize.
// Do not provide destructors in types derived from this class.
~ClassName()
{
// Do not re-create Dispose clean-up code here.
// Calling Dispose(false) is optimal in terms of
// readability and maintainability.
Dispose(false);
}
ソース: http: //msdn.microsoft.com/en-us/library/system.gc.suppressfinalize.aspx
このクラスで強制的に使用する必要がある場合は、コードでこのクラスをサポートし、他のクラスでコーディングして、通常の使用のために MyClass を非表示にすることができます。
スコープ内のリソースの破棄を強制したい場合は可能ですが、IDisposable は実際には必要ありません。次のコードを使用します。
public class ResourceHandle
{
public delegate void ResourceProvider(Resource resource);
private string _parms;
public ResourceHandle(string parms)
{
_parms = parms;
}
public void UseResource(ResourceProvider useResource)
{
Resource resource = new Resource(_parms);
useResource(resource);
resource.Close();
}
}
public class Resource
{
private string _parms;
internal Resource(string parms)
{
// Initialize resource
}
internal void Close()
{
// Do cleaning
}
// Public methods of resource
}
リソースは次の方法でのみ使用できます。
public void foo()
{
ResourceHandle resourceHandle = new ResourceHandle("parms");
resourceHandle.UseResource(delegate(Resource resource)
{
// use resource
});
}
ご覧のとおり、ここでは IDisposable は実際には必要ありません。