Warum wird diese C # -Klassendeklaration kompiliert?

8

Diese Frage ist wirklich ein bisschen sinnlos, aber ich bin nur neugierig:

Dies:

%Vor%

kompiliert, gibt jedoch eine Warnung

while This:

%Vor%

kompiliert nicht. Nur aus reiner Neugier, gibt es einen Grund dafür?

    
BFree 21.07.2009, 02:14
quelle

9 Antworten

4

Der einzige Grund, an den ich denken kann, ist, dass Sie manchmal geschützte Methoden schreiben müssen, um andere geschützte Methoden zu überschreiben. Die Sprache könnte wurde entworfen, um dies zu ermöglichen:

%Vor%

aber nicht das

%Vor%

aber das könnte etwas schwierig zu folgen sein - es ist die Abwesenheit von override , die es nutzlos macht, während im Falle von

%Vor%

es ist die Präsenz von virtual , die nutzlos ist. Das Vorhandensein von etwas "falschem" ist wahrscheinlich leichter zu verstehen als das Fehlen von etwas Nützlichem.

In diesem Fall kann es auch Auswirkungen auf die Performance haben, virtuell zu sein, während das Schützen von etwas statt des Privaten das wahrscheinlich nicht tut - also ist es ein bisschen schwerer.

Das sind aber nur Vermutungen - wenn wir wirklich Glück haben, wird Eric Lippert eine definitive Antwort geben. Er ist derjenige, den du willst, nicht ich:)

Beste Antwort: Warnungen als Fehler behandeln und sie sind gleichwertig;)

    
Jon Skeet 21.07.2009, 13:39
quelle
12

virtuell wird verwendet, um eine Methode / Eigenschaft "override" zu deklarieren. fähig ".

sealed wird verwendet, um anzugeben, dass die Klasse nicht geerbt werden kann.

Eine virtuelle Methode in einer versiegelten Klasse kann daher niemals außer Kraft gesetzt werden, da die Klasse niemals vererbt werden kann. Es macht einfach keinen Sinn.

protected beeinträchtigt den Zugriff auf ein Mitglied, deklariert es nicht "override-fähig" wie virtuell (obwohl es oft auf diese Weise verwendet wird) und ist dementsprechend nicht widersprüchlich.

    
Kevin Montrose 21.07.2009 02:22
quelle
4

Ich kann keinen guten Grund dafür sehen. Das geschützte MyMethod kann von MyClass aufgerufen werden, wird aber nie von einer abgeleiteten Klasse aufgerufen (weil MyClass versiegelt ist). Die virtuelle Version kann auch direkt von MyClass aufgerufen werden. Es ist jedoch unzulässig, dass die Methode überschrieben wird, weil Sie keine Klasse aus MyClass ...

ableiten können     
Jason Down 21.07.2009 02:25
quelle
2

Eine versiegelte Klasse kann über Vererbung geschützte Mitglieder haben. Wenn eine Methode Teil einer Klasse ist, spielt es keine Rolle, wie diese Methode dorthin gelangt.

Im ersten Fall ist es mit der protected-Methode für die versiegelte Klasse genauso, als ob die versiegelte Klasse eine geschützte Methode geerbt hätte. Also kompiliert es.

Aus Neugier, was genau ist die Warnung gegeben?

    
abelenky 21.07.2009 02:32
quelle
2

Der Fehler ist:

  

CS0549: 'Funktion' ist ein neues virtuelles Mitglied in der versiegelten Klasse 'class'.

Erstens macht es trotz der Tatsache, dass es nicht wirklich Sinn macht, neue protected oder virtual Mitglieder in eine sealed Klasse aufzunehmen, das CLI¹ es erlaubt. Die CLI ermöglicht auch das Aufrufen von Mitgliedern einer versiegelten Klasse mit der Anweisung callvirt IL, auch wenn ein Compiler sie durch die Anweisung call ersetzen könnte.

Zur Zeit kann ich in ECMA-334 (C # -Sprachspezifikation) nichts finden, für das der Compiler den obigen Fehler ausgeben muss. Es sieht so aus, als ob eine Microsoft-Implementierung den Fehler hinzugefügt hat, nur weil es nicht sinnvoll ist, neue virtuelle Member in eine versiegelte Klasse aufzunehmen.

¹Die CLI ist eine virtuelle Maschine, und der C # -Compiler gibt Bytecode aus, der darauf ausgeführt wird. Fast jedes Konzept, das in der CLI illegal ist, ist aus diesem Grund auch in C # illegal - aber das ist ein Fall, in dem C # ein wenig mehr tut (nicht dass es ein Problem ist).

Edit: Es scheint, dass Posts, die markiert werden, erklären, warum es keinen Sinn macht , Code wie den im OP zu schreiben. Aber bezüglich der Regel, die es zu einem Compilerfehler gemacht hat, scheinen sie falsch zu sein.

    
Sam Harwell 21.07.2009 02:50
quelle
1

Eine versiegelte Klasse kann nicht unterklassifiziert werden, daher ist virtuell keine Option. Also Fehler.

Das erste ist ein bisschen albern aber gültig, also warnt es.

    
Simeon Pilgrim 21.07.2009 02:41
quelle
0

Ich nehme an, der Compiler führt einige Optimierungen mit versiegelten Klassen durch, die unmöglich sind, wenn Sie eine virtuelle Methode deklariert haben - "keine vtable zu haben" scheint ein wahrscheinlicher Kandidat zu sein.

Das ist nur eine Vermutung.

    
kyoryu 21.07.2009 03:29
quelle
0

Als versiegelt When applied to a class, the sealed modifier prevents other classes from inheriting from it.

hier versuche ich euch eins nach dem anderen zu erklären:

%Vor%

es gibt Ihnen eine Warnung, weil es praktisch keinen Sinn macht, denn nachdem Sie eine Klasse als versiegelt deklariert haben, können Sie sie nicht erben und Ihre Methode ist protected , so dass Sie nicht außerhalb der Klasse mit ihrem Objekt darauf zugreifen können (und behalten Beachten Sie auch, dass Sie keine untergeordnete Klasse erstellen können, so dass Sie diese Methode auch nicht mit diesem Trick verwenden können.) So macht es praktisch keinen Sinn protected zu machen, damit der Compiler Sie warnt, aber wenn Sie es machen es als public oder internal dann gibt es keinen Fehler, weil es in diesem Fall nützlich ist.

jetzt der zweite:

%Vor%

Wie Sie Ihre Klasse versiegelt haben und nun machen Sie Ihre Methode so virtuell, dass Sie indirekt jemandem ein Angebot zum Überschreiben geben, und das kann nur durch Vererbung möglich sein und hier kommt das Problem. Ihre Klasse ist also versiegelt kann mit dieser Klasse keine Vererbung durchführen. Deshalb gibt es mit virtual einen Fehler.

Ich hoffe, es wird Ihnen helfen, zu verstehen.

als Referenz Ссылка

    
Peeyush 08.12.2011 18:29
quelle
0

Wenn ein neues geschütztes Member deklariert wird, bedeutet dies, dass dieses Member mit untergeordneten Klassen geteilt werden soll. Eine versiegelte Klasse kann keine Nachkommen haben. Ein neues geschütztes Mitglied zu deklarieren ist also ein bisschen ein Oxymoron, genauso wie es eine neue virtuelle Methode in einer versiegelten Klasse deklariert.

Warum virtual einen Fehler erzeugt, während protected nur eine Warnung erzeugt, kann ich nur spekulieren, dass es vielleicht damit zu tun hat, dass neue virtuelle Methoden es erfordern, dass der Compiler Datenstrukturen für den Typ (eine vtable) erstellt Neue geschützte Mitglieder haben nur ein Zugriffs-Flag gesetzt - keine neue Datenstruktur. Wenn der Compiler keine vtable für eine versiegelte Klasse erstellen darf, was sollte er tun, wenn er auf eine neue virtuelle Methode trifft? Fehler beim Kompilieren Eine neue geschützte Methode in einer versiegelten Klasse ist sinnlos, erfordert jedoch nicht, dass der Compiler in verbotenes Gebiet vordringt.

    
dthorpe 08.12.2011 18:54
quelle

Tags und Links