J'ai cette fonction Je crée 2 personnes d'instances de classe: p> J'appelle la fonction avec: P> MyClass.MyFunc(p, p2, 5);
6 Réponses :
La possibilité d'omettre les types d'appel dans l'appel est un bonbon de syntaxe (sauf si vous utilisez des types anonymes), et il compile exactement identique à p> Le compilateur déduit les valeurs de t1 code> et t2 code> en fonction des types des paramètres A code>, B code> et C code>. Si p1 code> et p2 code> est de types incompatibles (voir Réponse de Svick , le compilateur ne sera pas en mesure de déduire t1 code> et cela entraînera une erreur de compilation. P> p>
Néanmoins, le compilateur a besoin d'une ancrage pour voir s'il devrait vérifier que Apple ou Orange
Je pense que le compilateur ne se soucie pas de ce que les types sont, il vérifie simplement si les premier et second paramètres sont du même type.
@Royinamir, vous parlez de personnes et vous parlez de pommes et d'oranges ... Désolé, j'ai du mal à vous suivre :)
@Ilakogan Lorsque le compilateur se trouve T1, il devrait vérifier si T2 == T1 ou lorsqu'il voit des chèques T2 - E si T2 == T1.
T1 == T2 est la même chose que T2 == T1, nous parlons de type code> de la perspective du compilateur ici, pas d'une instance n'est égale à la vérification.
@ROYINAMIR Il ne vérifie pas si p1 == p2 code>. Il vérifie si typeof (p1) == typeof (p2) code>.
Ce n'est pas seulement Syntaxe Sugar si vous utilisez des types anonymes. Et il peut toujours compiler même si p1 code> et p2 code> sont différents types.
Merci, @svick, j'ai édité la réponse à mentionner des types anonymes. Pouvez-vous donner un exemple où cela compilera avec deux types différents?
@Ilakogan, voir Ma réponse pour des exemples de cela.
Il n'y a pas de priorité, les deux (A et B) doivent être identiques, c'est-à-dire par conception, T1 est résolu à la compilation. Si vous changez sur EDIT: P> La pièce intéressante: p> sorties: p> > mais ceci: p> lancera: p> Cependant Il semble que je vraiment strong> besoin de trouver un bon livre ou une ressource sur les types dynamiques en C # 4.0 pour comprendre la magie se produire ici. P> P> DYNAMIC CODE>, vous venez de reporter le type de type de type à l'exécution et il échouera ensuite à compilétime si les types ne sont pas identiques. Si vous voulez qu'ils soient différents, vous devez introduire T3.
Je ne sais pas si je comprends ce que tu veux dire, mais ... si A.getType () est égal à b.getType (), que c'est aussi vrai vice versa. Ils ont juste besoin d'être T1 (tant qu'il n'y a pas de dynamique évidemment, voir mon édition ci-dessus)
La magie de ce cas est extrêmement simple: un argument de type explicite dynamique code> est traité exactement comme si vous avez dit objet code> lorsque l'expression est analysée au moment de l'exécution. Si vous avez une question spécifique à propos de quelque chose que vous ne comprenez pas, c'est un site de questions-réponses; envisagez de poster une question.
Cela semble si évident maintenant, merci pour l'explication que vous avez postée.
Au moment de la compilation Si les types sont explicites, le compilateur vérifiera les types de paramètres passés et voyez s'ils correspondent à des types dans les génériques (aucun conflit). P>
Quoi qu'il en soit, la vérification réelle est effectuée à "Runtime", le code générique compile comme générique de toute façon (contrairement aux modèles C ++). Et puis lorsque le compilateur JIT compile la ligne, il vérifiera et voyez s'il peut créer la méthode en fonction des modèles que vous avez donnés et les paramètres envoyés. P>
Qui décide effectivement du type T1? (P? P2?) P> blockQuote>
N'est-il pas évident? Les deux. Les types de
p code> etp2 code> doivent être compatibles. Contrairement à quelles autres réponses disent, ils ne doivent pas nécessairement être les mêmes. La règle réelle est qu'il doit y avoir une conversion implicite de la part des types à l'autre. P>donc, par exemple
myfunc ("a", nouvel objet (), 5) code> est identique àmyfunc("A" objet ("A", 5) code>, car chaîne code> est implicitement convertible àobjet code>. Comme un autre exemple,myfunc (42L, 42, 4) code> est identique à celuimyfunc(42L, 42, 4) code>, car int < / code> est implicitement convertible àlong code>. p>En outre, il existe des cas où la possibilité de laisser le compilateur déduire les types n'est pas juste agréable, c'est nécessaire. Plus précisément, cela se produit lors de l'utilisation de types anonymes. Par exemple
myFunc (nouveau {p = "p"}, nouveau {p = "p2"}, 5) code> ne peut pas être réécrit pour spécifier les types explicitement. P>
"Qui décide effectivement du type T1? (P2 P2?)" P>
Normalement, le compilateur C # décide cela. Si l'un des arguments de la méthode est dynamique, la décision est effectuée à l'exécution (par la bibliothèque Microsoft.cshaarp).
Dans les deux cas, l'algorithme d'inférence de type décrit dans la spécification C # est appliqué:
Les deux types de Ensuite, le compilateur choisit l'un des types dans l'ensemble des limites qui satisfont également à toutes les autres limites.
Lorsqu'il n'y a qu'un seul lié, car S'il n'y a pas de choix unique de ce type, l'inférence de type échoue - une autre surcharge est choisie si possible, sinon une erreur de compilateur se produit (lorsque la décision est effectuée à l'exécution (dynamique), une exception est lancée à la place). P> p code> et p2 code> sont ajoutés à t1 code> 's ensemble de limites inférieures em> ( Les limites em> sont également possibles, mais uniquement lorsque des génériques de contravariation sont impliqués). P>
p code> et p2 code> ont le même type, ce choix est trivial.
Sinon (en supposant que seules les limites inférieures sont impliquées), cela signifie que le compilateur choisit un type de sorte que tous les autres types de candidats soient implicitement convertibles à ce type (quelle réponse de Svick décrit). P>
Vous vouliez dire Contravariant i> Generics.
@ Sciences LIPPERT: Oups, je mélange toujours les termes Covariance / Contravierce. En fait, je les ai regardés lors de la rédaction de cette question et j'ai toujours réussi à écrire le mauvais. Merci d'utiliser In / Out dans C #, c'est beaucoup plus facile à retenir.
À un niveau de haut niveau, l'inférence de type de méthode fonctionne comme ceci.
Nous faisons d'abord une liste de tous les arguments em> - les expressions que vous fournissez - et leur paramètre formel correspondant Tapez em>. P> Regardons un exemple plus intéressant que celui que vous donnez. Supposons que nous ayons p> et le même appel. Nous faisons donc les correspondances: p> puis nous faisons une liste de ce que "limites" sont sur chaque paramètre de type et qu'ils sont "fixes". Nous avons deux paramètres de type et nous commençons avec aucune limite supérieure, inférieure ou exacte. P> (rappelez notre récente discussion dans une autre question sur les tailles relatives des types de types étant basés sur si un type était plus ou moins restrictif; un type plus restrictif est plus petit em> que celui qui est moins restrictif. La girafe est plus petite que l'animal, car plus de choses sont des animaux que les girafes. Le "supérieur "et les ensembles liés" inférieurs "sont exactement que: la solution au problème de l'inférence de type pour un paramètre de type donné doit être plus grande ou identique à em> chaque borne inférieure et plus petite ou identique à toutes les limites supérieures, et identiques à em> toutes les limites exactes.) p> Nous examinons ensuite chaque argument et son type correspondant. (Si les arguments sont lambdas, nous devrions peut-être comprendre l'ordre em> dans lequel nous examinons des arguments, mais vous n'avez pas de lambdas ici, alors ignorons ce détail.) Pour chaque argument que nous faisons Une inférence em> au type de paramètre formel et ajoutez les faits que nous déduisons de cette inférence à l'ensemble lié. Ainsi, après avoir examiné le premier argument, nous déduisons les limites: p> après le deuxième argument que nous déduirons les limites p> T1: (fixed) Person
T2: (fixed) int
J'ai l'impression que le compilateur m'a donné une réponse. Merci beaucoup . (encore)
@Royinamir: De rien. J'ai ajouté des liens avec des articles et des vidéos utiles si vous souhaitez plus d'informations sur ce sujet.
Donc, C # 4 ajouté les limites supérieures? Pourquoi donc? Dans quelles situations sont-elles utiles?
@svick: Les limites supérieures ne sont que même possibles i> lorsque l'inférence de type générique doit être faite impliquant une conversion Contravariant i>. Étant donné que C # 3 n'a eu que des conversions de covariant ou non variantes, il n'y avait aucun moyen de ne jamais entrer dans une situation où il y avait même était i> une limite supérieure, nous n'avons même pas la peine de les mentionner dans l'algorithme. Lorsque nous avons ajouté des conversions Covariant et Contravariant sur des interfaces génériques et des délégués au C # 4, nous avons ajouté des déductions de la limite supérieure à l'algorithme d'inférence de type.
Pouvez-vous s'il vous plaît dire où je peux télécharger l'algorithme d'inférence vidéo complète de la vôtre que vous avez liée à votre réponse: blogs.msdn.com/b/ericlippert/archive/2006/11/17/... et c'est un lien direct dans Ce blog post WM.MICROSOFT.COM/MS/MSDN/VISUALCSHARP/ERIC_LIPPERT_2006_11 / ... . J'ai une connexion lente c'est pourquoi demander :)
@ M3taspl0it: aucune idée, désolé.
Il n'y a pas de «décision». Une correspondance est trouvée ou une erreur se produit. Essayez simplement
myfunc (P1, "", 5) code> oumyfunc ("", p2, 5) code>.