Tôi coi đây là sự lạm dụng câu lệnh using. Tôi biết rằng tôi là thiểu số trong vị trí này.
Tôi coi đây là một sự lạm dụng vì ba lý do.
Đầu tiên, bởi vì tôi mong đợi rằng "using" được sử dụng để sử dụng một tài nguyên và loại bỏ nó khi bạn hoàn thành nó . Thay đổi trạng thái chương trình không sử dụng một tài nguyên và thay đổi lại nó không phải là loại bỏ bất cứ thứ gì. Vì vậy, "sử dụng" để đột biến và khôi phục trạng thái là một sự lạm dụng; mã gây hiểu lầm cho người đọc bình thường.
Thứ hai, bởi vì tôi mong đợi "using" được sử dụng với mục đích lịch sự, không cần thiết . Lý do bạn sử dụng "using" để loại bỏ một tệp khi bạn hoàn thành nó không phải vì cần phải làm như vậy, mà vì nó lịch sự - ai đó có thể đang đợi để sử dụng tệp đó, vì vậy nói "xong bây giờ ”là điều đúng đắn về mặt đạo đức phải làm. Tôi hy vọng rằng tôi sẽ có thể cấu trúc lại "cách sử dụng" để tài nguyên đã sử dụng được lưu giữ lâu hơn và được xử lý sau đó, và tác động duy nhất của việc làm đó là hơi gây bất tiện cho các quy trình khác . Một khối "using" có tác động ngữ nghĩa đến trạng thái chương trình bị lạm dụng vì nó ẩn một đột biến quan trọng, bắt buộc của trạng thái chương trình trong một cấu trúc có vẻ như nó ở đó vì sự thuận tiện và lịch sự, không cần thiết.
Và thứ ba, hành động của chương trình của bạn được xác định bởi trạng thái của nó; nhu cầu vận dụng trạng thái một cách cẩn thận chính là lý do tại sao chúng ta có cuộc trò chuyện này ngay từ đầu. Hãy xem xét cách chúng tôi có thể phân tích chương trình gốc của bạn.
Khi bạn mang nó đến một cuộc xem xét mã trong văn phòng của tôi, câu hỏi đầu tiên tôi sẽ hỏi là "có thực sự chính xác để khóa phần mềm nếu một ngoại lệ được ném ra?" Rõ ràng là từ chương trình của bạn rằng điều này sẽ tích cực khóa lại khả năng đóng băng bất kể điều gì xảy ra. Có đúng không? Một ngoại lệ đã được ném ra. Chương trình ở trạng thái không xác định. Chúng tôi không biết liệu Foo, Fiddle hay Bar đã ném, tại sao họ lại ném, hoặc những đột biến nào mà họ thực hiện sang trạng thái khác chưa được làm sạch. Bạn có thể thuyết phục tôi rằng trong tình huống khủng khiếp đó, việc khóa lại luôn là điều đúng đắn?
Có thể là có, có thể là không. Quan điểm của tôi là với mã như nó được viết ban đầu, người đánh giá mã biết đặt câu hỏi . Với mã sử dụng "using", tôi không biết để đặt câu hỏi; Tôi giả sử rằng khối "using" phân bổ một tài nguyên, sử dụng nó một chút và xử lý nó một cách lịch sự khi nó được hoàn thành, không phải là dấu ngoặc nhọn đóng của khối "using" làm thay đổi trạng thái chương trình của tôi trong một khoảng thời gian đặc biệt khi tùy ý nhiều các điều kiện nhất quán của chương trình đã bị vi phạm.
Việc sử dụng khối "using" để có hiệu ứng ngữ nghĩa làm cho chương trình này trở nên phân mảnh:
}
vô cùng ý nghĩa. Khi tôi nhìn vào chiếc nẹp đóng đơn đó, tôi không nghĩ ngay rằng "chiếc nẹp đó có những tác dụng phụ ảnh hưởng sâu rộng đến tình trạng toàn cầu của chương trình của tôi". Nhưng khi bạn lạm dụng "sử dụng" như thế này, thì bỗng nhiên nó xảy ra.
Điều thứ hai tôi sẽ hỏi nếu tôi thấy mã gốc của bạn là "điều gì sẽ xảy ra nếu một ngoại lệ được đưa ra sau khi Mở khóa nhưng trước khi nhập thử?" Nếu bạn đang chạy một hợp ngữ không được tối ưu hóa, trình biên dịch có thể đã chèn một lệnh no-op trước khi thử và có thể xảy ra ngoại lệ hủy bỏ luồng khi no-op. Điều này hiếm khi xảy ra, nhưng nó xảy ra trong đời thực, đặc biệt là trên các máy chủ web. Trong trường hợp đó, mở khóa xảy ra nhưng khóa không bao giờ xảy ra, bởi vì ngoại lệ đã được ném trước khi thử. Hoàn toàn có thể mã này dễ gặp sự cố này và thực sự nên được viết
bool needsLock = false;
try
{
// must be carefully written so that needsLock is set
// if and only if the unlock happened:
this.Frobble.AtomicUnlock(ref needsLock);
blah blah blah
}
finally
{
if (needsLock) this.Frobble.Lock();
}
Một lần nữa, có thể nó có, có thể nó không, nhưng tôi biết đặt câu hỏi . Với phiên bản "đang sử dụng", nó cũng dễ gặp phải vấn đề tương tự: một ngoại lệ hủy bỏ chuỗi có thể được ném ra sau khi Frobble bị khóa nhưng trước khi vùng được bảo vệ thử liên quan đến việc sử dụng được nhập. Nhưng với phiên bản "using", tôi cho rằng đây là phiên bản "vậy thì sao?" tình hình. Thật không may nếu điều đó xảy ra, nhưng tôi cho rằng "using" chỉ ở đó để lịch sự, không làm thay đổi trạng thái chương trình cực kỳ quan trọng. Tôi giả sử rằng nếu một số ngoại lệ hủy bỏ luồng khủng khiếp xảy ra vào đúng thời điểm thì, ồ, bộ thu gom rác sẽ dọn dẹp tài nguyên đó cuối cùng bằng cách chạy trình hoàn thiện.