2017-09-06 2 views
-1

Ich habe einige Schnittstellen und Klassen für Domains und Elemente:Warum muss ich eine allgemeinere Schnittstelle implementieren, wenn ich bereits eine spezielle implementiert habe?

interface IElement {} 
class FloatElement : IElement {} 

interface IDomain<T> where T: IElement {} 
class FloatDomain : IDomain<FloatElement> 
{ 
    public static readonly FloatDomain Instance = new FloatDomain(); 
} 

Ich schrieb dieses

IDomain<IElement> foo = FloatDomain.Instance; 

bekam aber einen Fehler:

(CS0266) "Cannot implicitly convert type [...]. An explicit conversion exists (are you missing a cast?)"

(Beachten Sie, dass trotz der Hinweis " Eine explizite Konvertierung existiert ", FloatDomain.Instance as IDomain<IElement> gibt null zurück.)

Ich habe bereits herausgefunden, dass ich dieses Problem umgehen kann, indem FloatDomain auch implementieren IDomain<IElement>. Aber ich würde gerne wissen, warum diese Problemumgehung notwendig ist!

In meinem Verständnis FloatElement ist eine spezielle Version von IElement, das heißt ich implizit FloatElement zu IElement umwandeln kann. Aus diesem Grund ist IDomain<FloatElement> eine speziellere Version von IDomain<IElement>, d. H. Ich sollte auch in der Lage sein, IDomain<FloatElement> in IDomain<IElement> implizit zu konvertieren.

Oder mit anderen Worten: in meinem Verständnis ist IDomain<IElement> wie eine Basisklasse für alle anderen IDomain<T> wo TIElement implementiert, weil T=IElement der allgemeinste mögliche Fall ist.

Können Sie mich auf meinen Denkfehler hinweisen?

+0

Erfahren Sie mehr über Kovarianz. – SLaks

+0

Schauen Sie sich 'List ' an. Ziehen Sie in Erwägung, eine "Liste " in eine "Liste " zu schreiben. Stellen Sie sich vor, was passiert, wenn ein 'DefinitelyNotAString' 'Add'ed zu dieser Liste gehört. –

Antwort

2

Was Sie versuchen, ist Varianz genannt. In C# sind Interfaces standardmäßig nicht variant, und deshalb erhalten Sie Kompilierungsfehler.

interface IDomain<in T> where T: IElement {} 

interface IDomain<out T> where T: IElement {} 

Siehe Variance in Generic Types für weitere Informationen: Sie können Ihre Schnittstelle als covariant oder kontra ausdrücklich, damit es funktioniert markieren.

Verwandte Themen