2012-06-25 25 views
16

Chúng ta có thể chỉ định một "bắt nguồn từ" hạn chế trên các thông số kiểu chung chung như thế này:Có một ràng buộc kiểu chung cho "nơi KHÔNG bắt nguồn từ" không?

class Bar<T> where T : IFooGenerator 

Có cách nào để xác định KHÔNG có nguồn gốc từ đâu?


use-case của tôi: Tôi có một loạt các FooGenerator s mà parallelizable, với mã song song tương tự cho mỗi, nhưng chúng tôi không muốn họ luôn được song song.

public class FooGenerator : IFooGenerator 
{ 
    public Foo GenerateFoo() { ... } 
} 

Vì vậy, tôi tạo ra một lớp chứa chung để tạo Foo song song:

public class ParallelFooGenerator<T> : IFooGenerator where T : IFooGenerator 
{ 
    public Foo GenerateFoo() 
    { 
     //Call T.GenerateFoo() a bunch in parallel 
    } 
} 

Vì tôi muốn FooGeneratorParallelFooGenerator<FooGenerator> được hoán đổi cho nhau, tôi làm ParallelFooGenerator : IFooGenerator. Tuy nhiên, tôi rõ ràng không muốn ParallelFooGenerator<ParallelFooGenerator> hợp pháp.

Vì vậy, như một câu hỏi phụ trợ, có lẽ có cách nào tốt hơn để thiết kế điều này nếu những ràng buộc "không bắt nguồn từ" là không thể?

+2

'ParallelFooGenerator 'đã là không thể, bởi vì' ParallelFooGenerator' là một kiểu generic và bạn đã không chỉ định một lập luận chung chung. Ví dụ, 'ParallelFooGenerator >' là có thể - và sẽ cho phép một kiểu như vậy thực sự là xấu? – cdhowie

+1

Không thể thực hiện được - các ràng buộc được phép: http://msdn.microsoft.com/en-us/library/d5x73970.aspx – Slugart

+0

@cdhowie: Wow, derp, bạn nói đúng. Vâng, điều đó giải quyết vấn đề của tôi :) Nhưng câu hỏi vẫn có thể hữu ích cho người khác! –

Trả lời

9

Bạn có thể sử dụng giống như sau:

public interface IFooGenerator 
{ 
    Foo GenerateFoo(); 
} 

interface ISerialFooGenerator : IFooGenerator { } 

interface IParallelFooGenerator : IFooGenerator { } 

public class FooGenerator : ISerialFooGenerator 
{ 
    public Foo GenerateFoo() 
    { 
     //TODO 
     return null; 
    } 
} 

public class ParallelFooGenerator<T> : IParallelFooGenerator 
    where T : ISerialFooGenerator, new() 
{ 
    public Foo GenerateFoo() 
    { 
     //TODO 
     return null; 
    } 
} 
+1

Đây là thiết kế tốt hơn.* Thêm * một giao diện một cấp lên thay vì hạn chế thừa kế một cấp xuống là cách sạch hơn và dễ hiểu hơn. Mỗi giao diện và lớp học có ý nghĩa riêng. – vidstige

+0

@cdhowie đã giải quyết * sự cố * của tôi, nhưng tôi đánh dấu chính xác là nó trả lời câu hỏi trong tiêu đề. Cảm ơn! –

7

ParallelFooGenerator<ParallelFooGenerator> là không thể, vì ParallelFooGenerator là loại chung và bạn không chỉ định đối số chung.

Ví dụ: ParallelFooGenerator<ParallelFooGenerator<SomeFooGenerator>> là có thể - và sẽ cho phép loại như vậy thực sự xấu?

4

Câu trả lời đơn giản là không.

Câu trả lời dài (vẫn không có):

Microsoft đặt nó tốt trong explanation of type constrains của họ: "Trình biên dịch phải có một số sự đảm bảo rằng các nhà điều hành hoặc phương pháp cần thiết để gọi sẽ được hỗ trợ bởi bất kỳ đối số kiểu đó có thể là được chỉ định bởi mã máy khách. "

Mục đích cơ bản của các ràng buộc là không cấm sử dụng một số loại nhất định, mà là để cho phép trình biên dịch biết những toán tử hoặc phương thức nào được hỗ trợ. Tuy nhiên, bạn có thể, check if a type implements/inherits a specific interface/base class vào thời gian chạy và ném một ngoại lệ. Tuy nhiên, với điều đó, bạn sẽ không thể nhận được lỗi thiết kế từ intellisense.

Tôi hy vọng điều này sẽ hữu ích.

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