2009-03-11 26 views
47

Tôi có thuộc tính chuỗi có yêu cầu độ dài tối đa vì dữ liệu được liên kết với cơ sở dữ liệu. Tôi nên ném ngoại lệ nào nếu người gọi cố gắng đặt chuỗi vượt quá độ dài này?Ngoại lệ gì để ném từ một công ty thiết lập tài sản?

Ví dụ, đây C# mã:

public string MyProperty 
{ 
    get 
    { 
     return _MyBackingField; 
    } 
    set 
    { 
     if (value.Length > 100) 
      throw new FooException("MyProperty has a maximum length of 100."); 

     _MyBackingField = value; 
    } 
} 

tôi coi ArgumentException, nhưng nó chỉ có vẻ không đúng. Về mặt kỹ thuật, nó là một chức năng - MyProperty_set(string value) - vì vậy một trường hợp cho ArgumentException có thể được thực hiện, nhưng nó không được gọi là chức năng cho mắt của người tiêu dùng - nó ở bên phải của một toán tử gán.

Câu hỏi này có lẽ cũng có thể được mở rộng để bao gồm tất cả các loại xác thực dữ liệu được thực hiện trong trình cài đặt thuộc tính, nhưng tôi đặc biệt quan tâm đến trường hợp trên.

Trả lời

44

Có một cái nhìn qua mscorlib.dll với Reflector, trong một tình huống tương tự như System.String.StringBuilder.Capacity Microsoft sử dụng ArgumentOutOfRangeException() tương tự như:

public int PropertyA 
{ 
    get 
    { 
     return //etc... 
    } 
    set 
    { 
     if (condition == true) 
     { 
      throw new ArgumentOutOfRangeException("value", "/* etc... */"); 
     } 
     // ... etc 
    } 
} 
+1

Btw, Mono ném một ArgumentException trong trường hợp này ... –

+13

"ArgumentOutOfRangeException - Trường hợp ngoại lệ được ném khi giá trị của một cuộc tranh cãi nằm ngoài phạm vi cho phép của các giá trị theo quy định của phương thức được gọi " .... imo, Mono nên sửa mã của chúng. –

-1

Bạn có thể sử dụng InvalidOperationException. Đó là một sự thỏa hiệp. Tôi sẽ không bận tâm bằng cách sử dụng một ArgumentException hoặc.

16

Đối với tôi ArgumentException (hoặc một đứa trẻ) có ý nghĩa hơn, bởi vì đối số (giá trị) mà bạn cung cấp không hợp lệ, và đây là những gì mà ArgumentException đã được tạo ra.

10

Tôi sẽ không ném ngoại lệ nào cả. Thay vào đó tôi sẽ cho phép một chuỗi có độ dài bất kỳ và sau đó có một phương thức "Xác thực" riêng biệt trên lớp được gọi trước khi lưu. Có một số kịch bản đặc biệt nếu bạn sử dụng databinding nơi ném ngoại lệ từ setters bất động sản có thể giúp bạn trong một mớ hỗn độn.

Sự cố khi ném ngoại lệ từ người định vị thuộc tính là người lập trình quên bắt chúng. Nó phụ thuộc vào mức độ sạch sẽ mà bạn mong đợi dữ liệu bạn đang nhận được. Trong trường hợp này, tôi sẽ mong đợi độ dài chuỗi dài để được phổ biến không đặc biệt và như vậy bằng cách sử dụng một ngoại lệ sẽ là "kiểm soát dòng chảy với trường hợp ngoại lệ".

Để trích dẫn từ của Microsoft Design Guidelines for Developing Class Libraries:

Không sử dụng ngoại lệ đối với dòng chảy bình thường tầm kiểm soát, nếu có thể. Ngoại trừ lỗi hệ thống và hoạt động với điều kiện chủng tộc tiềm năng, khung nhà thiết kế phải thiết kế API để người dùng có thể viết mã không ném ngoại lệ. Ví dụ: bạn có thể cung cấp cách kiểm tra điều kiện tiên quyết trước khi gọi thành viên để người dùng có thể viết mã không ném ngoại lệ.

+4

Trong khi cá nhân tôi không đồng ý chút nào (Xác thực là công việc của người đặt cược sau khi tất cả - nếu không thì không có điểm nào trong việc có bất kỳ điều gì khác ngoài trường đơn giản = giá trị; trường trả về; getters/setters - Tôi thích bạn nâng cao điểm –

+1

Việc ném ngoại lệ vào các bộ định vị thuộc tính là OK để làm, tôi sẽ không ném ngoại lệ vào getters tài sản mặc dù –

+0

Việc trì hoãn việc ném một ngoại lệ sẽ không cho phép bạn bắt được kẻ xâm phạm. nếu một lập trình viên quên bắt một ngoại lệ thì nó sẽ nhảy trên mặt anh ta thay vì sủi bọt lên một cách vô tình – Trap

6

Hãy nhớ rằng có bao nhiêu vấn đề trong khoa học máy tính được giải quyết bằng cách thêm một mức độ gián tiếp bổ sung?

Một cách tiếp cận sẽ là tạo một kiểu mới, FixedLengthString, nói. Nó sẽ là trường hợp của rằng loại xác thực độ dài của chuỗi mà chúng được khởi tạo - với toán tử chuyển đổi thực hiện chuyển đổi loại từ một chuỗi đơn giản.Nếu setter thuộc tính của bạn lấy một kiểu như là đối số của nó thì mọi vi phạm sẽ trở thành ngoại lệ chuyển đổi loại thay vì một ngoại lệ đối số/thuộc tính.

Trong thực tế, tôi hiếm khi làm điều này. Nó có mùi hơi lấy OO quá xa - nhưng trong một số trường hợp nó có thể là một kỹ thuật hữu ích, vì vậy tôi đề cập đến nó ở đây để hoàn thành.

+2

Làm thế nào bạn sẽ đối phó với đi qua một FixedLengthString thiết lập tại tối đa 100 ký tự cho một tài sản yêu cầu một FixedLengthString đặt tối đa 50 ký tự? –

-2

Cố gắng sử dụng các ngoại lệ hiện có nếu có thể. Trong trường hợp này, sử dụng InvalidOperationException vì giá trị gửi đến sẽ đưa đối tượng vào trạng thái không nhất quán. Ngoại lệ tùy chỉnh có thể được tạo khi xử lý cụ thể với ngoại lệ tùy chỉnh là cần thiết. Trong trường hợp này, bạn chỉ ném một ngoại lệ với một số văn bản, vì vậy hãy sử dụng InvalidOperationException.

Khi ném InvalidOperationException hiển thị giá trị đã được chuyển đến bộ đặt này.

+0

Tất nhiên bạn có thể có những điều tốt nhất của cả hai thế giới và tạo ra loại ngoại lệ của riêng bạn xuất phát từ, ví dụ, InvalidOperationException. Tất nhiên bạn vẫn phải trả thêm một chút về mã và mã phức tạp. Đó là một chi phí nhỏ nhưng sau khi cân nó bạn vẫn có thể xem xét nó không có giá trị nó – philsquared

+2

InvalidOperationException không nên được nêu ra trong trường hợp này. Điều gì là sai là giá trị, không phải là hoạt động của thiết lập giá trị. – Trap

5
public IPAddress Address 
{ 
    get 
    { 
     return address; 
    } 
    set 
    { 
     if(value == null) 
     { 
      throw new ArgumentNullException("value"); 
     } 
     address = value; 
    } 
} 

qua MSDN

+0

Điểm tốt, mặc dù điều này là dành riêng cho trường hợp rỗng. Tuy nhiên, nó hỗ trợ việc sử dụng cho chuỗi 'ArgumentException', vì vậy +1 cho tham chiếu. –

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