Question

6.1 Les conversions implicites définit une conversion d'identité ainsi:

  

On convertit de conversion ayant une identité de tout type au même type. Cette conversion existe telle qu'une entité qui a déjà un type requis peut être dit être convertible à ce type.

Maintenant, quel est le but des phrases telles que celles-ci?

  

(Dans §6.1.6 conversions de référence implicites)

     

Les conversions implicites de référence sont:

     
      
  • [...]
  •   
  • De toute Référence de type référence de type T si elle a une identité implicite ou de conversion référence à un type de référence T 0 et T 0 a une conversion d'identité T.
  •   

et

  

(Dans §6.1.7 conversions de boxe)

     
      
  • Un type de valeur a une conversion de la boxe à un type d'interface I si elle a une conversion de la boxe à un type d'interface I 0 et I 0 a une conversion d'identité I .
  •   

Dans un premier temps ils semblent redondants (tautologie). Mais ils doivent être là pour un but, alors pourquoi sont-ils là?

Pouvez-vous donner un exemple de deux types T 1 , T 2 tels que T 1 serait pas implicitement convertibles en T 2 s'il n'y avait pas les paragraphes? cités ci-dessus

Était-ce utile?

La solution

Section 4.7 des notes de spécification qu'il ya une conversion d'identité de Foo<dynamic> à Foo<object> et vice versa. La partie de la spécification que vous citez est écrit pour que cette affaire soit traitée. Autrement dit, s'il y a une conversion de référence implicite de T à C<object, object> puis il y a aussi une conversion de référence implicite à C<object, dynamic>, C<dynamic, object> et C<dynamic, dynamic>.

On peut raisonnablement souligner que (1) l'intention de ces phrases est non évidente - d'où votre question - et la confusion, et (2) que la section sur les conversions d'identité doivent recouper la section sur les conversions dynamiques, et ( 3) des phrases comme cela dans la marque spec, il est difficile pour un implémenteur de la spécification de traduire clairement la langue dans une spécification mise en œuvre. Comment peut-on savoir si un tel existe de type? La nécessité spec précise pas les algorithmes exacts, mais ce serait bien si elle a donné plus de conseils.

La spécification est, malheureusement, pas un document parfait.

Autres conseils

Mise à jour le 22-Sep-2010:

Je doute personne va lire en plus Timwi. Même si, je voulais faire quelques modifications à cette réponse à la lumière du fait qu'une nouvelle réponse a été acceptée et le débat se poursuit toujours (au moins dans mon monde peut-être imaginaire) si oui ou non les extraits cités de la spécification sont techniquement redondants. Je ne suis pas ajouter beaucoup, mais il est trop important pour tenir dans un commentaire. La majeure partie de la mise à jour se trouve sous la rubrique "conversion impliquant le type de dynamic" ci-dessous.


Mise à jour le 19-Sep-2010:

Dans votre commentaire:

  

[T] son ??n'a pas de sens.

Bon sang, Timwi, vous dites que beaucoup . Mais tout droit, puis; vous me avez mis sur la défensive, donc voilà!

Disclaimer: J'ai certainement pas examiné les spécifications aussi près que vous avez. Sur la base de certaines de vos questions récentes, il semble que vous avez été à la recherche dans un peu ces derniers temps. Cela va naturellement à vous rendre plus familier avec beaucoup de détails que la plupart des utilisateurs sur SO; donc cela, comme la plupart des réponses que vous êtes susceptible de recevoir de quelqu'un d'autre que Eric Lippert, ne peut pas vous satisfaire.

Différents locaux

Tout d'abord, la prémisse de votre question est que si les déclarations sont mises en évidence redondants , ils ne servent à rien fin . La prémisse de ma réponse est que les déclarations redondantes ne sont pas nécessairement sans fin si elles clarifient quelque chose qui est pas évident pour tout le monde . Ce sont des lieux contradictoires. Et si nous ne pouvons être d'accord sur les lieux, nous ne pouvons pas avoir un argument logique simple. Je vous demande simplement de repenser votre site.

Votre réponse, cependant, était de Réaffirmons votre devise: «Si les phrases sont vraiment redondantes, ils confondent que le lecteur et ne clarifient rien »

(je aime la façon dont vous vous mis en place en tant que représentant pour tous les lecteurs de la spécification, il en passant.)

Je ne peux pas vous blâmer pour la tenue de cette position, exactement. Je veux dire, il ne semble évident. Et je ne donne des exemples concrets dans ma première réponse. Donc, ci-dessous, je vais essayer d'inclure quelques exemples concrets. Mais d'abord, permettez-moi de prendre un pas en arrière et offre mon avis sur cette étrange pourquoi conversion identité concept existe dans la spécification en premier lieu.

Le but du conversion d'identité définition

À première vue, cette définition semble plutôt superflu; est pas en train de dire qu'une instance de tout type T est convertible ... eh bien, à T? Oui, ça l'est. Mais je fais l'hypothèse * que le but de cette définition est de fournir les spécifications avec le vocabulaire propre à utiliser le concept de identité de type dans le contexte de la discussion conversions .

Cela permet des déclarations au sujet des conversions qui sont transitifs essentiellement dans la nature. Le premier point que vous avez cité la spécification comme un exemple d'une déclaration tautologique tombe dans cette catégorie. Il dit que si une conversion implicite est définie pour un certain type (je vais l'appeler K) à un autre type T 0 et T 0 a une conversion d'identité T, K est implicitement convertible en T. Par la définition de conversion d'identité donnée ci-dessus, « a une conversion d'identité » signifie vraiment « est du même type que. » Donc, la déclaration est redondante .

Mais encore une fois: conversion d'identité définition existe en premier lieu pour équiper la spécification d'un langage formel pour décrire conversions sans avoir à dire des choses comme « si T < sub> 0 et T sont vraiment le même type. "

OK, le temps pour des exemples concrets.

Lorsque l'existence d'une conversion implicite peut ne pas être évidente à certains développeurs

Remarque: beaucoup mieux par exemple a été fourni par Eric Lippert dans sa réponse à la question . Je laisse ces deux premiers exemples comme renforts mineures de mon point. J'ai également ajouté un troisième exemple que la conversion concrétise l'identité qui existe entre object et dynamic comme indiqué dans la réponse d'Eric.

transitive conversion de référence

Soit s que vous avez deux types, M et N, et vous avez une conversion implicite définie comme ceci:

public static implicit operator M(N n);

Ensuite, vous pouvez écrire du code comme ceci:

N n = new N();
M m = n;

Maintenant, disons que vous avez un fichier avec cette déclaration de using en haut:

using K = M;

Et puis vous avez, plus tard dans le fichier:

N n = new N();
K k = n;

OK, avant de poursuivre, je me rends compte que est évidente à et me . Mais ma réponse est, et a été de le début, qu'il pourrait pas évident pour tous , et donc spécifiant - tandis que redondants - a encore but .

Ce fin est: faire comprendre à quelqu'un gratter sa tête, regardant ce code, il est légal. Un conversion implicite existe de N à M, et un conversion ayant une identité existe de M à K (à savoir, M et K sont du même type); donc une conversion implicite existe de N à K. Il n'est pas juste logique (bien qu'il puisse être logique); il est là dans la spécification . Sinon, on pourrait croire à tort que quelque chose comme ce qui suit serait nécessaire:

K k = (M)n;

De toute évidence, ce n'est pas.

transitive conversion boxe

Ou prendre le int type. Un int peut être emballé comme IComparable<int>, non? Donc, cela est légal:

int i = 10;
IComparable<int> x = i;

Maintenant considérez ceci:

int i = 10;
IComparable<System.Int32> x = i;

Encore une fois, yes , il peut être évident pour vous, moi, et 90% de tous les développeurs qui pourraient jamais venir à travers elle. Mais pour cette minorité mince qui ne voient pas tout de suite: conversion de boxe existe de int à IComparable<int>, et un conversion d'identité existe de IComparable<int> à IComparable<System.Int32> (c.-à-IComparable<int> et IComparable<System.Int32> sont du même type); donc une conversion de boxe existe de int à IComparable<System.Int32>.

Conversion impliquant le type de dynamic

Je vais emprunter à mon exemple de conversion de référence ci-dessus et juste modifier légèrement pour illustrer la relation d'identité entre object et dynamic dans la version 4.0 de la spécification.

Disons que nous avons les types M<T> et N, et ont défini quelque part la conversion implicite suivante:

public static implicit operator M<object>(N n);

Alors ce qui suit est légal:

N n = new N();
M<dynamic> m = n;

, ce qui précède est clair que beaucoup moins évidentes que les deux exemples précédents. Mais voici la question à un million de dollars: Est-ce que ci-dessus toujours légal même si les extraits de la spécification citée dans la question n'existait pas (je vais appeler ces extraits Q par souci de concision.) Si la réponse est oui, alors Q est en fait redondant. Si non, alors il est pas.

Je crois que la réponse est oui.

Considérez la définition de conversion d'identité , défini à l'article 6.1.1 (je suis notamment toute la section ici car il est assez court):

  

On convertit de conversion ayant une identité de tout type au même type. Cette conversion existe telle qu'une entité qui a déjà un type requis peut être dit être convertible à ce type.

     

Parce que object et dynamic sont considérés comme équivalences il y a une conversion d'identité entre object et dynamic, et entre les types construits qui sont les mêmes pour remplacer toutes les occurrences de dynamic avec object . [Souligné]

(Cette dernière partie est également inclus dans la section 4.7, qui définit le type de dynamic).

Maintenant, regardons à nouveau le code. En particulier, je suis intéressé par cette seule ligne:

M<dynamic> m = n;

La légalité de cette déclaration (sans tenir compte Q - rappelez-vous, la question en cours de discussion est la légalité hypothétique de la déclaration ci-dessus si Q a fait pas exist), depuis M<T> et N sont des types personnalisés, dépend de l'existence d'une conversion implicite définie par l'utilisateur entre N et M<dynamic>.

Il existe une conversion implicite de N à M<object>. Par la section de la spécification citée ci-dessus, il y a une conversion d'identité entre M<object> et M<dynamic>. Par la définition de conversion d'identité , M<object> et M<dynamic> sont le même type .

Alors, comme dans les deux premiers (les plus évidents) exemples, je crois qu'il est vrai qu'une conversion implicite existe de N à M<dynamic> même sans prendre Q en compte , tout comme il est vrai qu'une conversion implicite existe de N à K dans le premier exemple et qu'une conversion de boxe existe de int à IComparable<System.Int32> dans le second exemple.

Sans Q , ce qui est beaucoup moins évident (donc Q existence d '); mais cela ne rend pas false (par exemple, Q ne sont pas nécessaires pour ce comportement à définir). Il est tout simplement moins évident.

Conclusion

je l'ai dit dans ma première réponse que ce soit l'explication « évidente », parce qu'il me semblait que vous aboyer le mauvais arbre. Vous d'abord posé ce défi:

  

Pouvez-vous donner un exemple de deux types T 1 , T 2 tels que T 1 ne serait pas implicitement convertible en T 2 s'il n'y avait pas les paragraphes cités ci-dessus?

Personne ne va relever ce défi, Timwi, parce qu'il est impossible. Prenez le premier extrait sur les conversions de référence. Il dit qu'un type K est implicitement convertible à un type T si elle est implicitement convertible en T 0 et T 0 est le même que T. Déconstruire cela, mettre retour ensemble, et vous vous retrouvez avec une tautologie évidente: K est implicitement convertible en T si elle est implicitement convertible en T. est-ce que cela peut introduire de nouvelles conversions implicites? Bien sûr que non.

Alors peut-être le commentaire de Ben Voigt était correct; peut-être ces points que vous poser des questions sur aurait été mieux placé en bas de page, plutôt que dans le corps du texte. Dans tous les cas, il est clair pour moi qu'ils sont redondants, et ainsi commencer par la prémisse ils ne peuvent pas être redondants, sinon ils ne seraient pas là est à se lancer a confié une mission d'un fou. Soyez prêt à accepter qu'une déclaration redondante peut encore faire la lumière sur un concept qui peut ne pas être évident pour tout le monde, et il deviendra plus facile d'accepter ces déclarations pour ce qu'ils sont.

redondante? Oui. Tautologie? Oui. Inutile? Dans my avis, non.

* De toute évidence, je n'ai pas participé à la rédaction de la spécification du langage C #. Si je l'ai fait, cette réponse serait beaucoup plus autoritaire. Comme il est, il représente tout simplement faible tentative d'un gars à faire sens d'un document assez complexe.


Réponse originale

Je pense que vous êtes (peut-être intentionnellement) donnant sur la plus réponse évidente ici.

Tenez compte de ces deux phrases dans votre question:

  

(1) Dans un premier temps, ils semblent redondants   (Tautologie). (2) Mais ils doivent être là   dans un but, alors pourquoi sont-ils là?

Pour moi, l'implication de ces deux phrases est ainsi qu'une déclaration tautologique ne sert à rien. Mais juste parce qu'une déclaration découle logiquement des prémisses établies, qui ne le rend pas évident pour tout le monde. En d'autres termes, même si (1) est vrai, la réponse à (2) peut être simplement: pour rendre le comportement décrit clairement à tous ceux qui lisent la spécification .

On pourrait soutenir que même si quelque chose n'est pas évident , il ne reste pas sa place dans un cahier des charges si elle fournit une définition redondante. A cette objection potentielle, je ne peux que dire: être réaliste. Ce n'est pas vraiment pratique (à mon avis) à peigne dans un document de décapage sur toutes les déclarations qui sont faits indiquant simplement auraient pu être déduites des déclarations antérieures.

Si ce étaient une pratique courante, je pense que vous pouvez trouver beaucoup de littérature là-bas - pas seulement les spécifications, mais les documents de recherche, des articles, des livres, etc. - serait un beaucoup plus courte, plus dense et plus difficile à comprendre.

Alors oui, peut-être qu'ils sont redondants. Mais cela ne nie pas leur but.

  

Un convertis de conversion d'identité   tout type au même type . Cette   conversion existe telle que une entité   qui a déjà un type requis peut   être considéré comme convertible en ce que   le type.

Ce que dit en C # -land, 1 == 1; un chat est un chat. Ceci est la base de l'affectation d'une référence d'objet à une variable du même type; si une variable de type T1 et T2 un typé sont en réalité les deux pique, il est possible d'assigner un à l'autre sans avoir explicitement jeté un comme Spade. Imaginez une variante C # où les affectations ont dû ressembler à ceci:

Spade mySpade = new Spade();
Spade mySpade2;

mySpade2 = (Spade)mySpade; //explicit cast required

En outre, une « identité » en mathématiques indique que l'expression qui évalue un résultat donné un ensemble d'entrées est équivalente à une autre expression qui produit le même résultat donné les mêmes entrées. Dans la programmation, cela signifie que l'expression ou la fonction qui renvoie une instance d'un type qui équivaut à ce type, sans conversion explicite. Si cela ne tient pas, le code suivant serait nécessaire:

public int myMethod() { /*Do something*/ }
...
int myInt = (int)myMethod(); //required even though myMethod() evals to an int.
...
int myInt = (int)(1 + 2); //required even though 1, 2, and 1+2 eval to an int.

La deuxième règle dit essentiellement que d'un type de valeur peut être affectée à une variable membre d'une classe si, en partie, la variable membre (un type encadré par définition, comme conteneur est un type de référence) est déclaré être le même type. Si cette règle n'a pas été spécifiée, théoriquement, une version de C # pourrait exister dans quels types de valeurs pures devraient être explicitement converties analogique de référence afin d'être stocké en tant que variable membre d'une classe. Imaginez, par exemple, une version de C # dans lequel les types de mot-clé bleu (int, float, décimal) et les noms de classe bleu clair (Int32, flotteur, décimal) fait référence à deux très différents, les types ne-explicitement convertibles et int , flotteur, décimal etc. étaient pas légal que les types de variables membres parce qu'ils ne sont pas les types de référence:

public class MyClass
{
  Int32 MyBoxedValueType; //using "int" not legal
}

...

MyClass myClass = new MyClass();
int theInt = 2;

myClass.MyBoxedValueType = (Int32)theInt; //explicit cast required

Je sais que cela semble stupide, mais à un certain niveau, ces choses doivent être connues, et dans les ordinateurs, vous devez spécifier TOUT. Lisez le livre de règles de hockey États-Unis pendant un certain temps de hockey sur glace; la première règle dans le livre est que le jeu doit être joué sur une surface de glace. Il est l'un des ultimes « bien Duhs », mais aussi une vérité fondamentale du jeu qui doit être compris pour que toute autre règle de sens.

mai, il est tel que les garanties de code pass-through lorsqu'il est appelé comme Convert.ChangeType(client, typeof(Client)) peu importe si IConvertible est mis en œuvre.

Regardez dans la source de ChangeType de mscorlib avec réflecteur et notez les conditions dans lesquelles value est retourné en l'état.

Rappelez-vous un opérateur = n'est pas une conversion, juste un ensemble de référence. Ainsi, le code comme Client client_2 = client_1 ne fonctionne pas de conversions implicites. Si une identité conversion implicite est déclarée en erreur CS0555 est émis.

Je suppose que la spécification dit laisser le C # poignée du compilateur de tels cas, et donc dot pas essayez de définir manuellement les conversions d'identité.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top