2009-12-29 31 views
5

Tôi tương đối mới với C# và .NET và tôi đang cố gắng tìm hiểu cách xử lý tốt hơn các ngoại lệ trong mã của mình.Tôi nên xử lý ngoại lệ như thế nào trong hàm C# này?

Hãy hàm sau Tôi đã viết ví dụ:

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

Nếu bạn cố gắng thêm một địa chỉ email có bị thay đổi trong message.From hoặc Message.To, nó sẽ ném một ngoại lệ. Ngay bây giờ ứng dụng của tôi chỉ bị treo và ghi khi điều này xảy ra.

Ai đó có thể chỉ cho tôi cách thích hợp để xử lý ngoại lệ đó trong phương pháp này không?

Trả lời

18

Điều này cách thích hợp để xử lý ngoại lệ!

Nói chung, không nên xử lý ngoại lệ trừ khi vấn đề có thể được sửa chữa và chỉ được xử lý ở nơi có thể áp dụng hiệu chỉnh.

Ví dụ: người gọi mã của bạn có thể muốn nhắc người dùng sửa địa chỉ email xấu. Nhưng mã của bạn không thể biết đúng cách để nhắc. Bạn đang được gọi từ WinForms hoặc Web Forms? Hộp thoại sẽ trông như thế nào? Nên có ngay cả một hộp thoại không? Đây là những thứ chỉ có thể được người gọi của phương thức của bạn biết, chứ không phải bởi chính phương thức của bạn.


Trong người gọi:

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

Lưu ý rằng bất kỳ trường hợp ngoại lệ khác hơn MyMailAddressException sẽ tuyên truyền để mã mà biết làm thế nào để xử lý chúng.


mức phù hợp của "xử lý" trong phương pháp của bạn:

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

Người gọi sau đó có thể bắt MyMailAddressException và có tất cả các thông tin cần thiết để nói cho người dùng những gì để sửa chữa. Các trường hợp ngoại lệ khác cần được phổ biến.


Chỉnh sửa trước đó của tôi đã giải quyết câu hỏi của bạn về phương pháp. Tôi đã giả định rằng ứng dụng của bạn có xử lý ngoại lệ cấp cao thích hợp. Gabriel chỉ ra rằng nếu bạn có xử lý ngoại lệ cấp cao thích hợp thì ứng dụng của bạn sẽ không bị lỗi!

Tuy nhiên, sự cố không nhất thiết phải là điều xấu. Nếu một cái gì đó xảy ra mà mã của bạn không thể xử lý, sau đó crashing là điều phải làm. Cách khác là cố gắng tiếp tục chạy, hy vọng rằng ngoại lệ không được giải quyết này đã không làm hỏng chương trình của bạn theo cách mà nó bắt đầu tạo ra kết quả không chính xác.

Chi tiết cụ thể về vị trí đặt "trình xử lý cấp cao nhất" phụ thuộc vào chương trình của bạn. Nó khác nhau giữa các ứng dụng WinForms và ASP.NET, ví dụ. Tuy nhiên, khái niệm sẽ giống nhau: an toàn đăng nhập tất cả các thông tin có sẵn, sau đó cho phép ngoại lệ truyền, làm hỏng ứng dụng.

Tất nhiên, bạn nên sử dụng finally khối để xóa ứng dụng của mình, ngay cả khi có ngoại lệ.

+0

Không, tôi không bỏ qua nó. Bạn có thấy nơi tôi nói về việc nhắc người dùng sửa địa chỉ email không hợp lệ không? Đó là xử lý ngoại lệ. –

+0

Không, vì đây là phương thức tiện ích cấp dưới, ngoại lệ nhất định nên được xử lý ở đây. Để nó cho người gọi. –

+0

@Jon: Không, đoạn giữa của anh ấy tóm tắt hoàn toàn cách ngoại lệ được sử dụng: iff vấn đề có thể được giải quyết. –

0

Có một số giải pháp khả thi ở đây và bạn chọn phần lớn phụ thuộc vào những gì bạn muốn xảy ra.

Điều bạn cần là trình xử lý Thử/Bắt quấn quanh chức năng được đề cập để bắt ngoại lệ được ném và xử lý nó.

Bây giờ, bạn có thể bao gồm tất cả trong một ngoại lệ và dừng hoàn toàn email hoặc bạn có thể thực hiện trên cơ sở TỚI ĐỊA CHỈ để 1 địa chỉ xấu trong danh sách 100 không bị ngắt hệ thống. HOẶC bạn có thể đặt nó ở nơi khác (nói nơi bạn gọi hàm)

4

Bạn không nên xử lý ngoại lệ. Bạn nên xử lý (khử trùng) đầu vào và đảm bảo rằng các địa chỉ email không bị thay đổi theo yêu cầu của MailAddress Lớp

đây là một ví dụ rất cơ bản:

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

Điều này thực sự khó hơn rất nhiều. Một trong những cách tốt nhất để kiểm tra một địa chỉ email thích hợp là cố gắng tạo một MailAddress và bắt ngoại lệ. –

+0

Bạn đang nói rằng anh ta nên dừng lại để cho dữ liệu xấu được đưa vào phương pháp này? Đôi khi điều đó là không thể. Đôi khi dữ liệu được tạo ra bởi con người thông qua giao diện người dùng không nằm trong tầm kiểm soát của chúng tôi ... và sau đó chúng ta phải đối phó với các đối số không đúng định dạng hoặc không đầy đủ - ở đâu đó ... Và nếu có nhiều nơi gọi methoid này, phương pháp này là hàng phòng thủ cuối cùng, và cơ hội cuối cùng để đối phó với họ. –

+0

Xem tại đây: http://stackoverflow.com/questions/201323/what-is-the-best-regular-expression-for-validating-email-addresses –

3

Cách tiếp cận tốt nhất là đảm bảo rằng đầu vào là SendMessage() được định dạng chính xác theo cách sẽ không khiến cho ngoại lệ được ném ở vị trí đầu tiên. Làm một số xác nhận và kiểm tra lỗi.

Trong mọi trường hợp, mặc dù, nếu bạn định xử lý nó, bạn có thể sẽ không xử lý nó trong SendMessage. Thay vào đó, hãy đi một cấp lên:

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. 
    } 
} 
6

Mỗi phương pháp chỉ nên bắt ngoại lệ mà chúng thực sự có thể xử lý. Tôi không thể thấy phương thức SendMail của bạn có thể làm bất cứ điều gì có ý nghĩa với một địa chỉ thư không hợp lệ và do đó nó chỉ nên cho phép ngoại lệ tuyên truyền cho người gọi.