2012-10-09 34 views
6

Tôi có một giao diện ISnack khi được thực hiện bởi một lớp, nó sẽ có một hàm tạo tham số mặc định. Về cơ bản:Có cách nào để thực thi hàm tạo không tham số không có ràng buộc chung không

public interface ISnack<T> where T : new() 
{ 

} 

Tôi sử dụng <T> where T : new() chỉ để thực thi hàm tạo tham số.

Sau đó tôi sẽ thực hiện giao diện như sau:

public class Cutlet : ISnack<Cutlet> 
{ 

} 

này hoạt động và nó chỉ đơn giản là đảm bảo Cutlet lớp có một constructor parameterless.

Bây giờ tôi có một lớp cơ sở trừu tượng Kitchen:

public abstract class Kitchen<T> where T : ISnack 
{ 

} 

Yêu cầu là Kitchen nên có hạn chế nơi T phải là một ISnack. Nhưng điều này sẽ không hoạt động vì không tồn tại ISnack, nhưng chỉ ISnack<T>.

Nếu tôi cố gắng này

public abstract class Kitchen<T> where T : ISnack<T> 
{ 

} 

nó sẽ không biên dịch ('T' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'ISnack<T>') và cũng sẽ không có ý nghĩa trong bối cảnh của tôi.

Nếu tôi có thể buộc ISnack s để có một constructor parameterless mà không kìm hãm bởi một tham số T loại, sau đó T trong Kitchen<T> có thể dễ dàng trở thành một ISnack. Làm thế nào để đi về nó?

Trả lời

10

Bạn không thể trừ khi bạn thêm ràng buộc; những hạn chế chung được tích lũy, vì vậy để làm cho trình biên dịch hạnh phúc bạn sẽ phải có:

public abstract class Kitchen<T> where T : ISnack<T>, new() 

Nếu điều đó là tốt, sau đó làm điều đó. Nếu không ổn, bạn sẽ phải xóa : new khỏi ảnh gốc và thực hiện mà không cần. Đây không phải là xấu như nó âm thanh, nhưng nó có nghĩa là bạn đẩy xác nhận xuống để thực hiện hơn là biên dịch. Nhưng: Activator.CreateInstance<T>() vẫn thực hiện những gì bạn cần, dù sao - ngay cả khi không có ràng buộc new(). Vì vậy, bạn có thể thay thế:

T newObj = new T(); // validated by the compiler 

với:

T newObj = Activator.CreateInstance<T>(); // not validated until executed 

Một thủ thuật tiện dụng khi chế loại bỏ có thể là: thêm một bài kiểm tra đơn vị/hội nhập mà tìm thấy các loại ứng cử viên thông qua phản ánh, và xác nhận các hạn chế thiếu như một phần của bộ thử nghiệm.

+0

Marc, Ditto! bạn đã vạch ra tất cả những gì tôi đã thử .. Hmmm thời gian chạy là tùy chọn tôi có tôi đoán – nawfal

+1

@nawfal Nếu nó ok, bạn có thể thêm một đối số chung thứ hai cho nhà bếp và điều này sẽ làm việc: 'abstact class Kitchen trong đó T: ISnack trong đó S: new() ' –

+0

@FelixK. bạn có thể làm cho nó một câu trả lời nữa không? – nawfal

1

chỉ cần thêm các hạn chế đối với T một lần nữa

public abstract class Kitchen<T> where T : ISnack<T>, new() {  } 
3

Bạn có thể sử dụng một tham số chung thứ hai:

abstact class Kitchen<T, S> 
    where T : ISnack<S> 
    where S : new() 
.... 

này sẽ giải quyết vấn đề của bạn.

Việc thêm tham số thứ hai vào một lớp cũng có thể gây ra một số vấn đề mà tôi đã gặp phải vì .NET 2.0 khả dụng. Một số tình huống phức tạp có thể yêu cầu thêm nhiều tham số chung hơn cho các lớp mà bạn muốn. Thông thường tôi phá vỡ chuỗi chung bằng cách thêm nhiều phôi trực tiếp (như (SpecificType)base.MyTypeTProperty). Nhận xét: Tôi cố gắng tìm một mẫu sau

+0

hoạt động này quá, nhưng tôi cho rằng là ít thanh lịch hơn so với một Marc đề nghị – nawfal

+0

@nawfal Tất nhiên, và nó có thể gây ra vấn đề trong các tình huống phức tạp hơn. Tôi có thể sẽ đăng một ví dụ sau. –

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