Trong mã mẫu được trình bày bên dưới, phương thức "CompileError" sẽ không biên dịch, vì nó yêu cầu ràng buộc where T : new()
như được hiển thị trong phương thức CreateWithNew()
. Tuy nhiên, phương thức CreateWithActivator<T>()
chỉ biên dịch mà không bị ràng buộc.Tại sao Activator.CreateInstance <T>() được phép không có ràng buộc kiểu generic() chung mới?
public class GenericTests
{
public T CompileError<T>() // compile error CS0304
{
return new T();
}
public T CreateWithNew<T>() where T : new() // builds ok
{
return new T();
}
public T CreateWithActivator<T>() // builds ok
{
return Activator.CreateInstance<T>();
}
}
Tại sao điều này?
Theo https://stackoverflow.com/a/1649108/531971, có sự tham khảo MSDN documentation, và this question, khái niệm new T()
trong Generics là thực sự thực hiện sử dụng Activator.CreateInstance<T>()
. Vì vậy, tôi không hiểu tại sao gọi số new T()
yêu cầu loại chung được hạn chế theo cách có thể bỏ qua khi sử dụng Activator.CreateInstance<T>()
.
Hoặc, để đặt câu hỏi theo cách khác: điểm của ràng buộc where T : new()
là gì, nếu dễ dàng tạo các phiên bản T
trong một phương pháp chung mà không có ràng buộc, bằng cách trực tiếp sử dụng cơ sở hạ tầng cơ bản giống nhau?
Vì 'CreateInstance()' chỉ sử dụng sự phản chiếu cũ đơn giản và không chịu bất kỳ ràng buộc nào. Nếu kiểu có một hàm tạo mặc định, nó sẽ tạo ra nó. –
Đây là điều tự kiểm soát. Bạn có thể làm khá nhiều thứ thông qua sự phản chiếu (thậm chí tiêu diệt tất cả các nguyên tắc OOP), nhưng nhiều người sẽ không đánh giá cao nó, gây ra sự bẩn thỉu của nó. – eocron
Có rất nhiều cách viết mã vụng về cho phép bạn loại bỏ một lỗi thời gian biên dịch và tạo ra một thời gian chạy thay thế. Đây chỉ là một ví dụ. Ví dụ. 'dynamic' cho phép bạn viết các lời gọi đến các hàm không tồn tại, do đó, thay vì một lỗi trình biên dịch, bạn nhận được một ngoại lệ thời gian chạy. Tương tự như vậy, ở đây, 'CreateInstance' cho phép bạn trì hoãn việc tìm ra rằng không có hàm tạo tham số nào tồn tại cho đến khi chạy. –