使い捨てオブジェクトが .Net でどのように実装されているかについての意見はありますか? また、IDisposable クラスの実装の反復性をどのように解決しますか?
IDisposable 型は、本来あるべき一流の市民ではないと感じています。あまりにも多くのことが開発者のなすがままになっています。
具体的には、使い捨てのものを正しく実装し、適切に廃棄することを確実にするために、言語とツールのサポートが改善されるべきではなかったのではないかと思います。
たとえば C# では、使い捨てセマンティクスを実装する必要があるクラスを次のように宣言できたらどうなるでしょうか。
public class disposable MyDisposableThing
{
~MyDisposableThing()
{
// Dispose managed resources
}
}
この場合、コンパイラは IDisposable インターフェイスの実装を簡単に生成できます。デストラクタ ~MyDisposableThing は、マネージド リソースを解放する実際の Dispose メソッドに変換できます。
中間の C# コードは次のようになります。
public class MyDisposableThing : IDisposable
{
private void MyDisposableThingDestructor()
{
// Dispose my managed resources
}
~MyDisposableThing()
{
DisposeMe(false);
}
public void Dispose()
{
DisposeMe(true);
GC.SuppressFinalize(this);
}
private bool _disposed;
private void DisposeMe(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
// Call the userdefined "destructor"
MyDisposableThingDestructor();
}
}
_disposed = true;
}
}
これにより、コードがよりクリーンになり、ボイラープレートの破棄コードが少なくなり、マネージド リソースを破棄する一貫した方法が得られます。IDisposable を手動で実装することは、エッジ ケースとアンマネージ リソースに対して引き続きサポートされます。
インスタンスが適切に破棄されるようにすることは、別の課題です。次のコードを検討してください。
private string ReadFile(string filename)
{
var reader = new StreamReader();
return reader.ReadToEnd(filename);
}
リーダー変数がメソッドのスコープを超えて存続することはありませんが、GC が破棄するまで待機する必要があります。この場合、コンパイラは、StreamReader オブジェクトが明示的に破棄されていないというエラーを発生させる可能性があります。このエラーは、開発者に using ステートメントでラップするように促します。
private string ReadFile(string filename)
{
using (var reader = new StreamReader())
{
return reader.ReadToEnd(filename);
}
}