Как я должен обработать исключения в этой функции C#?

Я относительно плохо знаком с 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);
    }
}

При попытке добавить адрес электронной почты, который уродлив в сообщении. От или сообщение. К, это выдаст исключение. Прямо сейчас мое приложение просто отказывает и горит, когда это происходит.

Кто-то может показать мне соответствующий способ обработать то исключение в этом методе?

5
задан Gunblade 29 December 2009 в 18:38
поделиться

5 ответов

Это - подходящий способ работы с исключениями!

В целом, исключение не должно быть обработано, если проблема не может быть исправлена, и оно должно быть обработано только в том месте, где может быть применено исправление.

Например, звонящий по вашему коду может попросить пользователя исправить плохой адрес электронной почты. Но ваш код не может знать правильного способа подсказки. Вам звонят из 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 и иметь всю необходимую информацию, чтобы сказать пользователю, что нужно исправить. Другие исключения должны распространяться.


Мои предыдущие правки рассмотрели ваш вопрос о методе. Я предполагал, что ваше приложение имеет соответствующую обработку исключений верхнего уровня. Габриэль указывает мне, что если бы у вас была подходящая обработка исключений верхнего уровня, то ваше приложение бы не зависало!

Однако, зависание не обязательно плохая вещь. Если произойдет что-то, с чем ваш код не сможет справиться, то падение - это правильный поступок. Альтернатива - попытаться продолжить работу, надеясь, что это необработанное исключение не повредит вашей программе так, что она начнет давать некорректные результаты.

Специфика того, куда именно поместить "обработчики верхнего уровня", зависит от вашей программы. Это отличается, например, между WinForms и ASP.NET приложениями. Однако, концепция будет та же самая: безопасно регистрировать всю доступную информацию, затем позволить исключению распространяться, что приведет к аварийному завершению работы приложения.

Конечно, вы должны использовать наконец-то блоки для очистки вашего приложения, даже при наличии исключений.

.
18
ответ дан 18 December 2019 в 05:40
поделиться

Каждый метод должен ловить только те исключения, с которыми он на самом деле может справиться. Я не вижу, как ваш метод SendMail может сделать что-либо значимое с недействительным почтовым адресом, и поэтому он должен просто позволить исключению распространиться на вызывающего абонента.

.
6
ответ дан 18 December 2019 в 05:40
поделиться

Вы не должны справляться с исключением. Вы должны обрабатывать (дезинфицировать) вводимые данные и убедиться, что почтовые адреса не повреждены в соответствии с требованиями класса MailAddress Class

- вот очень простой пример:

public bool IsValidEmailAddress(string EmailAddress){
    Regex regEmail = new Regex(@"^[a-zA-Z0-9][\w\.-]*[a-zA-Z0-9]@[a-zA-Z0-9][\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]$");

    if(regEmail.IsMatch(EmailAddress))
        return true;

    return false;
}

if (IsValidEmailAddress(SenderMail)){
    //do stuff to send the mail
}else{
    //return an error to the user interface
}
4
ответ дан 18 December 2019 в 05:40
поделиться

Здесь есть ряд возможных решений, и то, что вы выберете, во многом зависит от того, что вы хотите сделать.

Вам нужен обработчик Try/Catch, обернутый вокруг рассматриваемой функциональности, чтобы поймать брошенное исключение и разобраться с ним.

Дело в том, что вы можете обернуть все это в исключение и вообще остановить электронную почту, или вы можете сделать это на основе одного ADDRESS, чтобы 1 плохой адрес в списке из 100 не сломал бы систему. Или вы можете поместить его в другое место (скажем, куда вы вызываете функцию)

.
0
ответ дан 18 December 2019 в 05:40
поделиться

Лучший подход - убедиться, что вход в SendMessage() правильно отформатирован таким образом, что исключение не будет бросаться в первую очередь. В любом случае, если бы вы собирались работать с ним, то, скорее всего, не работали бы с ним в SendMessage. Вместо этого нужно подняться на один уровень вверх:

public void Submit() {
  try {
    SendMessage(emailForm.SenderAddress, emailForm.UserDisplayName,
      emailForm.RecipientEmails, emailForm.Subject, emailForm.MessageBody);
  } catch (MailException e) { // Substitute whichever exception is appropriate to catch here.
    // Tell user that submission failed for specified reasons.
  }
}
3
ответ дан 18 December 2019 в 05:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: