Cửa sổ đồng hồ Heisenberg
Điều này có thể cắn bạn rất tệ nếu bạn đang làm những thứ theo yêu cầu, như thế này:
private MyClass _myObj;
public MyClass MyObj {
get {
if (_myObj == null)
_myObj = CreateMyObj(); // some other code to create my object
return _myObj;
}
}
Bây giờ hãy nói rằng bạn có một số mã ở nơi khác bằng cách sử dụng này:
// blah
// blah
MyObj.DoStuff(); // Line 3
// blah
Bây giờ bạn muốn gỡ lỗi CreateMyObj()
phương thức của bạn . Vì vậy, bạn đặt một điểm dừng trên Dòng 3 ở trên, với ý định bước vào mã. Chỉ cần cho biện pháp tốt, bạn cũng đặt một điểm dừng trên dòng trên đó _myObj = CreateMyObj();
, và thậm chí là một điểm dừng bên trong CreateMyObj()
chính nó.
Mã đạt điểm dừng của bạn trên Dòng 3. Bạn bước vào mã. Bạn muốn nhập mã có điều kiện, vì _myObj
rõ ràng là null, phải không? Uh ... vậy ... tại sao nó lại bỏ qua điều kiện và đi thẳng tới return _myObj
?! Bạn di chuột qua _myObj ... và thực sự, nó có giá trị! Làm thế nào điều đó xảy ra?!
Câu trả lời là IDE của bạn khiến nó nhận được giá trị, bởi vì bạn mở cửa sổ "xem" - đặc biệt là cửa sổ đồng hồ "Ô tô", hiển thị các giá trị của tất cả các biến / thuộc tính có liên quan đến dòng thực thi hiện tại hoặc trước đó. Khi bạn đạt điểm dừng của mình trên Dòng 3, cửa sổ đồng hồ quyết định rằng bạn sẽ quan tâm để biết giá trị của MyObj
- vì vậy, đằng sau hậu trường, bỏ qua bất kỳ điểm dừng nào của bạn , nó đã đi và tính giá trị của MyObj
bạn - bao gồm cả cuộc gọi đến CreateMyObj()
đó đặt giá trị của _myObj!
Đó là lý do tại sao tôi gọi đây là Cửa sổ Đồng hồ Heisenberg - bạn không thể quan sát giá trị mà không ảnh hưởng đến nó ... :)
GOTCHA!
Chỉnh sửa - Tôi cảm thấy bình luận của @ ChristianHayter xứng đáng được đưa vào câu trả lời chính, bởi vì nó có vẻ như là một cách giải quyết hiệu quả cho vấn đề này. Vì vậy, bất cứ lúc nào bạn có một tài sản tải lười biếng ...
Trang trí tài sản của bạn bằng [DebuggerBrowable (DebuggerBrowableState.Never)] hoặc [DebuggerDisplay ("<được tải theo yêu cầu>")]. - Christian Hayter