10
votes

Puisque Int32 est un type de valeur, pourquoi hérite-t-il .Tostring ()?

Ce sont les documents sur .tostring () < / code> qui a suscité cette question. Ils indiquent:

Parce que l'objet est la classe de base de tous les types de référence dans le .NET. Cadre, ce comportement [.Tostring ()] est hérité par des types de référence qui ne font pas remplacer la méthode de tostring.

Encore plus sur elle va à l'état:

Par exemple, les types de base tels que CHAR, INT32 et String fournissent des implémentations de tosturer

Cependant, int32 est une structure structure et donc doit être un type type . .

Alors qu'est-ce qui se passe ici? Est-ce que INT32 met en œuvre c'est propre .Tostring () qui n'a rien à voir avec l'objet?


5 commentaires

Je suis à peu près sûr que cela a à voir avec la boxe.


Forums. asp.net/t/1694055.aspx/...


@MBEN Je suis à peu près sûr que la question et la réponse n'ont rien à voir avec la boxe.


On sonne comme peut-être que vous êtes confus sur la manière dont il est qu'un type de valeur peut hériter d'un type de référence, qui est un peu comme étant confus sur la manière dont vous pouvez mettre une boîte rouge dans une boîte bleue - vous ne pouvez sûrement pas mettre des boîtes bleues Dans d'autres cases bleues, non? Non, vous pouvez mettre une boîte rouge dans une boîte bleue, et vous pouvez également dériver une valeur de valeur d'un type de référence. Cela pourrait aider: blogs.msdn. COM / B / ERICLIPPERT / Archive / 2011/09/19 / ...


Notez que la documentation que vous indiquez indique que " objet est la classe de base de tous les types de référence dans le cadre .NET." Cependant, cela n'implique pas que tout ce qui a objet dans sa hiérarchie d'héritage est un type de référence. (Tous les chats sont dans la classe Mammalia mais pas toutes les espèces de la classe Mammalia sont des chats.) Il est parfaitement légal pour un type de valeur à hériter d'un type de référence, et En fait, tous struct provenant de ValueType (Type de référence) `et Valuetype dérive de objet .


6 Réponses :


11
votes

oui, int32 remplace tostring ... Bien que c'est un peu non négligeant ici. tous les types hériter des membres de objet - vous pouvez toujours appel tostring () , vous pouvez toujours appel est égal à etc. ( valueltype remplace est égal à et gethascode pour vous, bien que vous devriez presque toujours les remplacer plus loin dans les structures pour fournir une implémentation plus efficace.)

Notez que vous pouvez remplacer les méthodes très facilement: xxx

Ce n'est pas clair que l'aspect est confus (Il y a plusieurs domaines différents impliqués ici). Si vous pouviez clarifier, nous pourrions aborder le problème spécifique.


9 commentaires

Je suppose qu'il est confondu avec le fait, que les types de valeur se comportent comme des types de valeur mais héritent d'un objet, qui est une classe et donc un type de référence ..


@Andreasniedermair: Plus que cela, ils héritent de valueltype qui est lui-même une classe :)


Jup, sachez que, je voulais juste que ce soit très droit :)


Merci Jon - C'était votre article sur la valeur + Types de référence qui m'a fait commencer à penser à cela. La confusion réside dans l'énoncé L'objet est la classe de base de tous les types de référence et hérite d'où hériter .tostring alors pourquoi int32 héritez-t-il aussi?


Être la classe de base pour tous les types de référence ne signifie pas qu'il ne peut pas être dans la hiérarchie de l'héritage pour tous les types de valeur.


Voir mon commentaire @ Stackoverflow.com/questions/8152761/...


@ m.edmondson, voir ici pour l'objet Type de valeur hiérarchie.


@Jonskeet - alors y a-t-il quelque chose de spécial sur system.valuetype qui signifie que le CLR traite-t-il différemment?


@ M.EDMONDSON: Oui - Le CLR sait sur System.ValueType et system.enum . Ce sont des types très spéciaux.



13
votes

int32 est une structure et donc un type de valeur. Mais:

System.Object
   System.ValueType
      System.Int32


7 commentaires

Avez-vous déjà vu une déclaration de structure comme Structure publique FOO: System.Object ...? Je me demande comment ils obtiennent cela pour compiler :) Si vous avez déjà décompilé System.int32 Vous obtiendrez Public Struct int32: Icomarable, Iformattable, Iconvertible, Icomparable , IEQUABLE ... mais toujours ayant un baseType system.valueType ... étrange, n'est-ce pas?


Excellent cela m'a aidé à comprendre - alors y a-t-il quelque chose de spécial sur system.valuetype qui rend la manipulation d'exécution il est différente?


@ m.edmondson c'est la partie que je n'ai jamais compris ni ... Je devinez Il est spécial par le CLR ... Je pense que le livre de spécification .NET-CLR-CLR-SPÉCIFICATION DE MICROSOFT (STH Ceci: Amazon.de/Programmer-Language-Couverture-Microsoft-Devopmen T / ... ) couvrira cette magie :)


Je pense que ce serait pratique est @jon pourrait élaborer à ce sujet!


@Andreasniedermair: Qu'est-ce que c'est précisément que vous vous demandez? Je vous assure qu'il n'y a rien de magique à ce sujet; C'est un compilateur simple.


@Andreas Niedermair: Ce n'est pas légal par la spécification. La spécification sort exactement que vous ne pouvez pas extraire explicitement de System.valueType et qu'il existe un mot spécial réservé struct qui l'accomplit et que lorsque vous l'utilisez pour marquer. Une définition de type, vous ne pouvez répertorier que les interfaces que le type implémente, mais pas une classe de base (à nouveau, elle dérive implicitement de System.valueType ).


@ Ericlippert @jason l'a eu droit! ... Le mot clé struct implique system.valueType ... merci @jason!



0
votes

Les docs sont faux. Les deux types de référence et de valeur héritent de ce comportement de l'objet (mais rappelez-vous que tout dans .NET est une classe qui dérive de l'objet ).

Tous (la plupart?) Types de valeur de base (la plupart?) Remplacer la totring () pour renvoyer quelque chose de plus sensible que le nom de la classe.


9 commentaires

La documentation citée ci-dessus est correcte. Pourquoi croyez-vous que c'est incorrect?


@ERIC LIPPERT: Si les types de valeur héritent de l'appréciage, cela suggérerait que l'on peut utiliser des types de valeur n'importe où n'importe où peut utiliser l'appréciage. Cela ne fonctionne pas, cependant: l'appréciage satisfait à une contrainte de classe, mais pas à une contrainte de structure, alors que les types de valeur répondent à une contrainte de structure, mais pas à une contrainte de classe. Si on attribue une struct avec une interface de mutation (par exemple, la liste énumérateur) à une variable de type valuetype , la variable résultante se comportera comme un type de classe mutable, plutôt que Type de valeur mutable.


@supercat: Il y a un peu d'erreur logique dans votre argument. Si une structure h hérite de l'appréciage, on s'attend à ce que (1) tous les membres de l'appréciation soient également des membres de S; C'est la définition de "héritage". Et (2) qu'une valeur de type S peut être attribuée à une variable de type valeur de type (dans ce cas, via une conversion de boxe). Mais ce sont les deux faits sur instances de S. il n'y a aucune obligation que le type s soit utilisable partout où le type valeur de type peut légalement être utilisé .


@supercat: Pensez-y de cette façon: une pomme est une sorte de fruit. Si vous avez un bol pouvant contenir des fruits, ce bol peut contenir une pomme; Les pommes sont compatibles avec des fruits. Tous les fruits ont une propriété "goût"; Les pommes ont cette propriété parce qu'elles sont des fruits. Les pommes héritent des propriétés des fruits. Mais cela ne signifie pas que vous pouvez substituer le mot "pomme" partout où le mot fruit apparaît et préservez la vérité d'une phrase! "Le mot" fruit "commence par la lettre" F "" ne peut être substitué par "pomme" et préserver sa vérité.


@ERICLIPPERT: La conversion d'un type de valeur non comprimé à l'appréciation est une conversion à changement de représentation. La conversion d'un type de valeur boxée à l'appréciation est la préservation de la représentation. À mon avis, cela suggérerait que les "types de valeur boxée" sont des objets de type classe de classe qui héritent d'un appréciage, mais des innors ne sont pas. Au lieu de cela, ils sont implicitement convertibles aux types de valeur en boîte, qui héritent d'appréhension. La ride est qu'une demande de code JIT qui fonctionnerait avec un paramètre, une variable ou un champ dérivé de l'appréciation ...


@ Ericlippert: ... produira du code qui manipule l'entité directement plutôt que via une référence de tas. Comme j'y pense, je suis un peu impressionné par les personnes .NET 2.0 qui ont réussi à faire fonctionner des génériques aussi bien qu'ils le font. Il serait peut-être intéressant de penser à la manière dont les choses auraient pu avoir travaillé s'il y avait eu un moyen d'organiser des objets de référence de la valeur de la valeur de la valeur de la valeur (ce qui signifie qu'une copie ne pouvait pas simplement être blive, mais elle devrait de copier récursivement les références de tas imbriqués étaient censés avoir une sémantique de valeur), mais cela aurait plus de choses compliquées.


@ERIFLIPPERT: Je suppose que ma plus grande confusion est la suivante: comment décrire le type de ce qui est transmis à un paramètre, pour distinguer les types de valeur en boîte de types de valeur réelle. Mon inclination serait de considérer les variables / champs / paramètres des types de valeur comme étant en dehors du système de type. Envisager d'appeler bool f (T bar) où T: ienumerator {return bar.movenext ();} avec une variable de type liste.Enumerator ou une variable de type ienumerator qui détient une liste.Enumerator . Comment décririez-vous le type de l'instance passée dans bar dans chaque cas?


@supercat: vous êtes déroutant Héritage avec Compatibilité d'affectation . héritage est la propriété de types que les membres d'un type de base sont également membres d'un type dérivé; L'héritage n'a rien à voir avec la façon dont les bits regardent en mémoire. Un type de valeur non poxed n'est pas compatible avec une variable de type valeur de type, mais le type de valeur hérite toujours de tous les membres de sa classe de base.


@ERIFLIPPERT: Une valeur non comprimée peut être attribuée à l'un des valeurs valorisés sans une typast explicite (bien que vice-versa).



0
votes

Je pense que la réponse courte à votre question est que les types de valeur hériter de System.ValueType et cela hérite d'un objet.


0 commentaires

0
votes

Tous les struct ont héritage à partir de System.ValueType Class (non autorisé) qui est effectué uniquement par le compilateur. Tous les struct ont des méthodes à partir de ValueType Classe de base qui est héritée à partir de Object Classe nous permet d'accéder à Tostring () et tous les autres.

Même si Valuetype est hérité de objet , mais il a une mise en œuvre spéciale des substitutions.


0 commentaires

5
votes

Peut-être que votre confusion découle de ne pas réaliser que les types de valeur hériter de objet ? Voici le graphique d'héritage de system.Object , system.valueType , system.int32 et myNamespace.customer qui est censé être une classe de votre propre fabrication. J'étais paresseux et je n'ai pas écrit toutes les méthodes publiques et interfaces de int32 .

uml

Tostring est déclaré dans objet mais est survolée à la fois dans valeur de type et dans int32 . .


0 commentaires