Ich denke schon einige Tage über diese (Meta-) Frage nach:
Ist es möglich, eine gültige C # -Schnittstelle zu definieren, die in keiner Weise implementiert werden kann?
Mögliche Variationen dieser Frage: Ist es möglich, eine solche Schnittstelle in C # 2.0, 3.0, 4.0, 5.0 zu definieren? Ist es möglich, eine solche Schnittstelle zu definieren, die bei der Implementierung nicht einmal kompiliert wird oder die eine Laufzeitausnahme compiliert, aber auslöst?
Bearbeiten : Ich weiß, dass eine solche Schnittstelle nur per Definition nutzlos sein wird, aber sie ist eine nette Antwort für Vorlesungen oder das Testen von Bewerbern für einen Programmierjob, wie gut sie C # kennen.
Ist es möglich, eine gültige C # -Schnittstelle zu definieren, die nicht implementiert werden kann?
Diese Quizfrage passt nicht zu StackOverflow, aber was solls, es ist einfach zu beantworten. (Falsch, wie sich herausstellt! Lesen Sie weiter!)
%Vor% IFoo<T>
kann nicht für T
implementiert werden, da kein Typargument für T
verwendet werden kann. C
funktioniert nicht, weil C
keinen öffentlichen parameterlosen Konstruktor hat und es keine abgeleitete Klasse von C
geben kann, da der Standardkonstruktor privat ist. (Nun, es könnte eine zugängliche abgeleitete Klasse von C
in C
geben, aber in diesem Fall gibt es keine.)
UPDATE: Commenter "mike z" weist richtig darauf hin, dass
%Vor% implementiert die Schnittstelle, obwohl es natürlich keine Möglichkeit gibt, X<T>
zu instanziieren!
Noch besser, Benutzer "GranBurguesa" weist darauf hin, dass eine abgeleitete Klasse von C deklariert werden darf, solange sie niemals den privaten Konstruktor aufruft; Dies ist nur möglich, wenn es abstürzt und bei Instanziierung stirbt. (Nun, um wählerisch zu sein, wäre es auch erlaubt, dass die rekursiven Aufrufe bis auf eine Endlosschleife anstelle eines Absturzes optimiert werden.)
Beide hinterhältigen Problemumgehungen werfen eine philosophische Frage auf: Wenn eine Schnittstelle von einer Klasse implementiert wird, die niemand instanziieren kann, ist sie wirklich implementiert? Natürlich zeigt GranBurguesa, dass IFoo<D>
implementiert und aufgebaut werden kann, daher ist meine Antwort eigentlich falsch.
Es gibt auch Fälle, wie die in SLaks gelöschte Antwort, in der ein Missbrauch des generischen Mechanismus zu einem "infinitären" Typ führt. Solche Typen sind in der CLR nicht zulässig; Das C # -Design-Team hat erwogen, der C # -Compiler-Spezifikation eine ähnliche Sprache hinzuzufügen, ist aber noch nicht dazu gekommen. Die Verwendung dieser Typen kann den Compiler oder die Laufzeit zum Absturz bringen.
Ein Beispiel für einen Infinitary-Typ, der den Compiler zum Absturz bringt, finden Sie in meinem Artikel:
zur Unendlichkeit aber nicht jenseits
Hier ist eins. Schneiden Sie diesen Code in Visual Studio ein und Sie werden sehen, dass diese Schnittstelle nicht implementiert werden kann:
interface ΙAmAPerfectlyOrdinaryInterface { }
class C : IAmAPerfectlyOrdinaryInterface { }
Solange wir über Kleinigkeiten reden, halte ich das für eine sinnvolle Umsetzung von Eric Lipperts Versuch:
%Vor% Es kompiliert gut, stürzt aber mit StackOverflowException
ab, wenn Sie D
instanziieren.
Wenn Sie versuchen, eine alte Schnittstelle herauszufiltern, können Sie die Schnittstelle mit % markieren. co_de% Attribut.
Bearbeiten: als @Magnus in den Kommentaren notiert, wenn Sie ObsoleteAttribute
attribute to Error
dessen Verwendung führt zu einem Fehler.
Wenn ein Typ zugänglich und nicht versiegelt ist, ist es für externen Code möglich, Instanzen dieses Typs zu erstellen, und der Basistyp kann nicht wirklich etwas dagegen tun. Kein "vollständiges Vertrauen" oder Reflektion erforderlich.
%Vor% Beachten Sie, dass wenn ein Code nur in C # geschrieben wird, ein Basisklassen-Destruktor quietschen könnte, wenn er feststellt, dass das Objekt nicht von einem legitimen Typ ist, aber Code, der in anderen Sprachen als C # geschrieben ist, würde das Überschreiben von Finalize
erlauben zu beenden, ohne an seine Eltern zu verketten.
Ich denke, es ist möglich, eine offene generische Schnittstelle mit einer Kombination aus struct
und Klassenbeschränkungen anzugeben, die keine Kombination von Typen möglicherweise erfüllen könnte, z. B.
Ich bin mir nicht sicher, ob solch ein Open-Generic-Typ wirklich als "Schnittstelle" gelten würde, oder ob nur geschlossene generische Typen wirklich als Interfaces (oder Klassen oder Strukturen) gelten können.