我对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中添加格式错误的电子邮件地址,则会引发异常。现在我的应用程序只是在发生这种情况时崩溃和燃烧。
有人能告诉我在这种方法中处理该异常的适当方法吗?
答案 0 :(得分:18)
此 是处理异常的适当方法!
一般情况下,除非可以纠正问题,否则不应处理异常,并且只应在可以应用更正的地方处理。
例如,代码的调用者可能希望提示用户更正错误的电子邮件地址。但是你的代码无法知道正确的提示方式。您是从WinForms还是Web窗体调用的?对话框应该是什么样的?是否应该 一个对话框?这些东西只能由您的方法的调用者知道,而不是您的方法本身。
在来电者中:
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
块来清理应用程序。
答案 1 :(得分:6)
每种方法都应该只捕获它们实际可以处理的异常。我看不出你的SendMail
方法如何能够用无效的邮件地址做任何有意义的事情,因此它应该让异常传播给调用者。
答案 2 :(得分:4)
您不应该处理异常。您应该处理(清理)输入并确保根据MailAddress类的要求不会使电子邮件地址格式错误
这是一个非常基本的例子:
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
}
答案 3 :(得分:3)
最好的方法是确保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.
}
}
答案 4 :(得分:0)
这里有许多可能的解决方案,您选择的解决方案在很大程度上取决于您想要发生的事情。
你需要的是一个Try / Catch处理程序,它包含有问题的功能,以便捕获抛出的异常并处理它。
现在,问题是你可以将它全部包装在异常中,并完全停止电子邮件,或者你可以在每个TO ADDRESS基础上执行它,这样100个列表中的1个坏地址不会破坏系统。或者您可以将它放在别处(比如你在哪里调用函数)