65 votes

Quelle est la portée d'une variable lambda en C# ?

Je suis confus quant à la portée de la variable lambda, prenez par exemple le cas suivant

var query = 
    from customer in clist
    from order in olist
    .Where(o => o.CustomerID == customer.CustomerID && o.OrderDate ==  // line 1
        olist.Where(o1 => o1.CustomerID == customer.CustomerID)        // line 2
             .Max(o1 => o1.OrderDate)                                  // line 3
    )
    select new {
        customer.CustomerID,
        customer.Name,
        customer.Address,
        order.Product,
        order.OrderDate
    };

À la ligne 1, j'ai déclaré une variable lambda 'o', ce qui signifie que je ne peux pas la déclarer à nouveau à la ligne 2 (ou du moins le compilateur se plaint si j'essaie de le faire). Mais il ne se plaint pas de la ligne 3, même si 'o1' existe déjà ?

Quelle est la portée d'une variable lambda ?

174voto

yamen Points 9976

Les crochets donnent l'indice - la variable lambda est capturée dans la portée de l'endroit où elle est déclarée :

.Where(o => ... olist.Where(o1 => ...).Max(o1 => ...))
  //  |----------------------------------------------| scope of o
  //                       |---------|                 scope of first o1
  //                                      |---------|  scope of second o1

Notez qu'il n'y a pas de chevauchement entre les deux. o1 mais elles chevauchent toutes deux (ou font de l'ombre) à la variable o et ne peuvent donc pas utiliser le même nom.

14voto

BoltClock Points 249668

La portée d'un paramètre lambda est égale à la portée entière du corps de l'expression lambda, y compris toute expression lambda interne ou portée.

Si nous étendons la syntaxe de vos expressions lambda et ajoutons une indentation conviviale, cela peut devenir plus clair (bien que probablement pas aussi clair que réponse schématique de yamen !) :

.Where(o => {
    return o.CustomerID == customer.CustomerID
        && o.OrderDate == olist.Where(
            o1 => o1.CustomerID == customer.CustomerID
        )
        .Max(
            o1 => o1.OrderDate
        );
})

Remarquez que votre .Where().Max() L'appel est situé à l'intérieur d'un .Where() . Le site o dans le lambda externe est encapsulé par le lambda externe dans vos lambdas internes (ceci est appelé fermeture ) de sorte qu'il existe déjà dans la portée de vos lambdas internes, et ne peut pas être réutilisé comme paramètre.

Vous pouvez réutiliser o1 parce que vos deux lambdas internes sont complètement séparées l'une de l'autre, et qu'elle ne sort pas du cadre de l'une ou l'autre.

5voto

Frédéric Hamidi Points 123646

Vous ne pouvez pas utiliser le même nom de variable dans deux scopes si l'un des scopes contient l'autre.

Dans votre question, o est introduite dans la portée extérieure, elle ne peut donc pas être réutilisée dans la seconde Where() ou dans Max() car ces champs d'application sont contenus dans le champ d'application externe.

D'autre part, vous pouvez utiliser o1 dans les deux scopes internes car l'un ne contient pas l'autre, il n'y a donc aucune ambiguïté.

4voto

Pranay Rana Points 69934

Parce que lamda est le remplacement de la fonction anonyme ici dans votre code.

Même portée

Where(o => o.CustomerID == customer.CustomerID && o.OrderDate ==   //line 1
         olist.Where(o1 => o1.CustomerID == customer.CustomerID)   //line 2     

est la portée de la fonction dans laquelle vit la variable "o".

ici, à la ligne 3, c'est la nouvelle portée de la variable, c'est-à-dire la nouvelle portée de la fonction.

Portée différente

  .Max(o1 => o1.OrderDate)   )        //line 3

donc c'est le réson dans la ligne1 et la ligne2 varialbe "o" défini dans la ligne1 ne peut pas être défini dans la ligne2 à cause du même scrop et "o1" défini dans la ligne2 peut être défini à nouveau dans la ligne3 parce qu'il est dans un scope de fonction différent

2voto

leppie Points 67289

Le C# ne prend pas en charge ce type d'ombrage.

La raison o1 fonctionne à nouveau, c'est qu'il ne fait pas d'ombre au précédent o1 .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X