2016-07-24 12 views
0

Ich versuche, ein paar konkrete Instanzen in Sammlung hinzufügen, wo alle konkreten Instanzen von der gleichen Schnittstelle erben. Aber es kompiliert nicht.Wie fügt man einer Sammlung verschiedene konkrete Instanzen hinzu (die alle eine gemeinsame Schnittstelle erben)?

// Common interface. 
public interface ISearchService<in TSearchOptions> where TSearchOptions : ISearchOptions 
{ .. } 

// Concrete #1. 
public class FooSearchService : ISearchService<FooSearchOptions> 
{ .. } 

// Concrete #2. 
public class BaaSearchService : ISearchService<BaaSearchOptions> 
{ .. } 

Also mit dem obigen Code, beide Foo und Baa erben beide von einem ISearchService<ISearchOptions> aber jeder hat ihre eigenen spezifischen Suchoption Typ definiert.

Also versuche ich dies (was nicht kompilieren):

var searchServices = new List<ISearchService<ISearchOptions>> 
{ 
    new FooSearchService(), 
    new BaaSearchService() 
}; 

I've written the full code up on .NET Fiddle.

Die Idee ist, dass ich eine gemeinsame Sammlung von konkreten Instanzen habe, die alle eine gemeinsame Basisschnittstelle haben.

Ich bin mir ziemlich sicher, dass ich hier versagt habe wegen einer * abweichenden Dummheit, die ich ständig einfach nicht verstehe.

Ich dachte, vielleicht versuche ich zu viel zu tun .. so I've tried a new .NET Diffle with something different aber das funktioniert auch nicht.

Kann mir bitte jemand helfen?

Ich möchte nur eine gemischte Tüte einer gemeinsamen generische Schnittstelle :(

+0

Ich denke, Sie meinen "implementieren eine gemeinsame Schnittstelle". Vererbung ist ein Klassen/Unterklassen-Konzept (Suche nach "implementiert" vs "erbt"). Es ist am besten, richtige Sprachkonzepte zu verwenden, um andere Leser, die vielleicht lernen, nicht zu verwirren. –

Antwort

0

Es kompiliert, wenn Sie den Code, um diese Änderung:

public interface ISearchService<out TSearchOptions> where TSearchOptions : ISearchOptions 
{ } 
1

Sie out statt in verwenden sollte:

out bedeutet covariant was bedeutet, dass das Argument von einer Klasse zu einer seiner Basisklassen wechseln kann. Denken Sie an den Rückgabetyp der Methode (Ausgabe), wenn Sie das Ergebnis der Methode als Basisklasse verwenden können, können Sie eine beliebige seiner abgeleiteten Klassen nehmen.

in bedeutet contravariant was bedeutet, dass das Argument von einer Klasse in eine davon abgeleitete Klasse wechseln kann. Denken Sie an die Parameter der Methode (Eingabe), wenn Ihre Methode eine abgeleitete Klasse akzeptieren kann, können Sie eine Methode übergeben, die eine Basisklasse möchte.

public interface ISearchService<out T> where T : ISearchOptions 
{ 
} 

Hinweis: Denken an Eingabe-Methode und Ausgang nur meine Strategie ist zu erinnern, wenn out und in zu verwenden, es ist auch die Art und Weise arbeiten, generische Typparameter delegieren. Grundsätzlich funktionieren covariant und contravariant auf die gleiche Weise sowohl für die Schnittstelle als auch für den Delegaten.

+0

URGH :(Ihre Antwort war ... bis ... ich die folgende Methode zur Schnittstelle hinzugefügt: 'Aufgabe SearchAsync (TSearchOptions Suchoption);' FML :( –

+0

@ Pure.Krome: '' bedeutet Bereich führt zum Ausgang ', aber Sie verwenden es als Eingabe, die ungültig ist: http://stackoverflow.com/questions/5041664/t-must-be-contravariantly-valid –

+0

Also gibt es keine Möglichkeit, dies zu tun? –