2013-04-26 25 views
8

Tôi đã làm việc với một nhà phát triển đã có nhiều năm kinh nghiệm trong C# của tôi. Tôi không còn cách nào để liên lạc với anh ta nữa và tôi nhớ anh ta nói rằng không nên đưa mã vào một tham số mặc định là ít hàm tạo nhưng tôi không thể nhớ lý do tại sao.Thực hành kém để bao gồm mã trong hàm dựng mặc định

Thực hành tốt hay thực hành không tốt để bao gồm mã trong hàm dựng mặc định trong C# hoặc bất kỳ ngôn ngữ nào cho vấn đề đó?

Trả lời

6

Điều đó phụ thuộc vào tình huống, đôi khi cần thiết, đôi khi nó có thể được sử dụng, đôi khi không nên ở đó.

Điều quan trọng là bất kỳ nhà xây dựng nào cũng nên để đối tượng ở trạng thái được khởi tạo đúng cách. Nếu một đối tượng luôn cần một số mã để khởi tạo, nhưng không có đầu vào cụ thể để làm điều đó, thì một hàm tạo tham số sẽ là một nơi tốt cho điều đó.

+0

Có tầm quan trọng đáng kể, nhà xây dựng không được ném ngoại lệ. Nếu bất kỳ phần nào của việc khởi tạo có thể ném, hãy quấn trong một thử/nắm bắt và xử lý nó. – GalacticCowboy

+0

@GalacticCowboy: Ngược lại, nếu hàm tạo không có khả năng khởi tạo đối tượng đúng cách, nó * nên * ném một ngoại lệ. Đó là cách duy nhất mà nhà xây dựng có thể giữ cho đối tượng không được tạo ra. Xem ví dụ: http://stackoverflow.com/questions/3629849/throwing-argumentnullexception-in-constructor – Guffa

+0

Ah, đủ rồi. Tôi đã căn cứ vào bộ nhớ của tôi về một quy tắc FxCop, nhưng nó thực sự ném vào * static * constructors - một ngoại lệ trong một constructor tĩnh sẽ dẫn đến kiểu bị phá vỡ cho toàn bộ miền ứng dụng. – GalacticCowboy

8

Nó phụ thuộc vào tình hình, nhưng chắc chắn KHÔNG phải là thực hành không tốt để đặt mã trong các hàm tạo mặc định. Nếu bạn cần, hãy tiếp tục và làm điều đó.

0

Tôi biết chúng tôi đã thực hiện cuộc gọi đến việc khởi tạo tất cả các tham số trong hàm tạo mặc định. Có những lúc chúng ta cần "để trống" dữ liệu bên ngoài khai báo, vì vậy chúng ta thực hiện nó theo một phương thức riêng và gọi nó ở hàm tạo thấp nhất cho bất kỳ đối tượng nào.

0

Đó là vấn đề về hương vị. Tôi tìm thấy những quy tắc được xác định bởi kokos người dùng rất hữu ích:

quy tắc của mình:

  1. Đừng khởi tạo với các giá trị mặc định trong tuyên bố (null, false, 0, 0.0 ...).
  2. Ưu tiên khởi tạo khai báo nếu bạn không có tham số hàm tạo thay đổi giá trị của trường.
  3. Nếu giá trị của trường thay đổi do tham số hàm tạo đặt khởi tạo trong các hàm tạo.
  4. Nhất quán trong thực tế của bạn. (Quy tắc quan trọng nhất)

see: Initialize class fields in constructor or at declaration?

0

Các trường lớp được khởi tạo thường sẽ kết thúc trong hàm tạo mặc định. Nếu bạn khởi tạo các trường lớp trên cùng một dòng như các khai báo, các câu lệnh đó sẽ không chạy nếu bạn deserialize một đối tượng như vậy. Bên cạnh đó là thực hành tốt để thu thập tất cả các initalizations trong ctor mặc định.

5

gì nói đến cái tâm là mục 17 từ Effective Java (bởi Joshua Bloch):

mục 17: Thiết kế và tài liệu cho các thừa kế hoặc nếu không cấm nó

Ông giải thích rằng một constructor nên không gọi các phương thức có thể ghi đè:

public class Super { 
    // Broken - constructor invokes an overridable method 
    public Super() { 
        overrideMe(); 
    } 
    public void overrideMe() { 
    } 
} 

Điều cuối cùng xảy ra là bạn đang gọi hàm tạo của lớp cha (khi bạn c reate một thể hiện của subclass) và bạn nhận được hành vi bất ngờ.

Nếu hàm tạo của bạn thực hiện các phương thức khác trong lớp, bạn cần phải ghi lại điều này trong API của bạn để khi các nhà phát triển phân lớp, họ sẽ biết những gì mong đợi.

Nếu không, không có hại gì khi đặt mã trong hàm tạo của bạn.

+0

https://msdn.microsoft.com/en-us/library/vstudio/ms229060(v=vs.100).aspx đúng của nó?cs-save-lang = 1 & cs-lang = csharp # code-snippet-1 – siamak

2

Khi bạn deserialize một đối tượng với một BinaryFormatter, constructor mặc định không chạy khi đối tượng được tạo ra. BinaryFormatter sử dụng một thủ thuật để có được .NET để cung cấp cho một cá thể khởi tạo trong đó không có các hàm tạo mặc định nào được chạy.

Điều này không gây ra vấn đề, bởi vì BinaryFormatter điền vào tất cả các thành viên riêng tư. Tình huống duy nhất mà tôi có thể tưởng tượng là nguy hiểm là nếu bạn sử dụng hàm khởi tạo mặc định để "đăng ký" đối tượng ở đâu đó trong một số lớp tĩnh khác hoặc thứ gì đó dọc theo các dòng đó, trong trường hợp đó bạn có một tập hợp các vấn đề hoàn toàn mới.

+0

Đó không phải là một vấn đề, vì bạn chỉ đơn giản là có thể giữ từ đánh dấu lớp như serializable nếu nó không thể được tạo ra bởi deserialisation. – Guffa

+0

@ Guffa không phải là vấn đề ở đây. Bạn có thể không biết rằng loại điều này xảy ra khi deserialization. Ngoài ra, bạn có thể triển khai giao diện IDeserializationCallback để tham gia sự kiện này nếu bạn thực sự cần nó. Nhưng bạn cần phải biết. –

2

Quy tắc

Làm cho nó đơn giản càng tốt.

Toàn bộ các tiêu chuẩn mã hóa tốt là để bảo trì và khả năng gỡ lỗi. Tất cả chúng ta đều bắt gặp mã spaghetti. Điều này chỉ để những người khác hiểu rõ hơn về API của bạn. Ngay cả với javadoc tốt, hầu hết mọi người không mong đợi hàm tạo để thay đổi trạng thái của ứng dụng.

Ví dụ, nếu instantiating đối tượng của bạn làm một số thao tác cơ sở dữ liệu, bạn tốt hơn có một lý do chết tiệt tốt.

Counter Ví dụ

Bạn vẫn cần phải làm những gì là tốt nhất. Nếu bạn quyết định để có một singleton lười tải mà tải một bộ nhớ cache hoặc kết nối hoặc những gì có bạn, toàn bộ điểm là nó sẽ tự động tải một cái gì đó khi bạn nhanh chóng nó.

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