2009-10-30 35 views
26

Có sự khác biệt nào giữa hai cách tạo đối tượng không.Activator.CreateInstance <T> Vs mới

Student s1 = Activator.CreateInstance<Student>(); 
Student s1 = new Student(); 
  • Có sự khác biệt trong cách constructor được gọi hoặc khởi tạo bộ nhớ?
  • Theo hiểu biết của tôi, phương pháp đầu tiên trông hoàn toàn thừa. Nếu lập trình viên biết kiểu dữ liệu trong suốt thời gian thiết kế, anh ta sẽ sử dụng phương thức thứ hai.
+0

Related: http://stackoverflow.com/questions/6582259/fast-creation-of-objects-instead-of-activator-createinstancetype, http://stackoverflow.com/questions/6069661/does-system-activator -createinstancet-have-performance-issues-big-đủ-to-di – nawfal

Trả lời

12

quá tải này của phương pháp "Activator.CreateInstance" được sử dụng bởi trình biên dịch để thực hiện các instantiation của loại được xác định bởi các tham số kiểu sử dụng generics.

Giả sử bạn có các phương pháp sau đây:

public static T Factory<T>() where T: new() 
{ 
    return new T(); 
} 

Trình biên dịch sẽ chuyển đổi các "return new T();" để gọi "CreateInstance".

Nói chung, không có sử dụng cho mã CreateInstance trong mã ứng dụng, vì loại phải được biết lúc biên dịch. Nếu loại được biết tại thời gian biên dịch, cú pháp instantiation bình thường có thể được sử dụng (toán tử mới trong C#, New trong Visual Basic, gcnew trong C++).

More Info: http://msdn.microsoft.com/en-us/library/0hcyx2kd.aspx

+10

Rất thông thường đối với một loại không biết tại thời gian biên dịch. Nó rất hữu ích khi tách hợp đồng (giao diện) và thực hiện. – Thorarin

+0

Sẽ rất khó để viết mã deserialization mà không có 'CreateInstance'! – Gabe

+0

Tôi sẽ gọi đoạn cuối cùng tất cả đều sai. Nó khá phổ biến để có một tên tập tin trong một cấu hình và cần phải nhanh chóng nó. Tôi giả sử bạn đang cụ thể đề cập đến quá tải chung (được sử dụng trong câu hỏi) mà sẽ yêu cầu loại bê tông tại thời gian biên dịch. –

3

Không, Activator.CreateInstance<T> chỉ cần gọi hàm tạo mặc định bên dưới bìa. Sự khác biệt duy nhất giữa các ví dụ của bạn là một cuộc gọi phương thức bổ sung đến CreateInstance<T>.

Từ Activator.CreateInstance<T>:

Tạo một thể hiện của loại định bởi tham số loại generic quy định, sử dụng constructor parameterless.

4

Gọi mới có hiệu suất cao hơn, CreateInstance có thể sử dụng phản chiếu chậm.
Nếu bạn biết loại trong thời gian thiết kế - hãy sử dụng mới, ngay cả khi hai cuộc gọi giống hệt nhau (chúng không phải!) Tại sao quá phức tạp mã của bạn?

Chỉ sử dụng Activator.CreateInstance khi bạn không biết loại T trong thời gian thiết kế và bạn cần độ phân giải thời gian chạy của loại.

+0

có, nó sử dụng sự phản chiếu và do đó, 'new T()' nên được ưa thích thay vì 'Activator.CreateInstance ()' ([Nguồn] (http : //typedescriptor.net/browse/members/246503-System.Activator.CreateInstance [T]())). – Shimmy

5

Tôi sẽ không gọi Activator.CreateInstance() dự phòng.

Nếu bạn biết loại, có, bạn chỉ cần sử dụng new. Tuy nhiên, trong các trường hợp yêu cầu tải động các loại không xác định từ các khung plugin hoặc nơi loại được phân tích cú pháp từ một chuỗi (từ, ví dụ: tệp cài đặt), nó cực kỳ hữu ích.

Và để trả lời câu hỏi về sự khác biệt giữa hai, không, dưới mui xe, không có sự khác biệt thực sự giữa việc gọi new T()Activator.CreateInstance<T>(), như đã được Andrew Hare chỉ ra.

EDIT: Đừng bận tâm, tôi đã nhầm lẫn các generic CreateInstance<T>() với cách khác thường được sử dụng hơn CreateInstance(Type type)

3

Một sự khác biệt lớn là

Student s1 = new Student(); 

sẽ không biên dịch nếu không có constructor mặc định trên Student, trong khi

Student s1 = Activator.CreateInstance<Student>(); 

sẽ biên dịch ngay cả khi Student làm không có hàm tạo mặc định. (Nó sẽ biên dịch, và cho phép bạn chạy chương trình, nhưng nếu không có hàm tạo nào phù hợp, bạn sẽ nhận được một ngoại lệ, trong khi hàm khởi tạo sẽ không biên dịch nếu hàm tạo không tồn tại.)

Tương tự, gọi CreateInstance là một sử dụng tiềm ẩn của lớp, vì vậy, ví dụ, Resharper sẽ không biết rằng bạn đang instantiating nó, và có thể cho bạn biết rằng lớp học là không bao giờ instantiated.

Như đã đề cập trong câu trả lời khác, cuộc gọi CreateInstance cũng cho phép việc sử dụng một tham số kiểu chung chung:

T s1 = Activator.CreateInstance<T>(); 

dù bạn có lẽ sẽ tốt hơn bằng cách sử dụng một new loại hạn chế, vì nó sẽ cung cấp cho bạn biên dịch -giảm bảo rằng thực sự có một nhà xây dựng được gọi.

Quá tải Activator.CreateInstance(Type, ...) hữu ích hơn nhiều.

+0

Bạn có chắc chắn không? Nhà xây dựng nào nó sẽ gọi, nếu không có nhà xây dựng mặc định? Những tham số nào nó sẽ truyền cho constructor đó? –

+0

@ZarShardan Nó sẽ ném một ngoại lệ. Quan điểm của tôi là nó vẫn sẽ biên dịch; tức là: bạn sẽ gặp lỗi thời gian chạy thay vì lỗi trình biên dịch. (lỗi trình biên dịch là thích hợp hơn.) –

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