2010-09-06 2 views
0

Je viens de trouver un comportement mystérieux lorsque je travaillais avec System.Linq.Expressions.Expression et System.Reflection.MethodInfo..NET 4.0: Incompatibilité des noms de paramètres entre Expression et MethodInfo

Le code est le suivant:

static void Main(string[] args) 
    { 

     Expression<Func<double, double, double>> example = (x, y) => Math.Sin(x); 

     //Prints out "x, y": 
     Console.WriteLine(example.Parameters[0].Name + ", " + example.Parameters[1].Name); 

     //Prints out "a": 
     Console.WriteLine((example.Body as MethodCallExpression).Method.GetParameters()[0].Name); 

    } 

"a"? Où est passé mon "x" et d'où vient ce "a"? En pensant que c'est peut-être un alias utilisé au niveau bas, j'ai cherché "UsedName", "VisibleName" ou quelque chose comme ça, mais je n'ai rien trouvé.

Malheureusement, Expression ne dispose pas d'une propriété Parameters (je crois seulement LambdaExpression) qui retournerait les "paramètres utilisés", le cas échéant, dans une expression donnée.

On peut créer une méthode qui parcourt toute l'expression et qui recueille les différents paramètres utilisés, mais je me demandais s'il y avait un moyen plus simple de le faire.

Merci beaucoup d'avance.

Visual C# Express: 10.0.30319.1 RTMRel

.NET Framework: 4.0.30319 RTMRel

Répondre

2

Le a vient de la méthode que vous appelez - Math.Sin. x et y sont des paramètres de votre expression lambda; a est le paramètre dans Math.Sin.

Si vous voulez revenir x et y, jeté example-LambdaExpression:

foreach (ParameterExpression p in example.Parameters) 
{ 
    Console.WriteLine(p.Name); // Prints x then y 
} 

Donc non, il n'y a pas d'incohérence ici.

EDIT: Si vous voulez trouver les arguments utilisés dans l'appel de méthode - et vous êtes sûr qu'il est juste un appel de méthode et les arguments seront juste paramètres - vous pouvez utiliser quelque chose comme:

var methodCall = (MethodCallExpression) example.Body; 

// Implicitly casts each argument to ParameterExpression 
foreach (ParameterExpression p in methodCall.Arguments) 
{ 
    Console.WriteLine(p.Name); 
} 

Dans ce cas, il affiche simplement x car c'est ce qui est utilisé comme argument pour Math.Sin.

+0

Maintenant, je comprends que je ne comparais pas vraiment les pommes aux pommes, alors je suis d'accord qu'il n'y a pas d'incohérence. D'un autre côté: pourquoi la distribution? Je peux déjà accéder à 'Parameters',' Body', etc. directement depuis 'example', qui (je crois) est de type' LambdaExpression'. Ce que je pense serait vraiment utile est quelque chose comme ceci: 'ParameterExpression [] paramètres = (anyExpressionInstance comme LambdaExpression) .Parameters.ToArray();'. Dans ce cas précis, '(exemple.Body as LambdaExpression)' deviendrait 'x => Math.Sin (x)', d'où je pourrais récupérer le "paramètre en cours d'utilisation" 'x'. –

+0

@Blas: Vrai - Je lance en raison de votre paragraphe de démarrage "Malheureusement" - mais oui, j'avais oublié que vous avez réellement une «Expression », pas seulement une expression ». Alors oui, vous n'avez pas besoin de la distribution. Je vais modifier ma réponse. Personnellement, je lancerais plutôt que d'utiliser 'as', bien que, dans votre code de commentaire, une exception NullReferenceException ne soit pas aussi utile qu'une' InvalidCastException'. –

+0

@Blas: Il suffit de relire votre commentaire, il semble que vous voulez les * arguments * à l'appel de la méthode. Modification ... –

0

Placez le curseur sur Sin dans Visual Studio. Appuyez sur la touche F12. Voici d'où vient a. Il vient d'un développeur à Redmond qui a décidé de le nommer comme ceci :-)

+0

Je vois, donc "a" est juste le nom du paramètre "codé en dur" de la fonction Sin. –

+0

Oui, c'est d'où ça vient. –

Questions connexes