2010-12-15 57 views
17

Off đỉnh đầu của tôi, tôi có thể nghĩ đến 4 cách để kiểm tra cho các đối số null:Ưu điểm/nhược điểm của các phương pháp khác nhau để kiểm tra điều kiện tiên quyết?

Debug.Assert(context != null); 
Contract.Assert(context != null); 
Contract.Requires(context != null); 
if (context == null) throw new ArgumentNullException("context"); 

Tôi luôn sử dụng phương pháp cuối cùng, nhưng tôi chỉ thấy một đoạn mã được sử dụng Contract.Requires, mà tôi 'không quen thuộc với. Ưu điểm/nhược điểm của từng phương pháp là gì? Có cách nào khác không?


Trong VS2010 w/Resharper,

  • Contract.Assert cảnh báo tôi rằng biểu thức luôn là đúng (làm thế nào nó biết, tôi không hoàn toàn chắc chắn ... không thể HttpContext được null?),
  • Contract.Requires bị nhạt nhòa dần và nó nói với tôi trình biên dịch sẽ không gọi phương thức (tôi giả sử vì lý do thứ nhất, nó sẽ không bao giờ được null), và
  • nếu tôi thay đổi phương pháp cuối cùng để context != null tất cả mã follo cánh bị phai mờ và nó cho tôi biết mã là không thể truy cập heuristically.

Vì vậy, có vẻ như 3 phương pháp cuối cùng có một số loại thông minh được tích hợp trong trình kiểm tra tĩnh VS và Debug.Assert chỉ là câm.

+0

Câu hỏi không rõ ràng. Bạn có thực sự cố gắng sử dụng chúng cùng một lúc không? –

+0

@Matthew: Không chắc nó không rõ ràng ... không, tôi không cố gắng sử dụng chúng cùng một lúc. Tôi đã tạo ra một đoạn mã như thế chỉ để minh họa các cách khác nhau mà bạn có thể kiểm tra null. – mpen

+0

Đó là những gì tôi nghĩ từ phần còn lại của câu hỏi, nhưng trình bày cú pháp bạn sử dụng là kỳ quặc. –

Trả lời

12

Tôi đoán là có một hợp đồng được áp dụng cho giao diện IHttpHandler.ProcessRequest yêu cầu ngữ cảnh đó! = Null. Các hợp đồng giao diện được kế thừa bởi người triển khai của họ, vì vậy bạn không cần phải lặp lại Yêu cầu. Trên thực tế, bạn không được phép thêm các câu lệnh Yêu cầu bổ sung, vì bạn bị giới hạn các yêu cầu liên quan đến hợp đồng giao diện.

Tôi nghĩ rằng điều quan trọng là tạo sự khác biệt giữa việc xác định nghĩa vụ hợp đồng và chỉ cần thực hiện kiểm tra vô giá trị. Bạn có thể thực hiện kiểm tra rỗng và ném một ngoại lệ vào thời gian chạy, như một cách để thông báo cho nhà phát triển rằng họ đang sử dụng API của bạn một cách chính xác. Mặt khác, một biểu thức hợp đồng thực sự là một dạng siêu dữ liệu, có thể được giải thích bởi người viết lại hợp đồng (để giới thiệu các ngoại lệ thời gian chạy đã được thực hiện trước đó), mà còn bởi trình phân tích tĩnh, có thể sử dụng chúng để giải thích về tính chính xác tĩnh của ứng dụng của bạn.

Điều đó nói rằng, nếu bạn đang làm việc trong môi trường mà bạn đang tích cực sử dụng Hợp đồng mã và phân tích tĩnh, thì tốt nhất nên đặt các xác nhận trong biểu mẫu hợp đồng để tận dụng phân tích tĩnh. Ngay cả khi bạn không sử dụng phân tích tĩnh, bạn vẫn có thể để cửa mở cho các lợi ích sau này bằng cách sử dụng hợp đồng. Điều chính cần lưu ý là liệu bạn đã cấu hình các dự án của mình để thực hiện viết lại hay không, vì nếu không các hợp đồng sẽ không dẫn đến các ngoại lệ thời gian chạy như bạn mong đợi.


Để xây dựng trên những gì các bình luận đã nói, sự khác biệt giữa Khẳng định, Giả và Yêu cầu là:

    biểu
  • Một Contract.Assert được chuyển thành một sự khẳng định bởi Ổ ghi hợp đồng và phân tích tĩnh cố gắng chứng minh biểu thức dựa trên bằng chứng hiện tại của nó. Nếu nó không thể được chứng minh, bạn sẽ nhận được một cảnh báo phân tích tĩnh.
  • Một hợp đồng. Biểu thức được bỏ qua bởi người viết lại hợp đồng (theo như tôi biết), nhưng được giải thích bởi máy phân tích tĩnh dưới dạng một bằng chứng mới mà nó có thể tính đến trong phân tích tĩnh của nó. Hợp đồng.Giả sử được sử dụng để 'lấp đầy khoảng trống' trong phân tích tĩnh, ở nơi thiếu sự tinh tế để đưa ra các suy luận cần thiết hoặc khi liên kết với mã chưa được trang trí với Hợp đồng, để bạn có thể Giả sử, chẳng hạn, một hàm gọi cụ thể trả về kết quả không null.
  • Contract.Requires là điều kiện phải luôn đúng khi phương pháp của bạn được gọi. Chúng có thể là ràng buộc đối với các tham số cho phương thức (là điển hình nhất) và chúng cũng có thể là các ràng buộc trên các trạng thái hiển thị công khai của đối tượng (Ví dụ, bạn chỉ có thể cho phép phương thức được gọi nếu được khởi tạo là True). ràng buộc đẩy người dùng của lớp của bạn hoặc kiểm tra Khởi tạo khi sử dụng đối tượng (và có lẽ xử lý lỗi một cách thích hợp nếu không) hoặc tạo ra các ràng buộc của riêng mình và/hoặc các bất biến lớp để làm rõ rằng Khởi tạo đã thực sự xảy ra.
+0

Vậy ... chính xác thì khác biệt giữa 'Contract.Assert' và' Contract.Requires' là gì? – mpen

+2

@Ralph: 'Contract.Requires' chỉ ra những điều phải đúng khi phương thức được gọi,' Contract.Assert' nên đi vào giữa phương thức của bạn để kiểm tra trạng thái trung gian. Việc thêm 'Contract.Assert' vào đúng vị trí có thể giúp trình phân tích tĩnh chứng minh mã của bạn đúng nếu nó không thể tự quản lý nó. –

+3

Thực ra, trình kiểm tra tĩnh sẽ chỉ được hưởng lợi từ Contract.Assume. Phương thức này hoạt động giống như Contract.Assert khi chạy, nhưng yêu cầu trình kiểm tra tĩnh không thử và thống kê chứng minh điều này. – koenmetsu

2

Phương pháp đầu tiên phù hợp để kiểm tra điều kiện rỗng không bao giờ tồn tại. Đó là, sử dụng nó trong quá trình phát triển để đảm bảo nó không bất ngờ được thiết lập để null. Vì nó không thực hiện bất kỳ xử lý lỗi nào, điều này không thích hợp để xử lý các điều kiện rỗng trong sản phẩm được phát hành của bạn.

Tôi muốn nói rằng phiên bản thứ 2 và thứ 3 tương tự ở chỗ chúng không xử lý vấn đề theo bất kỳ cách nào.

Nói chung, nếu có khả năng biến đó thực sự có thể là rỗng trong sản phẩm cuối cùng, phiên bản cuối cùng là phiên bản để sử dụng. Bạn có thể thực hiện xử lý đặc biệt ở đó, hoặc chỉ cần đưa ra một ngoại lệ như bạn đã làm.

+1

Thực ra, các phương thức thứ 2 và thứ 3 sử dụng phân tích tĩnh để thử và chứng minh chúng đúng lúc biên dịch. –

+0

@Anon: Nhưng máy phân tích tĩnh sẽ không thể bắt tất cả ngoại lệ null tại thời gian biên dịch ... điều gì sẽ xảy ra nếu một phiếu bị trượt? Liệu nó có làm tăng ngoại lệ, tai nạn, không làm gì hay gì? – mpen

+1

@Ralph: Nếu máy phân tích tĩnh không thể chứng minh điều gì đó (nó không thể chỉ ra rằng hợp đồng sẽ thất bại trong một số trường hợp, nhưng nó không thể chứng minh nó luôn đúng), nó sẽ hiển thị cảnh báo biên dịch (không phải là lỗi) và thay thế bằng xác nhận. –

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