我该如何处理这个C​​#函数中的异常?

Gun*_*ade 5 .net c# exception-handling exception

我对C#和.NET比较陌生,我正在努力学习如何更好地处理代码中的异常.

以我编写的以下函数为例:

  public void SendEmail(string SenderEmail, string SenderDisplayName, IEnumerable<string> RecipientEmails, string Subject, string Message)
    {
        MailMessage message = new MailMessage();

        message.From = new MailAddress(SenderEmail, SenderDisplayName);
        foreach (var recipient in RecipientEmails)
        {
            message.To.Add(recipient);
        }
        message.Subject = Subject;
        message.Body = Message;

        SmtpClient smtpClient = new SmtpClient("192.168.168.182");
        smtpClient.Send(message);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您尝试在Message.From或Message.To中添加格式错误的电子邮件地址,则会引发异常.现在我的应用程序只是在发生这种情况时崩溃和燃烧.

有人能告诉我在这种方法中处理该异常的适当方法吗?

Joh*_*ers 18

处理异常的适当方法!

通常,除非可以纠正问题,否则不应处理异常,并且只应在可以应用更正的地方处理.

例如,代码的调用者可能希望提示用户更正错误的电子邮件地址.但是你的代码无法知道正确的提示方式.您是从WinForms还是Web窗体调用的?对话框应该是什么样的?如果有,即使一个对话框?这些东西只能由您的方法的调用者知道,而不是您的方法本身.


在来电者中:

try
{
    SendEmail(SenderEmail, SenderDisplayName, RecipientEmails, Subject, Message);
}
catch (MyMailAddressException ex)
{
    MessageBox.Show(ex.Message);
}
Run Code Online (Sandbox Code Playgroud)

请注意,除了以外的任何异常MyMailAddressException都会传播到知道如何处理它们的代码.


您的方法中适当的"处理"级别:

public enum MailAddressType
{
    Sender,
    Recipient
}

public class MyMailAddressException : Exception
{
    public MailAddressType AddressType { get; set; }
    public string EmailAddress { get; set; }

    public MyMailAddressException(
        string message,
        MailAddressType addressType,
        string emailAddress,
        Exception innerException) : base(message, innerException)
    {
        AddressType = addressType;
        EmailAddress = emailAddress;
    }
}

public void SendEmail(
    string senderEmail,
    string senderDisplayName,
    IEnumerable<string> recipientEmails,
    string subject,
    string message)
{
    using (
        var mailMessage = new MailMessage
                          {
                              Subject = subject, 
                              Body = message
                          })
    {
        try
        {
            mailMessage.From = new MailAddress(
                senderEmail, senderDisplayName);
        }
        catch (FormatException ex)
        {
            throw new MyMailAddressException(
                "Invalid from address", MailAddressType.Sender,
                senderEmail, ex);
        }

        foreach (var recipient in recipientEmails)
        {
            try
            {
                mailMessage.To.Add(recipient);
            }
            catch (FormatException ex)
            {
                throw new MyMailAddressException(
                    "Invalid to address", MailAddressType.Recipient,
                    recipient, ex);
            }
        }

        var smtpClient = new SmtpClient("192.168.168.182");
        smtpClient.Send(mailMessage);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,呼叫者可以捕获MyMailAddressException并获得告知用户要修复的所有必要信息.其他例外应该传播.


我之前的编辑已经解决了您关于该方法的问题.我一直在假设您的应用程序具有适当的顶级异常处理.Gabriel向我指出,如果你有适当的顶级异常处理,那么你的应用程序就不会崩溃!

然而,崩溃并不一定是件坏事.如果您的代码无法处理某些事情,那么崩溃是正确的做法.另一种方法是尝试继续运行,希望这种未处理的异常不会以一种开始产生错误结果的方式破坏您的程序.

准确放置"顶级处理程序"的具体细节取决于您的程序.例如,WinForms和ASP.NET应用程序之间存在差异.但是,概念将是相同的:安全地记录所有可用信息,然后允许异常传播,从而使应用程序崩溃.

当然finally,即使存在异常,您也应该使用块来清理应用程序.


Bri*_*sen 6

每种方法都应该只捕获它们实际可以处理的异常.我无法看到你的SendMail方法如何能够用无效的邮件地址做任何有意义的事情,因此它应该让异常传播给调用者.