8

プライベート変数を破棄する IDisposable インターフェイスを実装するクラスがあります_MailMessage。同じクラスに、プライベート IDisposable 変数を使用する非同期メソッドがあります。つまり、async public Task<bool> Send私の質問は次のとおりです。通常の IDisposable 実装は、非同期メソッドの完了後にプライベート変数を破棄しますか? これが私が話しているクラスの例です:

public class Email : IEmail
{
    private readonly IEmailData _EmailData;
    private MailMessage _MailMessage = new MailMessage();

    public Email(IEmailData emailData)
    {
        if (emailData == null)
        {
            throw new ArgumentNullException("emailData");
        }
        if (String.IsNullOrEmpty(emailData.To))
        {
            throw new ArgumentNullException("emailData.To");
        }
        if (String.IsNullOrEmpty(emailData.From))
        {
            throw new ArgumentNullException("emailData.From");
        }
        if (String.IsNullOrEmpty(emailData.FromName))
        {
            throw new ArgumentNullException("emailData.FromName");
        }
        if (String.IsNullOrEmpty(emailData.Subject))
        {
            throw new ArgumentNullException("emailData.Subject");
        }
        if (String.IsNullOrEmpty(emailData.Body))
        {
            throw new ArgumentNullException("emailData.Body");
        }

        _EmailData = emailData;
    }


    async public Task<bool> Send()
    {
        return await Task.Run<bool>(() =>
        {
            using (SmtpClient smtp = new SmtpClient())
            {
                smtp.Send(_MailMessage);
            }
            return true;
        });
    }

    #region "IDisposable implementation"
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }


    ~Email()
    {
        Dispose(false);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (_MailMessage != null)
                _MailMessage.Dispose();
        }
    }
    #endregion

}

デストラクタを使用しないことを提案する回答の 1 つに従って、IDisposable の実装を変更しました。

#region "IDisposable implementation"
public void Dispose()
{
    Dispose(true);
    GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
    if (disposing)
    {
        if (_MailMessage != null)
            _MailMessage.Dispose();
    }
}
#endregion
4

2 に答える 2

12

あなたはそれをかなり根本的に間違っています。デストラクタが必要だと思う場合は、99.9% の確率で間違っていることを覚えておくとよいでしょう。デストラクタは、解放する必要があるアンマネージ型のプライベート変数がある場合にのみ必要です。あなたはそうしない。間違ったことをしているとわかる方法は、破棄する引数が false の場合、実際には何もしていないことがわかったときです。つまり、デストラクタは実際には何もしません。したがって、それは必要ありません。そうすれば、使い捨てパターンも必要ありません。

さらに間違いがあります。IDisposable インターフェイスを継承して、独自の Dispose() メソッドを実装する必要があります。あなたが忘れてしまった。

Dispose() メソッドは、Email クラスのインスタンスを作成するクライアント コードによって呼び出される必要があります。自分で呼び出すことはできません。クライアント コードがいつ Email オブジェクトの使用を停止するかわかりません。これがあなたの質問に対する簡単な答えです。 Send() メソッドで自分自身を処分することはできません。クライアント コードが実際にそれを呼び出すという保証はありません。それを正しく行うには、クライアント コードに任せる必要があります。

于 2013-09-17T13:41:53.270 に答える