2010-03-15 49 views
34

Thực tiễn tốt nhất để xử lý các đối tượng trong hoặc vòng lặp là gì? Chúng ta có nên tạo một đối tượng bên ngoài các vòng lặp và tạo lại nó một lần nữa (sử dụng mới ...) hoặc tạo một đối tượng mới cho mỗi vòng lặp lặp lại không?
Ví dụ:Thực tiễn tốt nhất để tạo các đối tượng được sử dụng trong/vòng lặp foreach

foreach(var a in collection) 
{ 
    SomeClass sc = new SomeClass(); 
    sc.id = a; 
    sc.Insert(); 
} 

hoặc

SomeClass sc = null; 
foreach(var a in collection) 
{ 
    sc = new SomeClass(); 
    sc.id = a; 
    sc.Insert(); 
} 

Đó là tốt hơn?

Trả lời

67

Cách đầu tiên là tốt hơn vì nó rõ ràng truyền tải phạm vi dự định của biến và ngăn các lỗi vô tình sử dụng một đối tượng nằm ngoài phạm vi dự định.

Một lý do để muốn sử dụng biểu mẫu thứ hai là nếu bạn muốn thoát khỏi vòng lặp và vẫn có tham chiếu đến đối tượng bạn đã truy cập lần cuối trong vòng lặp.

Lý do xấu để chọn biểu mẫu thứ hai là hiệu suất. Nó có thể có vẻ thoạt nhìn rằng phương pháp thứ hai sử dụng ít tài nguyên hơn hoặc bạn chỉ đang tạo một đối tượng và sử dụng lại nó. Đây không phải là trường hợp ở đây. Việc khai báo lặp đi lặp lại của một biến bên trong một vòng lặp không tiêu thụ bất kỳ tài nguyên bổ sung hoặc chu kỳ đồng hồ để bạn không đạt được bất kỳ lợi ích hiệu suất nào từ việc kéo khai báo ra ngoài vòng lặp.

+3

+1 - đối tượng chỉ nên được khai báo ở đâu và khi nào cần. Nếu bạn cần int i trong vòng lặp for, hãy khai báo nó trong vòng lặp for chứ không phải ở trên cùng của phần thân hàm. Xem mã hoàn thành :). – JonH

+1

Trong khai báo biến .Net thực sự là siêu dữ liệu cho phương thức. Vị trí thực tế của nơi mà biến được tạo ra trong mã chỉ ảnh hưởng đến phạm vi cho trình biên dịch ... Nói cách khác, không có sự khác biệt về hiệu năng giữa hai ví dụ này. –

+2

Ngày xửa ngày xưa, có sự khác biệt nhỏ về IL được tạo ra giữa hai vòng lặp (giống với Java và C++), mặc dù không đủ để quan tâm. Không chắc chắn nếu các trình biên dịch hiện tại đã thay đổi đó hoặc nếu CLR tối ưu hóa thêm IL đi. –

4

Tôi chắc chắn ai đó có thể roi ra phân tích MSIL, nhưng thực tế không có sự khác biệt rõ rệt trong việc thực thi hoặc hiệu suất. Điều duy nhất bạn đang ảnh hưởng là lưu trữ một tham chiếu đối tượng.

Tôi nói giữ cho nó sạch sẽ và đơn giản; khai báo biến trong vòng lặp. Điều này cung cấp nguyên tắc mở/đóng trong thực tế, vì vậy bạn biết phạm vi biến được sử dụng và không được sử dụng lại ở nơi khác. Trong vòng lặp tiếp theo, biến mất phạm vi và được khởi động lại tự động.

1

Tôi nghĩ điều đó không quan trọng đối với hiệu suất, nhưng tôi thích điều đầu tiên hơn. Tôi luôn luôn cố gắng để giữ tuyên bố và instantiation với nhau nếu có thể.

+0

'Go To Definition' là hữu ích hơn nhiều khi nó thực sự đặt đối tượng thay vì khai báo nó. – cjk

3

Bạn đang tạo một đối tượng mới trong mỗi vòng lặp lặp lại trong cả hai trường hợp (vì bạn gọi new SomeClass()).

Cách tiếp cận trước đây làm rõ rằng sc chỉ được sử dụng bên trong vòng lặp, có thể là một lợi thế từ quan điểm bảo trì.

0

Tôi sẽ sử dụng cái đầu tiên, nhưng đối với trình biên dịch thì giống nhau, vì trình biên dịch di chuyển khai báo các biến từ các vòng lặp. Tôi đặt cược sau khi biên dịch mã sẽ giống như mã thứ hai.

+0

Đóng. Thứ hai tạo thêm 2 lệnh IL, ldnull và stloc.n để gán null cho sc. –

12

Trước hết, tôi lưu ý rằng bạn có nghĩa là "tạo các biến số " khi bạn nói "tạo đối tượng". Các tham chiếu đối tượng đi trong các biến số, nhưng chúng không phải là các biến.

Lưu ý rằng kịch bản bạn mô tả giới thiệu sự khác biệt ngữ nghĩa khi vòng lặp chứa hàm ẩn danh và biến là một biến thể bên ngoài được đóng kín của hàm ẩn danh. Xem

http://ericlippert.com/2009/11/12/closing-over-the-loop-variable-considered-harmful-part-one/

để biết chi tiết.

1

Tôi sẽ đi với tùy chọn 2 để gọn gàng, để giữ tất cả các khai báo ở một nơi. Bạn có thể nói rằng "các đối tượng chỉ nên được khai báo ở đâu và khi nào chúng cần" nhưng vòng lặp của bạn có thể sẽ có ít phương pháp riêng.

+1

Nói như một lập trình viên C. – riwalk

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