Question

Voici une méthode simple avec une boucle foreach :

IEnumerable<XElement> FieldsToXElements(object instance)
{
    var fieldElements = new List<XElement>();

    foreach (var field in instance.GetType().GetFields(instance))
    {
        fieldElements.Add(new XElement(field.Name, field.GetValue(instance)));
    }

    return fieldElements;
}

Un peu moche. Si LINQ avait un opérateur qui signifie "faire quelque chose" (par exemple, effectuez une Action pour chaque élément sélectionné dans l’instruction LINQ), il sera plus joli et plus concis:

IEnumerable<XElement> FieldsToXElements(object instance)
{
    var fieldElements = new List<XElement>();

    from field in instance.GetType().GetFields(instance))
    let name = field.Name
    let value = field.GetValue(instance)
    do fieldElements.Add(new XElement(name, value));

    return fieldElements;
}

Je me rends compte que c'est subjectif, et juste mon opinion. Pour une boucle foreach comportant une seule ligne invoquant une méthode, un code " do ". opérateur a du sens, à mon avis. Mais je me demande si quelqu'un chez MS a pensé la même chose. Un tel opérateur LINQ est-il prévu dans les prochaines versions (par exemple, parallèlement au lancement de C # 4.0)?

Voici un autre exemple, avec un prédicat, dans lequel l'opérateur fictif do rendrait le code plus net. Ceci:

IEnumerable<XElement> FieldsToXElements
    (object instance, Func<FieldInfo, bool> predicate)
{
    var fieldElements = new List<XElement>();

    foreach (var field in instance.GetType().GetFields(instance).Where(predicate))
    {
        fieldElements.Add(new XElement(field.Name, field.GetValue(instance)));
    }

    return fieldElements;
}

vs. ceci:

IEnumerable<XElement> FieldsToXElements
    (object instance, Func<FieldInfo, bool> predicate)
{
    var fieldElements = new List<XElement>();

    from field in instance.GetType().GetFields(instance))
    let name = field.Name
    let value = field.GetValue(instance)
    where predicate(field)
    do fieldElements.Add(new XElement(name, value));

    return fieldElements;
}
Était-ce utile?

La solution

Non, je ne m'attends pas à un langage direct (c'est-à-dire à l'intérieur de la syntaxe de la requête) de si tôt.

Cela ressemble à de la mythique méthode d'extension ForEach ; trivial à ajouter, mais Eric Lippert a fait de nombreuses remarques à propos du croisement entre le code fonctionnel sans effet secondaire et la Action < T > avec des effets secondaires. En particulier, les arborescences d’expression C # 3.0 / .NET 3.5 sont minables à l’effet de côté (rendre difficile la prise en charge complète du lambda). Le côté exécution est bien meilleur dans .NET 4.0 , mais ce n'est pas clair. pour le moment, combien de temps cela fera dans le langage (compilateur lambda) en C # 4.0.

Tout ce dont vous avez besoin (pour la version déléguée) est:

public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{   // note: omitted arg/null checks
    foreach(T item in source) { action(item); }
}

Ensuite, à partir de n'importe quelle requête, vous pouvez simplement utiliser .ForEach (x = > / * faire quelque chose * /) .

Autres conseils

Pour votre exemple spécifique (remplissage d'une liste < XElement > ), je le ferais de cette façon.

IEnumerable<XElement> FieldsToXElements(object instance)
{
  List<XElement> fieldElements =
  (
    from field in instance.GetType().GetFields(instance))
    let name = field.Name
    let value = field.GetValue(instance)
    select new XElement(name, value)
  ).ToList();  //Another Option is List<T>.AddRange()
  return fieldElements;
}

Aussi: n'oubliez pas que List < T > implémente déjà .ForEach < T > () , afin de l'utiliser contre tout Enumerable < T > ; , c’est tout le code dont vous avez besoin.

myEnumerable.ToList().ForEach( x => myAction(x) );

Je ne pense pas que ce soit trop difficile ou peut-être qu'il me manque quelque chose ...

IEnumerable<XElement> FieldsToXElements(object instance)
{
    return instance.GetType()
                   .GetFields(instance)
                   .Select( f => new XElement( f.Name,
                                               f.GetValue(instance) ) );
}

Si vous souhaitez simplement appeler une fonction à partir de votre instruction linq, vous pouvez déjà le faire. Vous pouvez également appeler une fonction dans une affectation Let.

var qry = from e in somelist
          let errorcode = DoSomeProcessing(e)
          select e;
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top