it-swarm.com.de

Warum ist 'void' als generischer Typ in C # nicht zulässig?

Was waren die Entwurfsentscheidungen, die dafür sprachen, dass void nicht konstruierbar und als generischer Typ nicht zulässig ist? Immerhin ist es nur ein spezielles leeres struct und hätte die gesamte PITA vermieden, unterschiedliche Func und Action Delegierte zu haben.

(C++ erlaubt explizite void Rückgaben und erlaubt void als Vorlagenparameter)

53
user23157

Das grundlegende Problem mit "void" ist, dass es nicht dasselbe bedeutet wie jeder andere Rückgabetyp. "void" bedeutet "wenn diese Methode zurückgibt, gibt sie überhaupt keinen Wert zurück." Nicht null; null ist ein Wert. Es wird überhaupt kein Wert zurückgegeben.

Dies bringt das Typensystem wirklich durcheinander. Ein Typsystem ist im Wesentlichen ein System, um logische Schlussfolgerungen darüber zu ziehen, welche Operationen für bestimmte Werte gültig sind. Eine void-Rückgabemethode gibt keinen Wert zurück, daher die Frage "Welche Operationen sind für dieses Ding gültig?" mache überhaupt keinen Sinn. Es gibt kein "Ding" für eine Operation, die gültig oder ungültig ist.

Darüber hinaus bringt dies die Laufzeit etwas heftig durcheinander. Die .NET-Laufzeit ist eine Implementierung des virtuellen Ausführungssystems, das als Stapelmaschine angegeben ist. Das heißt, eine virtuelle Maschine, bei der alle Vorgänge hinsichtlich ihrer Auswirkung auf einen Bewertungsstapel charakterisiert sind. (In der Praxis wird die Maschine natürlich auf einer Maschine mit Stapel und Registern implementiert, aber das virtuelle Ausführungssystem nimmt nur einen Stapel an.) Der Effekt eines Aufrufs einer void-Methode ist grundsätzlich anders als die Auswirkung eines Aufrufs einer nicht ungültigen Methode; Bei einer nicht leeren Methode wird immer etwas auf den Stapel gelegt, das möglicherweise entfernt werden muss. Eine void-Methode legt niemals etwas auf den Stapel. Daher kann der Compiler nichtige und nicht leere Methoden nicht gleich behandeln, wenn der zurückgegebene Wert der Methode ignoriert wird. Wenn die Methode ungültig ist, gibt es keinen Rückgabewert, daher darf kein Pop vorhanden sein.

Aus all diesen Gründen ist "void" kein Typ, der instanziiert werden kann. es hat keine Werte , das ist der springende Punkt. Es ist nicht in ein Objekt konvertierbar, und eine Methode zur Rückgabe von Leeren kann niemals polymorph mit einer Methode zur Rückgabe von Leeren behandelt werden, da dies den Stapel beschädigt!

Daher kann void nicht als Typargument verwendet werden, was, wie Sie bemerken, eine Schande ist. Es wäre sehr praktisch.

Im Nachhinein wäre es für alle Beteiligten besser gewesen, wenn anstelle von nichts automatisch eine Methode zur Rückgabe von Leeren "Unit" zurückgegeben hätte, einen magischen Singleton-Referenztyp. Sie würden dann wissen, dass jeder Methodenaufruf etwas auf den Stapel legt, Sie würden wissen, dass jeder Methodenaufruf etwas zurückgibt, das einer Variablen vom Objekttyp zugewiesen werden könnte =, und natürlich Unit könnte als Typargument verwendet werden, sodass keine separaten Delegatentypen für Action und Func erforderlich wären. Leider ist das nicht die Welt, in der wir uns befinden.

Weitere Gedanken in diesem Sinne finden Sie unter:

69
Eric Lippert

Von: http://connect.Microsoft.com/VisualStudio/feedback/details/94226/allow-void-to-be-parameter-of-generic-class-if-not-in-c-then- just-in-runtime

Dies ist eigentlich beabsichtigt - wir erlauben keine Instanz des void-Typs (zusammen mit vielen anderen Typen in der Laufzeit). Sie können auch keine Leere oder Leere [] erstellen. Wir haben diese Löcher aus Sicherheitsgründen verstopft.

Ich kann für mein ganzes Leben nicht sehen, wie leer eine Sicherheitslücke ist, aber ... so heißt es.

9
Winston Ewert