2011-08-19 11 views
5

Considerate questo codiceL'analisi del codice si lamenta che non sto eliminando oggetti. Cosa c'è di sbagliato qui?

private MailMessage GetMailMessageFromMailItem(Data.SystemX.MailItem mailItem) 
     { 

      var msg = new MailMessage(); 

      foreach (var recipient in mailItem.MailRecipients) 
      { 
       var recipientX = Membership.GetUser(recipient.UserKey); 
       if (recipientX == null) 
       { 
        continue; 
       } 

       msg.To.Add(new MailAddress(recipientX.Email, recipientX.UserName)); 
      } 

      msg.From = new MailAddress(ConfigurationManager.AppSettings["EmailSender"], 
            ConfigurationManager.AppSettings["EmailSenderName"]); 

      msg.Subject = sender.UserName; 
      if (!string.IsNullOrEmpty(alias)) msg.Subject += "(" + alias + ")"; 
      msg.Subject += " " + mailItem.Subject; 
      msg.Body = mailItem.Body; 
      msg.Body += Environment.NewLine + Environment.NewLine + "To reply via Web click link below:" + Environment.NewLine; 
      msg.Body += ConfigurationManager.AppSettings["MailPagePath"] + "?AID=" + ContextManager.AccountId + "&RUN=" + sender.UserName; 

      if (mailItem.MailAttachments != null) 
      { 
       foreach (var attachment in mailItem.MailAttachments) 
       { 
        msg.Attachments.Add(new Attachment(new MemoryStream(attachment.Data), attachment.Name)); 
       } 
      } 

      return msg; 
     } 

Sto solo prendendo il mio tipo di database e la conversione in MailMessage. Viene inviato in un'altra funzione.

L'analisi del codice mi dice che non sto eliminando "msg" che è corretto. Ma se lo faccio qui - ottengo un'eccezione quando sto provando a inviarlo.

Inoltre, lamenta di non smaltire MemoryStream qui:

msg.Attachments.Add (nuovo allegato (nuovo MemoryStream (attachment.Data), attachment.Name));

Non ho idea di come disporlo correttamente. Ho provato cose diverse, ma è stato sempre eccezioni quando l'invio di mail dicendo "flusso si chiude"

risposta

2

In sostanza non si dovrebbe - lo smaltimento del messaggio di posta tardi disporrà di ogni allegato, che disporrà di ogni flusso. Inoltre, non riuscire a smaltire uno MemoryStream che non viene utilizzato in servizi remoti non causerà alcun danno.

Suggerisco di sopprimere l'avviso per questo metodo.

MODIFICA: Sospetto che sia possibile utilizzare [SuppressMessage] per sopprimere il messaggio.


Nota che c'è il rischio che qualche codice getterà codice a metà strada attraverso il metodo, così si finisce per non essere in grado di smaltire il messaggio, anche se si dispone di una dichiarazione using nel codice chiamante. Se sei davvero infastidito, potresti scrivere:

private MailMessage GetMailMessageFromMailItem(Data.SystemX.MailItem mailItem) 
{ 
    bool success = false; 
    var msg = new MailMessage(); 
    try 
    { 
     // Code to build up bits of the message 
     success = true; 
     return msg; 
    } 
    finally 
    { 
     if (!success) 
     { 
      msg.Dispose(); 
     } 
    } 
} 

Personalmente direi che questo è eccessivo.

+0

Come si sopprimono gli avvisi? – katit

+0

@katit: Pass - Non utilizzo l'analisi del codice. Sono sicuro che ci sono molte istruzioni online. –

+0

@Downvoter: cura di commentare? –

0

Riguardo a "not disposing" msg "", l'unico modo che posso pensare è invece di restituire MailMessage piuttosto che passare un riferimento a un MailMessage. Qualcosa di simile. Non sono sicuro se sia una buona idea.

private void GetMailMessageFromMailItem(ref MailMessage msg, Data.SystemX.MailItem mailItem) 
+0

Ho il sospetto che il flusso verrà archiviato nell'allegato e verrà letto solo in seguito. –

+0

@Jon Skeet, ora che ci penso, lo stream dovrebbe rimanere aperto. – Jethro

-1

Anche il creatore dell'oggetto monouso deve smaltirlo. Se non riesci a smaltire il messaggio qui, dovrebbe essere passato da un creatore da qualche altra parte. L'analisi del codice è giusta in questo caso e si può finire con perdite molto sfortunate e difficili da debugare se si ignorano questi messaggi.

+0

Il trasferimento di proprietà è un concetto molto utile, che purtroppo né C# né Code Analysis forniscono aiuto. –

+0

Pertanto deve essere evitato. Quindi è saggio assegnare al creatore la responsabilità di smaltire le sue risorse disponibili. –

+0

Il creatore non è sempre il proprietario logico. Ad esempio, nel modello di fabbrica, il creatore non è mai il proprietario, né può la fabbrica disporre la risorsa che crea. Invece, una risorsa non esposta deve essere restituita. –