2014-07-15 17 views
7

Ho un'interfaccia con due parametri generici, ma uno dei parametri dovrebbe essere fornito dall'implementazione della classe.Come implementare un parametro generico che non è generico

public interface IA<T, U> { ... } 
public class X<T> : IA<T, int> { ... } 
public class Y<T> : IA<T, MyClass> { ... } 

Tuttavia, un'altra interfaccia hanno un metodo che accetta un'istanza di IA come parametro - tuttavia, ogni caso deve essere la stessa (stessa classe può prendere multipli X, ma poi non sarà mai prendere una Y, o vice versa). Ho cercato di mettere come un constrainst generica, ma poi ho qualcosa di simile

public interface IB<T, U, V> where U : IA<T, V> { 
    void MyMethod(U value); 
} 
public class Z<T> : IB<T, X<T>, int> { ... } 

Naturalmente, non voglio scrivere quel parametro V, come non riesco a scegliere un valore per esso. Il parametro U impone già quale dovrebbe essere il valore di V! Tuttavia, non posso semplicemente rimuovere V, perché non potrei scrivere il vincolo.


Un'altra soluzione è non utilizzare il vincolo:.

public interface IB<T> { 
    void MyMethod(IA<T> value); 
} 

Ma in questo modo, non posso garantire l'attuazione di IB riceverà solo un'implementazione di IA (cioè potrà per ricevere sia X e Y, e non dovrebbe).


C'è un modo per evitare la creazione del parametro generico V nell'interfaccia IB (nella prima soluzione), mentre ancora reciprocamente escludendo le implementazioni di IA? C'è qualche ragione specifica che il compilatore non può inferire il tipo di V e mi permetta di scrivere solo class Z<T> : IB<T, X<T>> o questo caso non era previsto nelle specifiche della lingua/è stato scelto per non essere implementato?

+0

L'interfaccia 'IB' dovrebbe avere gli stessi argomenti generici di' IA'. Non vedo perché è necessario passare 'X ' come tipo. Hai abbastanza da definire 'MyMethod (IA valore)' che lo limiterebbe a 'X' o' Y' ma non a entrambi. – cgTag

risposta

3

Hai già abbastanza tipi generici per limitare IB<T,U>.MyMethod() di ricevere sia X e Y. Hai solo bisogno di definire l'argomento del metodo come accettare su un tipo specifico.

public interface IA<T,U> {} 
    public class X<T> : IA<T,int> {} 
    public class Y<T> : IA<T,string> {} 

    public interface IB<T,U> 
    { 
     void MyMethod(IA<T,U> value); 
    } 

    IB<int,int> foo; 
    X<int> a; 
    Y<int> b; 

    foo.MyMethod(a); // will compile 
    foo.MyMethod(b); // will not compile 

C'è un modo per evitare la creazione del parametro generico V nell'interfaccia IB (nella prima soluzione) mentre ancora reciprocamente escluse le implementazioni di IA? C'è qualche ragione specifica per cui il compilatore non può inferire il tipo di V e permettermi di scrivere solo la classe Z: IB> o questo caso non era previsto nelle specifiche del linguaggio/è stato scelto per non essere implementato?

Non penso sia così che l'inferenza funziona in C#. Per dedurre il tipo di U, lo MyMethod dovrebbe essere scritto in questo modo.

public interface IB<T> 
    { 
     void MyMethod<U>(IA<T,U> value); 
    } 

    IB<int> foo = null; 
    X<int> a; 
    foo.MyMethod(a); // int type is inferred by compiler 

è ancora necessario utilizzare IA<T,U> nell'interfaccia IB. Non penso che ci sia un modo semplice per aggirare ciò.

+0

Questo è corretto, grazie.Mentre il tipo nella mia domanda è logicamente inferenziale, questo perché esiste una ridondanza di tipi. – Mephy

+0

@Mephy se ho capito bene, volevi rimuovere 'IA' dall'essere usato da' IB'. Non sono sicuro che tu possa (o almeno facilmente). – cgTag

+1

@MathewFoscarini No, non lo so. C'era solo un duplicato perché avevo bisogno di specificare il parametro 'U' di' IA' e il parametro 'V' di' IB' per essere lo stesso. La tua risposta funziona bene, sono in grado di rimuovere il parametro 'U' di' IB' senza problemi. – Mephy

Problemi correlati