2012-06-22 28 views
7

Tôi có một lớp chứa một tập hợp các mục. Để thuận tiện tôi đã cung cấp GetCurrentItem đó được thực hiện bởiTạo thuộc tính có thể ném IndexOutOfRangeException

public Type GetCurrentItem 
{ 
    get { return this.items[this.items.Count - 1]; } 
} 

mà sẽ ném một ngoại lệ nếu không có các mục trong danh sách.

Tôi có nên để ngoại lệ bị ném hay tôi nên trả lại null? Nếu đây là một API tôi trao cho bạn, bạn sẽ mong đợi điều gì? Ngoại lệ hoặc null? Có cách nào tốt hơn để xử lý việc này không?

+2

API chính xác: 'Enumerable.Single' hoặc' Enumerable.SingleOrDefault' là gì? (câu trả lời: nó phụ thuộc) –

Trả lời

9

Khi nào chính xác hơn? Như bình luận của Kirk cho thấy: nó phụ thuộc. Đôi khi, null có ý nghĩa hợp lý và đôi khi ngoại lệ phù hợp hơn nếu không có mặc định là hợp lý. Một điều tôi cố gắng làm là nghĩ "đang gọi GetCurrentItem một thất bại hợp lý hay một điều an toàn?"

Nếu không gọi được GetCurrentItem khi không có, thì việc ném ngoại lệ là khóa học chính xác. Ví dụ: nếu bộ sưu tập của bạn có thuộc tính HasCurrent hoặc IsEmpty nơi người nào đó có thể kiểm tra kết quả trước khi gọi GetCurrentItem thì họ nên "biết rõ hơn". Nhưng nếu các mục hiện tại là null là một cách hợp lý chính xác của việc sử dụng lớp học của bạn, sau đó bằng mọi cách thiết kế nó theo cách đó. Dù bằng cách nào, tôi sẽ ghi lại hành vi trong các nhận xét mã để cho người dùng biết về hành vi mong đợi.

Tôi sẽ nói điều này mặc dù việc hiển thị ngoại lệ ArgumentOutOfRange có thể là chi tiết triển khai chảy máu. Đó là, nếu người dùng của lớp này không có ý tưởng rằng cấu trúc bên trong là một mảng hoặc List<T>, thì không chảy ra ngoại lệ đó, nhưng hãy nắm bắt nó, bọc nó và ném một cái có ý nghĩa hơn (tùy chỉnh, hoặc một cái gì đó như InvalidOperationException).

Kể từ khi họ không thực sự trực tiếp đi qua trong một cuộc tranh cãi, họ nhận được một ngoại lệ ArgumentOutOfRange có thể gây nhầm lẫn :-)

+0

Một lựa chọn ngoại lệ tốt là 'InvalidOperationException', theo ví dụ được đặt bởi' Stack .Peek() '. –

+0

@MichaelLiu: Vâng, đồng ý. Tôi đã thêm rằng trong chỉnh sửa của tôi cũng giống như bạn đã nhận xét :-) –

3

Để lỗi phát sinh. Đây chỉ là cách các bộ sưu tập khác hoạt động. Nó sẽ được lên đến các ứng dụng người dùng để xử lý các trường hợp ngoại lệ tiềm năng (đặc biệt là khi làm việc với các bộ sưu tập). Có thể có phương thức bool HasSelection() mà người dùng có thể gọi trước khi tiếp tục.

3

Trường hợp ngoại lệ nên được sử dụng cho các trường hợp ngoại lệ. Nếu CurrentItem có thể là null, bạn không nên ném một ngoại lệ. Tôi không thấy lý do tại sao không có một CurrentItem là đặc biệt.

1

Câu hỏi đặt ra là liệu sau đó bạn mong đợi GetCurrentItem để trả về một giá trị an toàn. Nếu Type là nullable, thì GetCurrentItem có thể trả về null khi không có mục hiện tại nào. Nếu bạn luôn mong đợi danh sách không trống và để luôn luôn có một cái gì đó được chọn theo mặc định, sau đó ném một ngoại lệ có ý nghĩa.

Bạn thường không nên ném ngoại lệ trừ khi trường hợp của bạn thực sự là ngoại lệ và không phải là trường hợp sử dụng thông thường. Tuy nhiên, điều này có thể khá chủ quan.

0

Nếu điều này GetCurrentItem có ý nghĩa đối với API của bạn, tôi sẽ ném "InvalidOperationException" khi không có mục nào. Bạn có thể muốn đặt tên theo cách khác nếu cho phép null là kết quả hợp lệ.

Hãy xem xét phương pháp LINQ Last hiện có đã cung cấp cùng một chức năng hay không.

1

Tôi cố gắng suy nghĩ về điều đó từ quan điểm của người dùng. Đi đến số Principal of Least Astonishment.

Nếu tôi đang sử dụng thư viện hoặc đối tượng và được gọi là GetCurrentItemIndexOutOfRangeException bị ném, tôi sẽ nghĩ, "Tôi không gọi bất kỳ thứ gì có chỉ mục, tôi muốn mục hiện tại". Do đó, đề xuất của tôi sẽ là trả về null, điều đó sẽ khiến tôi nghĩ, "Ồ, không có mục nào hiện tại."

Cách khác, nếu thuộc tính là người lập chỉ mục và tôi muốn nhận một mục ở một chỉ mục nhất định, tôi sẽ không ngạc nhiên bởi một số IndexOutOfRangeException.

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