2011-06-24 23 views
21

Do sau (rất nhiều chỉnh sửa, pseudo-) mã:Tại sao resharper đề xuất "biến bọc trong mảng" để truy cập vào cảnh báo đóng cửa đã sửa đổi?

int count = 0; 
thing.Stub(m => m.AddBlah()).WhenCalled(o => count++); 
thing.Stub(m => m.RemoveBlah()).WhenCalled(o => count--); 

DoStuff(thing); 

Assert.AreEqual(1, count); 

ReSharper cung cấp một cảnh báo trên đếm - "Tiếp cận đóng cửa sửa đổi". Tôi hiểu tại sao tôi nhận được cảnh báo này (biến đếm được sửa đổi trong hai lambdas khác nhau, và có khả năng có ngữ nghĩa không mong muốn), nhưng tôi không hiểu lời khuyên của ReSharper: "Wrap biến cục bộ trong mảng". Nếu tôi cho phép ReSharper thực hiện việc này, tôi nhận được:

int count[] = { 0 }; 
thing.Stub(m => m.AddBlah()).WhenCalled(o => count[0]++); 
thing.Stub(m => m.RemoveBlah()).WhenCalled(o => count[0]--); 

DoStuff(thing); 

Assert.AreEqual(1, count[0]); 

Và không cảnh báo.

Tại sao sử dụng mảng an toàn?

+0

Bạn đã thấy phiên bản ReSharper này trong phiên bản nào? –

Trả lời

2

Điều này là do 2 loại khác nhau. Int là một kiểu giá trị và mảng là một kiểu tham chiếu. Điều này có nghĩa là int nằm trên stack và con trỏ của mảng nằm trên stack.

Khi bạn cập nhật một loại Giá trị, nó sẽ cập nhật phần bộ nhớ ngăn xếp đó. Các loại tham chiếu mặt khác lá đó mảnh ngăn xếp bộ nhớ một mình và sửa đổi những gì nó trỏ đến.

Trình chia sẻ lại không khiếu nại về mảng vì 2 phương pháp Lambda khác nhau đang tạo một khoảng đóng xung quanh bộ nhớ trỏ đến vị trí cập nhật giá trị. Cả Lambdas đều có cùng địa chỉ và không thay đổi địa chỉ gốc.

+1

Nhưng chắc chắn các lambdas đóng xung quanh một biến int cũng là cả hai trỏ đến cùng một điểm trong bộ nhớ, vì vậy sự khác biệt là gì? Mã thực hiện giống nhau trong cả hai trường hợp, do đó, thực hiện khôn ngoan, không có sự khác biệt. Nhưng tôi không thấy lý do tại sao resharper đối xử với họ khác nhau. – citizenmatt

+0

@citizenmatt, hãy nghĩ về trường hợp khi phương thức đã trả về, ReSharper không biết rằng lambdas sẽ chỉ chạy trong khi bạn đang gọi tới DoStuff (điều) –

+0

Đây không phải là lý do chính xác, hãy nhìn vào câu trả lời khác. Không có sự khác biệt trong việc nắm bắt các biến tham chiếu hoặc giá trị bên trong một lambda, đó là lý do tại sao hành vi cũng giống nhau. http://stackoverflow.com/questions/5438307/detailed-explanation-of-variable-capture-in-closures –

12

Tôi nhận thấy điều tương tự này trong chính bản thân mình và cũng tự hỏi tại sao nó không cảnh báo khi giá trị được bọc trong một mảng. Câu trả lời khác ở đây là không may sai, và dường như hiểu lầm cách đóng cửa được thực hiện, vì vậy tôi nghĩ rằng tôi sẽ cố gắng giải thích (những gì tôi nghĩ là) lý do đằng sau này refactoring. Như bạn đã thấy, kết quả là giống nhau cho dù được bọc mảng hay không, vì vậy việc tái cấu trúc không thực sự "sửa" bất cứ điều gì và các vấn đề tương tự có thể gặp phải khi truy cập một đóng cửa được sửa đổi thông thường tồn tại sau khi áp dụng sự thay đổi. Tuy nhiên, sau khi thay đổi vì bản thân countmảng không bị sửa đổi (chỉ nội dung của nó), cảnh báo "Truy cập vào đóng cửa đã sửa đổi" không còn phù hợp nữa.

Sự thay đổi không thực sự làm cho vấn đề trở nên rõ ràng hơn (ít nhất theo ý kiến ​​của tôi), vì vậy dường như gợi ý này về cơ bản nói cho ReSharper bỏ qua vấn đề, mà không cần phải sử dụng đến // ReSharper disable AccessToModifiedClosure cơ chế để ngăn chặn lỗi.

+0

Nó có vẻ hợp lý rằng đây là lý do của họ bởi vì tôi không thể nghĩ ra bất kỳ lý do nào khác cho mã này "sửa chữa ". Nếu nó thực sự là lý do tại sao họ thực hiện điều này, có vẻ như kỳ quặc rằng họ nghĩ rằng việc gói tất cả các truy cập vào một biến trong mảng một phần tử sẽ ít lộn xộn hơn là chỉ vô hiệu hóa cảnh báo bằng nhận xét khi nó được sử dụng. – jam40jeff

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