Có, có những lý do chính đáng:
- Nó xác định chính xác những gì là null, có thể không rõ ràng từ
NullReferenceException
- Nó làm cho mã không thành công trên đầu vào không hợp lệ ngay cả khi một số điều kiện khác có nghĩa là giá trị không được tham chiếu
- Nó làm cho ngoại lệ xảy ra trước khi phương pháp có thể có bất kỳ tác dụng phụ nào khác mà bạn có thể gặp phải trước lần tham khảo đầu tiên
- Điều đó có nghĩa là bạn có thể tự tin rằng nếu bạn chuyển tham số vào thứ khác, bạn không vi phạm hợp đồng của họ
- Nó ghi lại các yêu cầu của phương pháp của bạn (tất nhiên là sử dụng Hợp đồng mã thậm chí còn tốt hơn)
Bây giờ đối với sự phản đối của bạn:
- Nó chậm hơn : Bạn có thấy đây thực sự là nút thắt cổ chai trong mã của bạn hay bạn đang đoán? Kiểm tra vô hiệu rất nhanh chóng và trong phần lớn các trường hợp, chúng sẽ không phải là nút cổ chai
- Nó làm cho mã khó bảo trì hơn : Tôi nghĩ ngược lại. Tôi nghĩ rằng sẽ dễ dàng hơn khi sử dụng mã khi nó được làm rõ ràng cho dù một tham số có thể rỗng hay không và bạn tin tưởng rằng điều kiện đó được thực thi.
Và khẳng định của bạn:
Rõ ràng, mã sử dụng s sẽ ném ra một ngoại lệ.
Có thật không? Xem xét:
void f(SomeType s)
{
Console.WriteLine("I've got a message of {0}", s);
}
Điều đó sử dụng s
, nhưng nó không ném ra một ngoại lệ. Nếu nó không hợp lệ s
là null và điều đó cho thấy rằng có gì đó không ổn, thì một ngoại lệ là hành vi thích hợp nhất ở đây.
Bây giờ bạn đặt các kiểm tra xác thực đối số đó ở đâu là một vấn đề khác. Bạn có thể quyết định tin tưởng tất cả mã trong lớp của riêng mình, vì vậy đừng bận tâm đến các phương thức riêng tư. Bạn có thể quyết định tin tưởng phần còn lại của assembly của mình, vì vậy đừng bận tâm đến các phương pháp nội bộ. Bạn gần như chắc chắn nên xác nhận các đối số cho các phương thức công khai.
Một lưu ý phụ: quá tải hàm tạo một tham số của ArgumentNullException
chỉ nên là tên tham số, vì vậy thử nghiệm của bạn phải là:
if (s == null)
{
throw new ArgumentNullException("s");
}
Ngoài ra, bạn có thể tạo một phương thức mở rộng, cho phép phần nào ngắn gọn hơn:
s.ThrowIfNull("s");
Trong phiên bản của tôi về phương thức mở rộng (chung), tôi đặt nó trả về giá trị ban đầu nếu nó không phải null, cho phép bạn viết những thứ như:
this.name = name.ThrowIfNull("name");
Bạn cũng có thể có quá tải không lấy tên tham số, nếu bạn không quá bận tâm về điều đó.