Quelle était la logique de conception pour faire de null pas un type primitif?

Lors de l’utilisation de reflection, Type.IsPrimitive sur un type void renvoie false.Coming venant d’un arrière-plan C ++, cela était surprenant.

L’examen de la spécification C # 6.0 (Page 82) ne mentionne pas le type de void , ce qui peut signifier qu’il n’est pas catégorisé comme un type.

Existe-t-il quelque chose dans les spécifications de langage ou autrement qui catégorise le void comme autre chose. Ou toute autre discussion ou telle qui mentionne la raison derrière cela?

Pourquoi n’est pas vide un type primitif? Parce que ce n’est pas quelque chose que vous pouvez instancier. Ce n’est pas un type primitif, ni un type de référence. Ce n’est rien du tout.

Eric Lippert décrit quelques “problèmes” avec le type de vide dans ce post sur le génie logiciel , qui décrit les spécificités de void tant que type à utiliser dans les delegates et les Action :

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.

En faire un type primitif void la signification et le but particuliers de void dans le VES (Virtual Execution System), comme l’explique Eric plus tard:

L’effet d’un appel vers une méthode de vide est fondamentalement différent de l’effet d’un appel vers une méthode de non-vide; une méthode non-vide place toujours quelque chose sur la stack, qu’il peut être nécessaire de supprimer. Une méthode vide ne met jamais quelque chose sur la stack.

Rendre void un type primitif enfreint cette règle, bien que vous puissiez argumenter sur son utilité, comme Eric l’explique plus loin dans l’article cité en référence.

void n’est pas un type, c’est un mot clé . Comme en C ++, cela signifie exactement la même chose. Les mots clés jouent un rôle important dans une langue, ils ne peuvent apparaître qu’à certains endroits et l’parsingur est autorisé à faire des suppositions difficiles quant à l’intention du programmeur.

Le rôle principal consiste à générer de bons messages d’erreur. Évident sur une déclaration comme return 42; Dans une méthode déclarée nulle, vous obtenez un message d’erreur très clair: “Hé, vous avez dit que rien ne sera retourné”. Ce qui est moins évident, c’est qu’ils sont très utiles pour remédier aux erreurs de syntaxe élémentaires. Une accolade manquante } par exemple, est une erreur assez difficile à récupérer. Lorsque l’parsingur rencontre un void lors de l’parsing d’un corps de méthode, il peut réinitialiser l’état de l’parsingur et générer à nouveau des messages d’erreur corrects.

Le fait que le type System.Void existe est une bizarrerie liée aux métadonnées. L’équivalent approximatif d’un fichier .h en C ++. Ils existent principalement pour traiter les ressortingctions techniques en C ++, il n’a pas de concept de modules, il utilise un modèle de compilation en un seul passage et exige que les déclarations apparaissent toujours avant les définitions. Un travail assez pénible en C ++, bien que les outils d’édition puissent aider un peu. Aucune ressortingction de ce type en C #, le compilateur génère la déclaration à partir de la définition.

Les métadonnées décrivent une méthode en détail, stockée dans les enregistrements MethodDef et MethodDefSig des métadonnées. Les concepteurs du CLR auraient pu exprimer la notion de “cette méthode ne renvoie pas de données” de deux manières. Un moyen évident est qu’ils auraient pu utiliser un peu dans l’ énumération MethodAtsortingbutes , quelque chose comme “HasNoReturnValue”. Toutefois, étant donné que de nombreuses méthodes ont un type de retour non nul et que leur espace est réservé dans l’enregistrement MethodDefSig, elles ont simplement choisi une valeur sentinelle comme type de retour. System.Void.

Réfléchir sur le type System.Void n’est généralement pas utile. De manière réaliste, ils auraient pu choisir n’importe quelle valeur pour IsPrimitive et cela n’aurait fait aucune différence. False était un choix logique, il ne décrit pas un type.

À la lecture de la spécification C #, il n’est fait aucune mention d’un type void . Il est écrit en tant que return type . Dans la table des matières, il n’est pas classé dans les types référence ou valeur. Il est mentionné en tant que mot clé.

La section sur la fonction typeof dit:

La troisième forme de typeof-expression consiste en un mot-clé typeof suivi d’un mot-clé void entre parenthèses. Le résultat d’une expression de cette forme est l’object System.Type qui représente l’absence d’un type. L’object type renvoyé par typeof (void) est distinct de l’object type renvoyé pour tout type. Cet object de type spécial est utile dans les bibliothèques de classes permettant de réfléchir sur les méthodes du langage. Ces méthodes souhaitent pouvoir représenter le type de résultat de toute méthode, y compris les méthodes void, avec une instance de System.Type.

Ce qui pour moi indique que void a un type associé mais n’est utilisé que dans le cas où vous souhaitez que la reflection vous donne quelque chose de tangible à cause du système de type. Sinon, void est juste un mot clé.