2009-02-24 31 views
11

Vì vậy, mỗi lần tôi viết biểu thức lambda hoặc phương thức ẩn danh bên trong một phương thức mà tôi không nhận được hoàn toàn, tôi buộc phải biên dịch lại và khởi động lại toàn bộ khung ứng dụng hoặc đơn vị kiểm tra để khắc phục. Điều này là nghiêm trọng gây phiền nhiễu, và tôi kết thúc lãng phí thời gian hơn tôi đã lưu bằng cách sử dụng các cấu trúc này ở nơi đầu tiên. Thật tệ khi tôi cố gắng tránh xa họ nếu tôi có thể, mặc dù Linq và lambdas là một trong những tính năng C# yêu thích của tôi.Tại sao tôi không thể chỉnh sửa phương thức chứa phương thức ẩn danh trong trình gỡ lỗi?

Tôi cho rằng có lý do kỹ thuật tốt cho lý do tại sao theo cách này và có lẽ ai đó biết? Hơn nữa, không ai biết nếu nó sẽ được cố định trong VS2010?

Cảm ơn.

Trả lời

14

Có một lý do rất tốt cho việc bạn không thể làm điều này. Lý do đơn giản là chi phí. Chi phí cho phép tính năng này trong C# (hoặc VB) là cực kỳ cao.

Chỉnh sửa hàm lambda là một trường hợp cụ thể của một lớp các vấn đề ENC rất khó giải quyết với kiến ​​trúc ENC (Edit'n'Continue) hiện tại. Cụ thể, nó rất khó để ENC bất kỳ phương pháp mà nơi ENC làm một trong các cách sau: -

  1. Tạo Metadata dưới hình thức của một lớp
  2. chỉnh sửa hoặc tạo ra một phương pháp chung

Các vấn đề đầu tiên là nhiều ràng buộc về logic hơn nhưng nó cũng va chạm vào một vài hạn chế trong kiến ​​trúc ENC. Cụ thể là vấn đề đang tạo ra lớp học đầu tiên không phải là quá khó khăn. Điều khó chịu là tạo ra lớp học sau lần chỉnh sửa thứ hai. Động cơ ENC phải bắt đầu theo dõi bảng biểu tượng không chỉ cho mã trực tiếp, mà cả các lớp được tạo ra nữa. Thông thường điều này không quá tệ, nhưng điều này trở nên ngày càng khó khăn khi hình dạng của một lớp được tạo ra dựa trên ngữ cảnh mà nó được sử dụng (như trường hợp với lambdas vì các bao đóng). Quan trọng hơn, làm thế nào để bạn giải quyết sự khác biệt đối với các cá thể của các lớp đã tồn tại trong tiến trình?

Vấn đề thứ hai là hạn chế nghiêm ngặt trong kiến ​​trúc CLR ENC. Không có gì mà C# (hoặc VB) có thể làm để giải quyết vấn đề này.

Lambdas không may xảy ra cả hai vấn đề này. Các phiên bản ngắn là ENC'ing một lambda liên quan đến rất nhiều đột biến trên các lớp học hiện tại (có thể hoặc có thể không được tạo ra từ các ENC khác). Vấn đề lớn xảy ra trong việc giải quyết sự khác biệt giữa mã mới và các cá thể đóng hiện có đang tồn tại trong không gian quy trình hiện tại. Ngoài ra, lambdas có xu hướng sử dụng generics nhiều hơn so với mã khác và nhấn vấn đề # 2.

Chi tiết rất đẹp và một chút quá liên quan đến câu trả lời SO bình thường. Tôi đã xem xét việc viết một bài đăng blog dài về đề tài này. Nếu tôi đi xung quanh nó, tôi sẽ liên kết nó trở lại câu trả lời cụ thể này.

+1

Thẳng từ miệng ngựa. +1 –

+0

@Jon Chúng tôi đã có nhiều cuộc họp nội bộ về chủ đề này và tôi đã phải trình bày bài này nhiều lần. Tôi thực sự cần phải viết một tài liệu đầy đủ về chủ đề này. Viết blog có vẻ như là một nơi tốt cho nó. Hy vọng rằng điều này sẽ được giải quyết trong một phiên bản tương lai của VS. – JaredPar

+1

Hãy viết một blog về nó. – Eyvind

0

Khởi động lại thử nghiệm đơn vị sẽ mất vài giây, nếu có. Tôi chưa bao giờ thích mô hình "chỉnh sửa và tiếp tục" thành thật - bạn nên luôn chạy lại từ IMO ban đầu, chỉ trong trường hợp thay đổi giữa chừng thực thi sẽ ảnh hưởng đến mã chạy trước đó. Cho rằng, bạn nên sử dụng các bài kiểm tra đơn vị có thể chạy với một vòng quay rất nhanh. Nếu xét nghiệm đơn vị cá nhân của bạn mất một thời gian khó chịu để bắt đầu, đó là một cái gì đó bạn nên xem xét giải quyết.

EDIT: Đối với lý do tại sao nó không hoạt động - bạn có thể thấy rằng nó hoạt động đối với một số lambdas nhưng không phải cho những người khác. Các biểu thức lambda không nắm bắt bất kỳ biến nào (bao gồm this) được lưu trong một biến tĩnh riêng, do đó chỉ có một cá thể của đại biểu được tạo ra. Thay đổi mã có nghĩa là reinitialising biến mà có thể có tác dụng phụ thú vị tôi nghi ngờ.

+0

Tôi đồng ý .... nhưng không phải là câu trả lời cho câu hỏi. –

+0

Tôi biết bạn sẽ biết câu trả lời ;-) –

+0

IMO câu trả lời cho nhiều câu hỏi là để tránh đi vào tình huống đau đớn để bắt đầu. –

1

Theo danh sách Supported Code Changes, bạn không thể thêm trường vào các loại hiện có. Các phương thức ẩn danh được biên dịch thành các lớp có tên kỳ lạ (kinda <>_c__DisplayClass1), chính xác là: các kiểu. Mặc dù các thay đổi của bạn đối với phương thức nặc danh có thể không bao gồm việc thay đổi tập các biến kèm theo (thêm những biến sẽ thay đổi các trường của một lớp hiện có), tôi đoán đó là lý do không thể sửa đổi các phương thức nặc danh.

+1

Bạn không phải sửa đổi chính phương thức ẩn danh cho vấn đề này để tự biểu hiện, nó đủ để sửa đổi một phương thức _contains_ một phương thức nặc danh, và có vẻ như ngay cả một không gian đơn lẻ cũng đủ để tống nó ra ... – Eyvind

1

Nó là một chút đáng tiếc khi tính năng này được hỗ trợ một phần trong VB nhưng không phải trong C#: http://msdn.microsoft.com/en-us/library/bb385795.aspx

Thực hiện hành vi tương tự trong C# sẽ giảm mức độ đau bằng 80% cho các chức năng có chứa biểu thức lambda, nơi chúng ta không cần phải sửa đổi các biểu thức lambda cũng như bất kỳ biểu thức nào phụ thuộc vào chúng, và có lẽ không phải là một "chi phí quái vật".

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