Ý chính nếu câu hỏi có vẻ là "Làm thế nào để tôi trả lại hai mẩu thông tin không liên quan từ một phương thức trả về một int? Tôi không bao giờ muốn kiểm tra giá trị trả về của mình và null là xấu, đừng sử dụng chúng."
Hãy nhìn vào những gì bạn muốn vượt qua. Bạn đang vượt qua một int hoặc một lý do không int cho lý do tại sao bạn không thể đưa ra int. Câu hỏi khẳng định rằng sẽ chỉ có hai lý do, nhưng bất kỳ ai đã từng làm enum đều biết rằng bất kỳ danh sách nào cũng sẽ phát triển. Phạm vi để xác định các lý do khác chỉ có ý nghĩa.
Ban đầu, sau đó, có vẻ như đây có thể là một trường hợp tốt để ném ngoại lệ.
Khi bạn muốn nói với người gọi một cái gì đó đặc biệt không thuộc kiểu trả về, ngoại lệ thường là hệ thống phù hợp: ngoại lệ không chỉ dành cho trạng thái lỗi và cho phép bạn trả lại nhiều ngữ cảnh và lý do để giải thích lý do tại sao bạn chỉ có thể hôm nay
Và đây là hệ thống DUY NHẤT cho phép bạn trả về các số nguyên có giá trị được bảo đảm và đảm bảo rằng mọi toán tử int và phương thức lấy int có thể chấp nhận giá trị trả về của phương thức này mà không cần phải kiểm tra các giá trị không hợp lệ như null hoặc giá trị ma thuật.
Nhưng các trường hợp ngoại lệ thực sự chỉ là một giải pháp hợp lệ nếu như tên của nó ngụ ý, đây là một trường hợp đặc biệt , không phải là quá trình kinh doanh thông thường.
Và một thử / bắt và xử lý cũng giống như một bản kiểm tra null, đó là những gì đã bị phản đối ở nơi đầu tiên.
Và nếu người gọi không chứa thử / bắt, thì người gọi phải gọi, v.v.
Một vượt qua thứ hai ngây thơ là để nói "Đó là một phép đo. Đo khoảng cách tiêu cực là không thể." Vì vậy, đối với một số phép đo Y, bạn chỉ có thể có hằng số cho
- -1 = chưa biết,
- -2 = không thể đo lường,
- -3 = từ chối trả lời,
- -4 = được biết nhưng bí mật,
- -5 = thay đổi tùy theo pha mặt trăng, xem bảng 5a,
- -6 = bốn chiều, các phép đo được đưa ra trong tiêu đề,
- -7 = lỗi đọc hệ thống tệp,
- -8 = dành riêng cho sử dụng trong tương lai,
- -9 = hình vuông / khối nên Y giống với X,
- -10 = là màn hình theo dõi nên không sử dụng các phép đo X, Y: sử dụng X làm đường chéo màn hình,
- -11 = đã viết các số đo ở mặt sau của hóa đơn và nó đã được rửa thành bất hợp pháp nhưng tôi nghĩ rằng đó là 5 hoặc 17,
- -12 = ... bạn có ý tưởng.
Đây là cách nó được thực hiện trong rất nhiều hệ thống C cũ và ngay cả trong các hệ thống hiện đại, nơi có một ràng buộc thực sự đối với int, và bạn không thể bọc nó thành một cấu trúc hoặc một loại nào đó.
Nếu các phép đo có thể âm tính, thì bạn chỉ cần làm cho kiểu dữ liệu của mình lớn hơn (ví dụ int dài) và có các giá trị ma thuật cao hơn phạm vi của int và lý tưởng bắt đầu bằng một số giá trị sẽ hiển thị rõ ràng trong trình gỡ lỗi.
Có nhiều lý do tốt để có chúng như một biến riêng biệt, thay vì chỉ có số ma thuật. Ví dụ, gõ nghiêm ngặt, bảo trì và phù hợp với mong đợi.
Trong nỗ lực thứ ba của chúng tôi, sau đó, chúng tôi xem xét các trường hợp đó là quá trình kinh doanh bình thường để có các giá trị không phải là int. Ví dụ: nếu một tập hợp các giá trị này có thể chứa nhiều mục không nguyên. Điều này có nghĩa là một xử lý ngoại lệ có thể là cách tiếp cận sai.
Trong trường hợp đó, nó có vẻ là một trường hợp tốt cho một cấu trúc vượt qua int và cơ sở lý luận. Một lần nữa, lý do này có thể chỉ là một const như trên, nhưng thay vì giữ cả hai trong cùng một int, bạn lưu trữ chúng như các phần riêng biệt của một cấu trúc. Ban đầu, chúng ta có quy tắc là nếu lý do được đặt, int sẽ không được đặt. Nhưng chúng ta không còn bị ràng buộc với quy tắc này; chúng tôi cũng có thể cung cấp các số liệu hợp lệ cho các số hợp lệ.
Dù bằng cách nào, mỗi khi bạn gọi nó, bạn vẫn cần nồi hơi, để kiểm tra lý do để xem liệu int có hợp lệ hay không, sau đó rút ra và sử dụng phần int nếu lý do cho phép chúng tôi.
Đây là nơi bạn cần điều tra lý do của mình đằng sau "không sử dụng null".
Giống như các trường hợp ngoại lệ, null có nghĩa là để biểu thị một trạng thái đặc biệt.
Nếu một người gọi đang gọi phương thức này và bỏ qua hoàn toàn phần "cơ sở" của cấu trúc, mong đợi một số mà không có bất kỳ xử lý lỗi nào và nó nhận được số 0, thì nó sẽ xử lý số 0 dưới dạng số và sai. Nếu nó có được một con số ma thuật, nó sẽ coi đó là một con số và sai. Nhưng nếu nó bị vô hiệu, nó sẽ rơi xuống , vì nó cũng nên làm.
Vì vậy, mỗi khi bạn gọi phương thức này, bạn phải kiểm tra giá trị trả về của nó, tuy nhiên bạn xử lý các giá trị không hợp lệ, cho dù trong băng tần hay ngoài băng, thử / bắt, kiểm tra cấu trúc cho thành phần "hợp lý", kiểm tra int để biết số ma thuật hoặc kiểm tra int cho null ...
Cách khác, để xử lý phép nhân của một đầu ra có thể chứa một int không hợp lệ và một lý do hợp lý như "Con chó của tôi đã ăn phép đo này", là làm quá tải toán tử nhân cho cấu trúc đó.
... Và sau đó quá tải mọi nhà khai thác khác trong ứng dụng của bạn có thể được áp dụng cho dữ liệu này.
... Và sau đó quá tải tất cả các phương thức có thể mất ints.
... Và tất cả những quá tải sẽ cần phải vẫn chứa kiểm tra cho ints không hợp lệ, chỉ để bạn có thể đối xử với các kiểu trả về của một phương pháp này như thể nó là luôn luôn là một int có giá trị tại thời điểm khi bạn đang gọi nó.
Vì vậy, tiền đề ban đầu là sai theo nhiều cách khác nhau:
- Nếu bạn có các giá trị không hợp lệ, bạn không thể tránh việc kiểm tra các giá trị không hợp lệ đó tại bất kỳ điểm nào trong mã nơi bạn đang xử lý các giá trị.
- Nếu bạn trả lại bất cứ thứ gì ngoài int, bạn sẽ không trả về int, vì vậy bạn không thể coi nó như int. Quá tải toán tử cho phép bạn giả vờ , nhưng đó chỉ là giả vờ.
- Một int có số ma thuật (bao gồm NULL, NAN, Inf ...) không còn thực sự là int, đó là cấu trúc của một người nghèo.
- Tránh null sẽ không làm cho mã mạnh hơn, nó sẽ chỉ che giấu các vấn đề với ints hoặc chuyển chúng vào một cấu trúc xử lý ngoại lệ phức tạp.