Esiste un vincolo di tipo generico per “dove NON deriva”?

Possiamo specificare un vincolo “derivato da” su parametri di tipo generico come questo:

class Bar where T : IFooGenerator 

C’è un modo per specificare NON derivato da?


Il mio caso d’uso: ho un sacco di FooGenerator che sono parallelizzabili, con lo stesso codice di parallelizzazione per ciascuno, ma non vogliamo che siano sempre paralleli.

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

Pertanto, creo una class contenitore generica per generare Foo in parallelo:

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

Dal momento che voglio che FooGenerator e ParallelFooGenerator siano intercambiabili, ParallelFooGenerator : IFooGenerator . Tuttavia, chiaramente non voglio che ParallelFooGenerator sia legale.

Quindi, come domanda ausiliaria, c’è forse un modo migliore di progettarlo se i vincoli “non derivati ​​da” sono impossibili?

Potresti usare qualcosa come la seguente:

 public interface IFooGenerator { Foo GenerateFoo(); } interface ISerialFooGenerator : IFooGenerator { } interface IParallelFooGenerator : IFooGenerator { } public class FooGenerator : ISerialFooGenerator { public Foo GenerateFoo() { //TODO return null; } } public class ParallelFooGenerator : IParallelFooGenerator where T : ISerialFooGenerator, new() { public Foo GenerateFoo() { //TODO return null; } } 

ParallelFooGenerator non è già ansible, perché ParallelFooGenerator è un tipo generico e non hai specificato un argomento generico.

Ad esempio, ParallelFooGenerator> è ansible – e consentirebbe ad un tipo del genere di essere così cattivo?

La semplice risposta è no.

La lunga risposta (ancora no):

Microsoft lo mette bene nella spiegazione dei vincoli di tipo : “Il compilatore deve avere una certa garanzia che l’operatore o il metodo che deve chiamare sia supportato da qualsiasi argomento di tipo che potrebbe essere specificato dal codice client.”

Lo scopo fondamentale dei vincoli non è quello di impedire l’uso di determinati tipi, ma piuttosto di consentire al compilatore di sapere quali operatori o metodi sono supportati. Tuttavia, è ansible controllare se un tipo implementa / eredita una specifica interfaccia / class base in fase di esecuzione e genera un’eccezione. Con ciò, però, non sarà ansible ottenere un errore in fase di progettazione da intellisense.

Spero che questo possa essere d’aiuto.