Quelqu'un peut-il expliquer pourquoi le premier des deux exemples suivants est valide et l'autre n'est pas? Plus précisément, comment une relation est-elle créée entre t et tproperty dans le premier exemple?
void SomeMethod<T>( Expression<Func<T,Object>> expression ){ ... }
4 Réponses :
Le problème, aussi loin que je peux voir, est simplement que Il est probablement aussi confus que dans le premier exemple, vous avez deux paramètres de type appelés ceci est maintenant le même DateTime code> n'est pas une classe ... vous passez dans
t code> comme
DateTime code> (que ce soit implicite ou explicite).
t code> - un sur le type, et un sur la méthode. Ils sont en fait complètement séparés ... Pour être identiques, réécrivez le premier exemple que: p>
t: classe code> < / p> p>
Désolé mauvais exemple ... Évidemment DateTime est une structure. Fait des modifications à mon exemple pour espérer plus clairement le problème. En supposant que l'objet est en fait une classe avec des propriétés et non une structure.
Bien que cela soit vrai, et cela peut certainement être écrit de cette façon - je suis intéressé par l'endroit où la connexion est faite que TPROPERTY est réellement liée à T, permettant ainsi P => p.property dans l'expression sans jamais définir le type générique de TPRPERTY . Plus important encore, comment j'ai accompli la même chose avec une méthode qui n'est pas dans une classe générique. Est-ce que j'ai du sens? :)
Tout d'abord, votre premier exemple est incorrect et ne compilera pas comme indiqué. Outre le manquant En outre, vos exemples "ignorent" (c'est-à-dire enfreindre) le type réel de Il n'y a pas de relation implicite établie dans le premier exemple, non plus. Lorsque vous instaniez Donc, le type d'argument de la Lambda est connu à ce stade, vous n'avez donc pas à le spécifier. Le type de retour d'expression lambda est déduit en tant que type d'expression à droite de Dans le deuxième exemple, étant donné que public code> sur la méthode, vous définissez
t code> deux fois - une fois sur classe et une fois sur méthode. Ce n'est pas une erreur en soi (bien que vous obtenez un avertissement), mais lors de la compilation de l'appel de la méthode, vous obtiendrez la même erreur que vous décrivez obtenir par exemple # 2. Donc, je suppose que le code réel est comme celui-ci:
TPROPERTY code> dans votre Appelez à
SOMEMETHOD CODE>. Votre deuxième exemple spécifie explicitement le type de
t code>, oui, mais pas
tproperty code>. P>
Someclass <> code> avec
t = mydateclass code>, la signature de
SOMEMETHOD code> pour cette instanciation devient effectivement: p>
=> code>, et ce sera le type inféré de
TPROPERTY code>. P>
t code> n'a pas été explicitement spécifié lors de l'instanciation de la classe, et car il n'ya aucun moyen de le déduire des arguments de la méthode, il doit être spécifié explicitement. Une fois que vous le spécifiez,
TPROPERTY code> est désigné exactement de la même manière que pour l'exemple n ° 1. P> P>
Je ne comprends pas ce que vous impliquez avec votre indicateur de commentaires. Dites-vous que aucun exemple ne devrait ne pas fonctionner car le type de TPROPERTY est inconnu dans les exemples? En ce qui concerne les erreurs de syntaxe, oui, coupable comme chargé - je n'ai pas essayé de compiler ces exemples avant de poster.
"Inférer" signifie "Trouver automatiquement le type". Dans ce cas, il va comme suit: Type de t code> est connu ->
T1 code> dans
FUNC
dt code> est connu -> Le type de retour de Lambda est déduit en tant que type d'expression
dt.year code> (une fois que nous connaissons le type de
dt code>, nous avons évidemment Connaître le type de
dt.year code> ->
treesult code> dans
Func
TPROPERTY code> est connu.
La confusion n'est pas avec une compréhension de ce que signifie un inducteur, mais comment définir MyDaTeclass au niveau de la classe par rapport au niveau de la méthode fait une différence. c'est à dire; Soméclass
Oh, je vois maintenant. Si votre exemple n ° 2 est pris exactement comme indiqué, l'erreur du compilateur est simplement parce que vous ne spécifiez pas TPROPERTY code>. Ce n'est pas parce que cela ne peut pas être déduit, mais parce que, contrairement à C ++, C # ne vous permet pas de spécifier explicitement certains paramètres de type dans un appel de méthode, mais omettez les autres. Vous vous omettez tous tout d'entre eux (et laissez-les déduire) ou vous spécifiez tout.
Exactement. :) Désolé si je n'étais pas clair. J'ai essayé de baisser l'exemple, mais j'ai peut-être obscurcier le problème en ajoutant des erreurs de compilateur avec le code Adhoc. Excuses.
Plutôt que de taper les spécificités, jetez un coup d'œil à ce message par Eric Lippert . Je pense que cela répondra à ce que vous essayez de demander. P>
Je me rends compte que c'est long et conçu, mais je pense que c'est le meilleur coup pour le Buck pour vous répondre. P>
Vous permettrez au compilateur d'inférer les paramètres de type. Cela fonctionne bien pour le cas 1: parce que vous déclarez d'abord une instance: p> qui indique au compilateur que t est MyDateclass code>. Ensuite, lorsque vous appelez la méthode: p>
sc.SomeMethod((MyDateClass dt) => dt.Year );
Donc, efficacement le compilateur effectue la magie dans le premier exemple? Faire une hypothèse que TPROPERTY devrait être un int car .year est un int? Cela répondrait à ma question, je ne peux pas dire que c'est satisfaisant cependant. :)
... Je pense que la lumière est juste descendue. La DIFF entre la classe
Je ne sais pas pourquoi vous n'êtes pas satisfait, mais l'inférence de type statique n'est pas une magie et a des règles explicites et est une nouvelle fonctionnalité en C #.
@Ikariii - Je ne suis pas sûr de ce que vous impliquez. Ce n'est pas contextuel, T est connu dans le premier exemple car vous deviez le préciser à la création de classe. Vous vous attendez à ce que cela soit déduit dans la seconde.
Droite ... Mais quelle est la différence entre spécifier T au niveau de la classe et spécifier au niveau de la méthode? Soméclass
Merci Mark, je pense que vous avez compris le problème exactement et avons pu articuler une réponse pour amener mon cerveau à partir d'un époque à queue! :)