可以在 C# 中的委托上传递 System.Net.Mail.MailMessage 对象吗?

Posted

技术标签:

【中文标题】可以在 C# 中的委托上传递 System.Net.Mail.MailMessage 对象吗?【英文标题】:Is it okay to pass a System.Net.Mail.MailMessage object around on a delegate in C#? 【发布时间】:2011-07-05 17:51:27 【问题描述】:

我制作了一个小型 SmtpSender 类,用于处理 Smtp MailMessage 对象的发送。当消息已发送或发送失败时,我会引发一个委托,该委托包含一个“响应”对象,该对象具有用户尝试发送的原始 MailMessage 以及成功/失败布尔值和错误字符串。然后,用户可以根据需要将 MailMessage 对象重新提交给发件人类以重试。

我想知道的是......如果我提出一个包含非托管资源对象的委托,我是否需要在当前范围内处置该对象?如果是这样,在当前范围内调用 Dispose 会杀死委托函数接收的对象吗?从长远来看,我担心内存泄漏。

任何建议或帮助将不胜感激。提前致谢!

戴夫

public delegate void SmtpSenderSentEventHandler(object sender, SmtpSendResponse theResponse);

public class SmtpSendResponse : IDisposable

    #region Private Members

    private MailMessage _theMessage;
    private bool _isSuccess;
    private string _errorMessage;

    #endregion

    #region Public Properties

    public MailMessage TheMessage
    
        get  return _theMessage; 
        set  _theMessage = value; 
    

    public bool IsSuccess
    
        get  return _isSuccess; 
        set  _isSuccess = value; 
    

    public string Error
    
        get  return _errorMessage; 
        set  _errorMessage = value; 
    

    #endregion

    #region Constructors

    public SmtpSendResponse(MailMessage theMessage, bool isSuccess)
        : this(theMessage, isSuccess, null)
     

    public SmtpSendResponse(MailMessage theMessage, bool isSuccess, string errorMessage)
    
        _theMessage = theMessage;
        _isSuccess = isSuccess;
        _errorMessage = errorMessage;
    

    #endregion

    #region IDisposable Members

    public void Dispose()
    
        if (_theMessage != null)
        
            _theMessage.Attachments.Dispose();
            _theMessage.Dispose();
        
    

    #endregion

【问题讨论】:

当你知道你已经完成了它时一定要处理它,该对象公开Dispose方法来按需为你销毁它自己。通常,如果一个对象包含一个一次性对象,那么他们负责管理它,您的班级会处理处置 - 所以这真的取决于您的班级何时完成。尽管我可以看到不以这种方式传递此类项目的论点,但有些人可能会问:根对象是由什么负责的?就好像您在处理程序中进行处理一样,下一个订阅者(如果有的话)呢?好问题。 仅供参考,澄清我所指的“具有非托管资源的对象”是 MailMessage 对象。 致失望先生。发送者类有一个 SmtpSenderSentEventHandler 类型的事件。这通过 SmtpSendResponse 对象向订阅者提出。然后,订阅者必须测试成功是否为真,如果是,则将其丢弃。如果成功为假,他们可能想尝试使用相同的 MailMessage 对象重新发送。 这段代码没有任何作用。没有它,客户端代码看起来几乎一样,减去它必须弄清楚为什么失败以及何时处理对象的问题。试试看。 它不应该做任何事情。它只是一个代表 Smtp 发送结果的持有者对象,它通过委托传递给订阅者进行询问。订阅者可能是表单或其他东西,他们只会向用户显示错误并为他们提供重试的能力。如果他们想重试,那么他们需要将 MailMessage 对象传递回发送者类。如果当时成功了,那么他们就会处理掉它。 【参考方案1】:

当你对一个对象调用 dispose 时,你说你已经完成了它,并且它应该进入一个可以被垃圾收集器清理的“损坏”状态。所以一旦它被处理掉,我就不会再使用它了。因此,仅在完成后才将其丢弃。

使用/触摸类的最后一个对象应该处理它。不要过早丢弃它。

【讨论】:

在这种情况下,什么时候还为时过早?问题是事件的订阅者本身并不知道还有谁订阅了该事件,实际上,这不关他们的事。如果我命令报童回到报刊亭,因为他已经送了我的报纸,那么我邻居的报纸呢?我认为这就是这个问题真正变得比最初假设的更值得思考的地方。 按照这个类比,如果你对报童说“回家”,它应该知道它是否需要交付更多的文件,如果没有,它会很高兴地遵守。在代码中,通常 MailMessage _theMessage 知道在不再引用它时处理垃圾收集。因此,处置所有委托,不要在共享(静态)对象上保留记录列表。

以上是关于可以在 C# 中的委托上传递 System.Net.Mail.MailMessage 对象吗?的主要内容,如果未能解决你的问题,请参考以下文章

C# 学习笔记 6.委托

c#中委托的作用是啥?

.net:C#的委托

C# 将委托作为参数传递

C#解惑1——委托&事件(转)

30天C#基础巩固------了解委托,string练习