2012-06-25 11 views
16

Możemy określić „pochodzi od” ograniczenia na parametry typu rodzajowego jak ten:Czy istnieje ogólne ograniczenie typu dla "skąd NIE pochodzi od"?

class Bar<T> where T : IFooGenerator 

Czy istnieje sposób, aby określić NIE pochodzi od?


My use-case: Mam kilka FooGenerator s, które są parallelizable, z tym samym kodem Zrównoleglanie dla każdego, ale nie chcemy ich do zawsze być parallelized.

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

Zatem utworzyć rodzajowe klasy kontenera do generowania Foo równolegle:

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

Ponieważ chcę FooGenerator i ParallelFooGenerator<FooGenerator> być stosowane zamiennie, robię ParallelFooGenerator : IFooGenerator. Jednak wyraźnie nie chcę, aby ParallelFooGenerator<ParallelFooGenerator> było legalne.

Tak więc, jako pytanie pomocnicze, istnieje prawdopodobnie lepszy sposób zaprojektowania tego, jeśli ograniczenia "nie pochodzą od" są niemożliwe?

+2

'ParallelFooGenerator ' już nie jest możliwe, ponieważ 'ParallelFooGenerator' to typ rodzajowy i nie określił ogólny argument. Na przykład, 'ParallelFooGenerator >' jest możliwy - i czy pozwolenie na taki typ naprawdę byłoby takie złe? – cdhowie

+1

Nie jest to niemożliwe - dozwolone ograniczenia: http://msdn.microsoft.com/en-us/library/d5x73970.aspx – Slugart

+0

@cdhowie: Wow, derp, masz rację. Cóż, to rozwiązuje mój problem :) Ale pytanie może być przydatne innym! –

Odpowiedz

9

Można użyć coś jak poniżej:

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

To jest lepszy projekt imho.* Dodanie * interfejsu o jeden poziom w górę zamiast ograniczania spadku o jeden poziom w dół to droga czystsza i łatwiejsza do zrozumienia. Każdy interfejs i klasa ma sens sam. – vidstige

+0

@cdhowie rozwiązany * mój * problem, ale zaznaczam to poprawnie, ponieważ odpowiada na pytanie w tytule. Dzięki! –

7

ParallelFooGenerator<ParallelFooGenerator> już nie jest możliwe, ponieważ ParallelFooGenerator jest typem ogólnym i nie podano ogólnego argumentu.

Na przykład, ParallelFooGenerator<ParallelFooGenerator<SomeFooGenerator>> jest możliwe - i czy pozwolenie na taki typ naprawdę będzie takie złe?

4

Prosta odpowiedź brzmi: nie.

Długa odpowiedź (jeszcze nie):

Microsoft stawia go dobrze w ich explanation of type constrains: „kompilator musi mieć jakąś gwarancję, że operator lub metoda musi zadzwonić będą wspierane przez dowolny rodzaj argumentu, który może być określony przez kod klienta. "

Podstawowym celem ograniczeń nie jest zabronienie używania niektórych typów, ale raczej umożliwienie kompilatorowi informacji o obsługiwanych operatorach lub metodach. W trakcie wykonywania można jednak wykonać check if a type implements/inherits a specific interface/base class i podać wyjątek. Z tym jednak nie będziesz w stanie uzyskać błędu w czasie projektowania od intellisense.

Mam nadzieję, że to pomoże.

Powiązane problemy