Le problème fondamental de "vide" est que cela ne signifie pas la même chose que tout autre type de retour. "void" signifie "si cette méthode retourne, alors elle ne renvoie aucune valeur." Non nul; null est une valeur. Il ne renvoie aucune valeur que ce soit.
Cela bousille vraiment le système de types. Un système de types est essentiellement un système permettant de déduire logiquement 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 pas de "chose" pour qu'une opération soit valide, valide ou invalide.
De plus, cela gâche quelque chose de féroce au moment de l'exécution. Le runtime .NET est une implémentation du système d'exécution virtuel, spécifié en tant que machine à 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 entendu, dans la pratique, la machine sera mise en œuvre sur une machine avec à la fois une pile et des registres, mais le système d'exécution virtuel suppose uniquement une pile.) L'effet d'un appel à une méthode void est fondamentalementdifférent de l'effet d'un appel à une méthode non nulle; une méthode non-vide place toujours quelque chose sur la pile, qu'il peut être nécessaire de supprimer. Une méthode vide ne met jamais quelque chose sur la pile. Et par conséquent, le compilateur ne peut pas traiter les méthodes vide et non vide 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, "vide" n'est pas un type pouvant être instancié; il n'a pas de valeurs , c'est tout son propos. Il n'est pas convertible en objet et une méthode de renvoi vide ne peut jamais, jamais être traitée de manière polymorphe avec une méthode de renvoi non 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 tous les intéressés si au lieu de rien, une méthode de renvoi de vide renvoyait automatiquement "Unit", un type de référence de singleton magique. Vous saurez alors que chaque appel de méthode place quelque chose sur la pile , vous saurez que chaque appel de méthode retourne quelque chose qui pourrait être affecté à une variable de type objet et que, bien entendu, Unit pourrait être utilisé comme argument de type . pas besoin d'avoir des types de délégués Action et Func séparés. Malheureusement, ce n'est pas le monde dans lequel nous sommes.
Pour d'autres réflexions dans ce sens, voir: