2012-09-27 22 views
16

Vì vậy, chỉ vì tò mò tôi muốn xem điều gì đặc biệt về lớp ngoại lệ cho phép nó được sử dụng với từ khóa Throw trong khi một lớp tiêu chuẩn thì không.Tại sao một loại được ném hoặc bị bắt nguồn từ System.Exception

Tất cả tôi thấy là lớp ngoại lệ thực hiện như sau

public class Exception : System.Object, System.Runtime.Serialization.ISerializable, System.Runtime.InteropServices._Exception 
{ 
} 

Vì vậy, tôi cố gắng thực hiện những giao diện tương tự và cố gắng ném ngoại lệ tùy chỉnh của riêng tôi mà không xuất phát từ System.Exception vô ích. Tôi chỉ đơn giản là thông báo rằng

Kiểu bắt hoặc bị ném phải được bắt nguồn từ System.Exception

Vậy là có bất kỳ lý do cụ thể cho việc này? Tôi cho rằng có ít lựa chọn trong ngôn ngữ được quản lý dường như tùy ý.

+0

Tôi nghĩ rằng để tìm hiểu cách thức hoạt động, sẽ có ý nghĩa hơn khi xem xét việc triển khai 'ném' thay vì lớp' Ngoại lệ '. – Guillaume

+0

Khá công bằng nhưng thành thật mà nói, tôi sẽ không có một đầu mối nào để bắt đầu làm điều đó ... –

Trả lời

18

Tôi nghĩ tiền đề của bạn bị nhầm lẫn. Có thể một đối tượng được ném không được bắt nguồn từ System.Exception. Bạn không thể ném nó vào C# hoặc kiểm tra đối tượng trong một mệnh đề catch. Từ phần 8,10 của C# spec (v4.0):

Một số ngôn ngữ lập trình có thể hỗ trợ trường hợp ngoại lệ mà không phải là biểu diễn như một đối tượng có nguồn gốc từ System.Exception, mặc dù trường hợp ngoại lệ như vậy không bao giờ có thể được tạo ra bởi mã C# . Một mệnh đề chung bắt buộc có thể được sử dụng để bắt các ngoại lệ như vậy. Do đó, một mệnh đề chung của câu lệnh là khác biệt về mặt ngữ nghĩa với mệnh đề chỉ định loại System.Exception, trong trường hợp trước đây cũng có thể bắt ngoại lệ từ các ngôn ngữ khác.

Một ví dụ về đánh bắt chung:

try 
{ 
} 
catch (Exception) { } // 'specific' catch 
catch { } // 'general' catch 

Đặc biệt, điều này rất quan trọng khi gọi unmanaged code.

Một số loại dường như luôn được điều trị đặc biệt bằng mọi ngôn ngữ. Chủ yếu là vì chúng rất cơ bản với hệ thống. System.Exception, System.ValueType, System.Delegate là tất cả các loại đặc biệt trong C# được ràng buộc chặt chẽ với từ khóa ngôn ngữ và CLR, vì vậy không có gì ngạc nhiên khi bạn không thể triển khai các lớp đảm nhận vai trò của chúng.

+1

Wow, tôi không biết điều đó, cảm ơn bạn rất nhiều vì đã mở rộng hiểu biết của tôi ... –

+0

+1 Tôi đã đọc khá nhiều thông số C#, nhưng tôi chưa bao giờ thấy (hoặc ít nhất là chưa bao giờ nắm bắt được ý nghĩa của) đoạn đó. Upvote của tôi đặt bạn đến đại diện năm 1999, tôi sẽ xem nếu tôi có thể tìm thấy cái gì khác để bỏ phiếu cho bạn hơn 2000. – phoog

4

Ngôn ngữ sử dụng System.Exception làm cơ sở cho tất cả các ngoại lệ. Về cơ bản, điều này có nghĩa là bất kỳ ngoại lệ có thể ném hoặc bắt được nào đều không nên lỗi nếu bạn làm (Exception)myExc. Điều này có thể do định nghĩa của lớp System.Exception được sử dụng để tất cả ngoại lệ tuân thủ cùng một giao diện. Do giao diện nhất quán, các ngoại lệ xuất hiện với một dấu vết ngăn xếp và một thông báo có ý nghĩa (ví dụ), đó là vô giá đối với việc ghi nhật ký.

9

Design Guidelines for Exceptions

Exceptions là những cơ chế tiêu chuẩn để báo lỗi. Các ứng dụng và thư viện không được sử dụng mã trả lại để giao tiếp các lỗi . Việc sử dụng các ngoại lệ thêm vào một thiết kế khuôn khổ phù hợp và cho phép báo cáo lỗi từ các thành viên, chẳng hạn như nhà thầu, mà không thể có một kiểu trả về

throw (C# Reference)

Trường hợp ngoại lệ ném là một đối tượng mà lớp có nguồn gốc từ System.Exception, như được hiển thị trong ví dụ sau.

class MyException : System.Exception {} 
// ... 
throw new MyException(); 

Exceptions Overview

Trong .NET Framework, một ngoại lệ là một đối tượng được thừa kế từ các ngoại lệ Lớp

Vì vậy, ngoại trừ của bạn phải xuất phát từ System.Exception, nhưng tùy thuộc vào bạn, cách bạn tổ chức nó bên trong.

4

Đó là sự lựa chọn tùy ý của các nhà thiết kế của CLS. Có lẽ họ đã chọn lựa này vì những lý do nhất quán. C# theo sau CLS; yêu cầu được thực thi bởi trình biên dịch vì lý do này, không phải vì bất kỳ lý do kỹ thuật nào liên quan đến việc thực hiện loại Ngoại lệ.

CLI thực sự có thể ném bất kỳ đối tượng nào. Xem http://jilc.sourceforge.net/ecma_p3_cil.shtml#_Toc524462405.

3

Một lý do tại sao mọi ngoại lệ cần phải có một lớp cơ sở chung là vì vậy bạn có thể nắm bắt mọi loại ngoại lệ trong một khối catch duy nhất.

Nếu tôi có điều này:

try 
{ 
    ... 
} 
catch(Exception ex) 
{ 
    // Handle somehow 
} 

Đó sẽ bắt ALL trường hợp ngoại lệ, và sẽ cho phép tôi để hiển thị nó là gì (bằng cách sử dụng ex.Message).

Nếu bạn có thể ném bất cứ điều gì, thì bạn có thể bắt được mọi thứ và vẫn cho phép bạn truy cập đối tượng được ném như thế nào?

Bạn có thể có điều này, mà sẽ bắt hoàn toàn tất cả mọi thứ:

try 
{ 
    ... 
} 
catch 
{ 
    // Handle somehow 
} 

Nhưng bạn đã 'mất' điều mà bị ném.

+0

Vậy còn về bắt (đối tượng o) thì sao? Điều này có thể sẽ không đủ khi tương tác với C++, nhưng đây không phải là lý do để tránh ném cái gì khác. –

Các vấn đề liên quan