2010-05-26 5 views
8

Je suis novice en termes d'expressions lambda et je cherche à utiliser la syntaxe pour définir la valeur d'une propriété dans une collection basé sur une autre valeur dans une collectionExpressions lambda - définissez la valeur d'une propriété dans une collection d'objets en fonction de la valeur d'une autre propriété dans la collection

Typiquement je fais une boucle:

class Item 
{ 
    public string Name { get; set; } 
    public string Value { get; set; } 
} 

void Run() 
{ 
    Item item1 = new Item { Name = "name1" }; 
    Item item2 = new Item { Name = "name2" }; 
    Item item3 = new Item { Name = "name3" }; 

    Collection<Item> items = new Collection<Item>() { item1, item2, item3 }; 

    // This is what I want to simplify. 
    for (int i = 0; i < items.Count; i++) 
    { 
     if (items[i].Name == "name2") 
     { 
      // Set the value. 
      items[i].Value = "value2"; 
     } 
    } 
} 

Répondre

14

LINQ est généralement plus utile pour sélectionner des données que pour la modification de données. Cependant, vous pourriez écrire quelque chose comme ceci:

foreach(var item in items.Where(it => it.Name == "name2")) 
    item.Value = "value2"; 

Ce premier sélectionne les éléments qui doivent être modifiés et modifie alors tous en utilisant une norme impérative boucle. Vous pouvez remplacer la boucle foreach avec la méthode ForAll qui est disponible pour les listes, mais je ne pense pas que cela vous donne un avantage:

items.Where(it => it.Name == "name2").ToList() 
    .ForEach(it => it.Value = "value2"); 

Notez que vous devez ajouter ToList au milieu, parce que ForEach est un .NET 2.0 fonctionnalité qui est disponible uniquement pour le type List<T> - pas pour tous les types IEnumerable<T> (comme les autres méthodes LINQ). Si vous aimez cette approche, vous pouvez mettre en œuvre pour ForEachIEnuerable<T>:

public static void ForEach<T>(this IEnumerable<T> en, Action<T> f) { 
    foreach(var a in en) f(a); 
} 

// Then you can omit the `ToList` conversion in the middle 
items.Where(it => it.Name == "name2") 
    .ForEach(it => it.Value = "value2"); 

Quoi qu'il en soit, je préfère boucle foreach, parce que cela fait aussi clairement que vous faites une mutation - et il est utile de voir ce fait facilement dans le code.

+0

Légère correction: C'est supposé être it.value = "value2" ... –

+0

belle. Pas moyen de contourner la boucle alors? –

+0

@Michael Rut, la boucle se lit mieux que la méthode ForEach, mais c'est une question d'opinion. Je suis d'accord avec ce que Tomas a dit dans sa réponse sur la clarté de l'action. Cependant, il a montré un moyen pour vous de faire abstraction de la boucle (bien que clairement une boucle se produira encore, plutôt que vous le codez explicitement ou non). –

Questions connexes