Domanda

Scusate se questa è una vittima, ma non riuscivo a ottenere la giusta combinazione di parole chiave per filtrare le varie domande tipo di vincolo e di farmaci generici là fuori (come ci sono un sacco).

Ho due interfacce - diamo loro IOnline e IOffline chiamano.

Sono strettamente correlati in quanto descrivono i contratti quasi identici, ma una delle differenze principali tra loro è il contesto in cui vengono utilizzate le implementazioni concrete. Non è esattamente la mia situazione, ma illustra bene il problema.

Ho poi alcuni metodi là fuori che funzionano contro gli esecutori concreti di queste interfacce. A volte questi metodi vogliono solo a che fare con un tipo e non l'altro.

abbastanza semplice:

public void DoStuff<T>(string foo) where T : IOnline {}

Il calciatore sta attuando il codice per metodi che possono operare su tipo SIA. Ho pensato che questo sarebbe corretto, ma nel leggere l'errore di compilazione, la mia aspettativa che il vincolo sarebbe stato interpretato come "consentire a qualsiasi tipo T da utilizzare genericamente qui se attuano IOnline O IOffline", è in realtà essere interpretato come "Consenti qualsiasi tipo T da utilizzare genericamente qui se attuano ENTRAMBI".

public void DoStuff<T>(string foo) where T : IOnline, IOffline {}

Cercando di implementare due metodi diversi con lo stesso nome ma diversi vincoli fallisce come c'è ovvi problemi ambiguità -: siamo non sovraccaricano poiché l'elenco parametro è lo stesso (in quanto il comportamento desiderato è identico).

I potrebbero usare due nomi diversi per due metodi differenti, ognuno con il vincolo del caso, ma che sembra kludgy e fa altre cose a valle per essere un rompicoglioni ... fattibile, ma non l'ideale.

Mi sento come se ci deve essere qualcosa che mi manca qui ... Mi sento perfettamente a suo agio in terra generico ma questa è la prima volta che io abbia mai avuto per realizzare quello che sto cercando e mi sento come se fossi basta girare le ruote atm.

È stato utile?

Soluzione

Fornire più vincoli come nel tuo secondo esempio è davvero additiva. Il pagina MSDN sui vincoli generici ha un po 'di questo.

Potete fare i vostri due interfacce ereditano da un'interfaccia di base, e vincolare i metodi per il tipo di base?

Altri suggerimenti

Non è forse una risposta alla tua domanda, ma io spontaneamente la sensazione che si può decidere di riconfigurare le interfacce. Dalla tua domanda:

  

Sono strettamente correlati in quanto   descrivere contratti quasi identici,   ma una delle differenze principali tra   loro è il contesto in cui la   saranno utilizzati implementazioni concrete.

La mia opinione di interfacce è che Si tratta di contratti . Essi definiscono come una cosa deve cercare , non è esattamente come dovrebbe si comportano ; questo è il compito di attuazione. Ora, non ho informazioni sulla vostra applicazione o dominio del problema, ma avrei probabilmente cercare di passare un po 'di tempo ad individuare le parti identiche di quelle interfacce e spostarli in una singola interfaccia, e mantenere solo le differenze come interfacce separate. In questo modo si potrebbe forse navigare passato questo tipo di problemi più facilmente.

Credo che il modo standard in .NET per farlo è quello di avere un'interfaccia che contiene sia le funzioni IOnline e IOffline, e poi alcuni oggetti che dicono che le funzioni siano effettivamente applicate in una classe specifica. Si vede questo modello in vari luoghi in .NET con le cose come un metodo Seek (), che potrebbe o non potrebbe essere implementata e una proprietà CanSeek che è possibile testare.

Non è forse la progettazione OO più pulito, ma funziona.

perde un po 'della fase di compilazione il controllo, ma non riesco a vedere alcun modo intorno ad esso ... Tu devi scegliere quale si preferisce utilizzare, (sto assumendo la vostra preferenza sarebbe in linea):

public void DoStuff<T>(string foo)
{
    Type type = typeof(T);
    if(type.GetInterfaces().Contains(typeof(IOnline)))
         doStuffOnline<T>(foo);
    else if(type.GetInterfaces().Contains(typeof(IOffline)))
         doStuffOffline<T>(foo);
    else
         throw new Exception("T must implement either IOnline or IOffline");
}

private void doStuffOnline<T>(string foo){ // can assume T : IOnline }
private void doStuffOffline<T>(string foo){ // can assume T : IOffline }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top