web-dev-qa-db-fra.com

Pourquoi 'void' n'est pas autorisé en tant que type générique en C #

Quelles ont été les décisions de conception qui ont plaidé en faveur du fait que void n'était pas constructible et n'était pas autorisé en tant que type générique? Après tout, ce n'est qu'un struct spécial vide et aurait évité le PITA total d'avoir des délégués Func et Action distincts.

(C++ autorise les retours explicites de void et autorise void comme paramètre de modèle)

53
user23157

Le problème fondamental avec "void" est qu'il ne signifie pas la même chose que tout autre type de retour. "void" signifie "si cette méthode retourne alors elle ne retourne aucune valeur du tout." Pas nul; null est une valeur. Il ne renvoie aucune valeur.

Cela gâche vraiment le système de type. Un système de type est essentiellement un système permettant de faire des déductions logiques sur les opérations valides sur des valeurs particulières; une méthode de retour vide ne renvoie pas de valeur, donc la question "quelles opérations sont valides sur cette chose?" ça n'a aucun sens. Il n'y a aucune "chose" pour qu'il y ait une opération, valide ou invalide.

De plus, cela gâche quelque chose de féroce à l'exécution. Le runtime .NET est une implémentation de Virtual Execution System, qui est spécifié en tant que machine de pile. C'est-à-dire une machine virtuelle où les opérations sont toutes caractérisées en termes d'effet sur une pile d'évaluation. (Bien sûr, en pratique, la machine sera implémentée sur une machine avec à la fois une pile et des registres, mais le système d'exécution virtuel ne suppose qu'une pile.) L'effet d'un appel à une méthode void est fondamentalement différent de l'effet d'un appel à une méthode non nulle; une méthode non vide met toujours quelque chose sur la pile, qui pourrait avoir besoin d'être sauté. Une méthode void ne met jamais quelque chose sur la pile. Et par conséquent, le compilateur ne peut pas traiter les méthodes vides et non vides de la même manière dans le cas où la valeur renvoyée par la méthode est ignorée; si la méthode est vide alors il n'y a pas de valeur de retour donc il ne doit pas y avoir de pop.

Pour toutes ces raisons, "void" n'est pas un type qui peut être instancié; il n'a aucune valeur , c'est tout son point. Ce n'est pas convertible en objet, et une méthode de retour vide ne peut jamais, jamais être traitée de manière polymorphe avec une méthode qui ne retourne pas de vide car cela corrompt la pile!

Ainsi, void ne peut pas être utilisé comme argument de type, ce qui est dommage, comme vous le constatez. Ce serait très pratique.

Avec le recul, il aurait été préférable pour toutes les parties concernées que, au lieu de rien du tout, une méthode de retour de vide renvoie automatiquement "Unit", un type de référence singleton magique. Vous sauriez alors que chaque appel de méthode met quelque chose sur la pile , vous sauriez que chaque appel de méthode retourne quelque chose qui pourrait être assigné à une variable de type d'objet , et bien sûr Unit pourrait être utilisé comme argument de type , donc il ne serait pas nécessaire d'avoir des types délégués Action et Func séparés. Malheureusement, ce n'est pas le monde dans lequel nous vivons.

Pour plus de réflexions dans cette veine, voir:

69
Eric Lippert

De: http://connect.Microsoft.com/VisualStudio/feedback/details/94226/allow-void-to-be-parameter-of-generic-class-if-not-in-c-then- juste à l'exécution

C'est en fait par conception - nous n'autorisons aucune instance du type void (ainsi que de nombreux autres types dans le runtime). Vous ne pouvez pas non plus créer un vide ou un vide []. Nous avons bouché ces trous de type pour plus de sécurité.

Je ne peux pas pour la vie de moi voir à quel point le vide est une faille de sécurité, mais ... c'est ce que cela dit.

9
Winston Ewert