c# - 我应该如何处理此 C# 函数中的异常?

标签 c# .net exception exception-handling

我是 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);
    }
}

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

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

最佳答案

处理异常的合适方法!

一般情况下,除非问题可以更正,否则不应处理异常,并且只应在可以应用更正的地方处理。

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


在调用者中:

try
{
    SendEmail(SenderEmail, SenderDisplayName, RecipientEmails, Subject, Message);
}
catch (MyMailAddressException ex)
{
    MessageBox.Show(ex.Message);
}

请注意,除 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);
    }
}

然后调用者可以捕获 MyMailAddressException 并获得所有必要的信息来告诉用户要修复什么。其他异常应该传播。


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

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

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

当然,您应该使用 finally block 来清理您的应用程序,即使存在异常也是如此。

关于c# - 我应该如何处理此 C# 函数中的异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1976163/

相关文章:

c# - 调试 HTTP/1.1 400 错误请求的可视化 Web 开发人员 Web 服务

c# - 异步使用 System.Diagnostics.Process,我应该如何确保在确定它已退出之前收到最后的输出?

为静态方法抛出 java.lang.NoClassDefFoundError 而不是为静态成员抛出

java - 使用 Exception 来防止使用不需要的参数实例化类是一个好习惯吗

c# - DataSet.WriteXml 到字符串

c# - 使用 ghostscript 将 Postscript 转换为文本文件

c# - 如何使用“Entity Framework Core”(又名EF7)实现“软删除”?

c# - 相当于库 (DLL) 的 'app.config'

exception - 上传 logstash 1.1.15 时出现问题 - 将整体 jar 作为 Cloud Foundry 应用程序。

c# - 在 switch/case 中使用 for 循环