2009-12-22 3 views
0

Je pensais à la différence entre Expression<Func<>> et Func<>, et je me demandais si vous pouvez convertir une méthode statique à un arbre d'expression comme suit:C# syntaxe d'expression

class Program 
{ 
    static void Main(string[] args) 
    { 
     Func<int, int> t = x => hrm(x); 
     Func<int, int> t2 = new Func<int, int>(hrm); 

     // Works as expected: 
     Expression<Func<int, int>> et = x => hrm(x); 
     // Brokenness: 
     Expression<Func<int, int>> et2 = new Func<int, int>(hrm); 
    } 

    static int hrm(int x) 
    { 
     return x + 9; 
    } 
} 

Ce qui est si spécial au sujet de la deuxième « Func <> "Qu'il ne peut pas être converti en Expression, quand le premier peut?

Répondre

4

Je pense que votre confusion vient du fait que lambdas peut représenter des expressions ou des délégués (avec la même syntaxe) en C#. Donc, ce code:

x => hrm(x) 

signifie quelque chose de différent selon l'endroit où il est écrit. Lorsqu'il est affecté à Func<int, int>, il est compilé normalement pour créer un délégué Func<int, int>. Cependant, lorsqu'il est affecté à une expression, le compilateur C# diffère la compilation et l'extrait est interprété comme une expression. Comparez ceci avec new Func<int, int>(hrm), qui renvoie toujours un délégué Func<int, int>.

+0

Merci, itowlson. Je ne suis pas le maître de la démarque. –

+0

Point décisif: ce n'est pas tout à fait que "les expressions et les lambdas sont syntaxiquement équivalents", mais que "les lambdas représentant les expressions et les lambdas représentant les délégués sont syntaxiquement équivalents". Les deux sont toujours des lambdas. Mais bonne explication du point général que le compilateur traite un lambda différemment selon ce qu'il retourne. – itowlson

+0

Vous avez raison. Je vais le corriger. –

1

Ma compréhension:
Un lambda peut être représenter une expression ou un délégué/Action/Func.
Le premier exemple fonctionne, car le côté gauche s'assure que vous voulez une expression.
Le deuxième exemple ne fonctionne pas, car vous créez un Func <> explicitement sur le côté droit.

1

Seules les expressions lambda sont convertibles en arbres d'expression. C'est pourquoi votre deuxième option ne compilera pas.

Vous pouvez créer un arbre d'expression pour représenter l'invocation de hrm() - mais ce serait soit via un lambda ou en créant l'AST à la main. De plus, dans les deux cas, le corps du hrm() n'est jamais disponible sous la forme d'un arbre d'expression - si c'est ce que vous cherchiez à faire.

+0

C'est en fait ce que je cherchais à faire, mais j'avais une bonne idée que ce ne serait pas si facile. – cwa