Frage

Hier ist eine einfache Methode, mit einer foreach Schleife:

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;
}

Art hässlich. Wenn es einige Betreiber in LINQ waren, die „etwas tun“ bedeuten (zum Beispiel eine Action für jeden in der LINQ-Anweisung ausgewählt ausführen), wäre es schöner aussehen, mehr kurz und bündig:

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;
}

Ich weiß, das ist subjektiv, und meiner Meinung nach einfach. Für eine foreach-Schleife, die eine Linie hat, die einfach eine Methode aufruft, macht ein „do“ Operator Sinn, meiner Meinung nach. Aber ich frage mich, ob jemand bei MS das gleiche gedacht hat. Ist ein solcher LINQ Operator in zukünftigen Versionen geplant (zum Beispiel neben dem C # 4.0 Debüt)?

Hier ist ein weiteres Beispiel mit einem Prädikat, wo der fiktive do Operator wirklich den Code sehen Reiniger machen würde. Dies:

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. folgt aus:

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;
}
War es hilfreich?

Lösung

Nein, ich erwarte keine direkte Sprache suport (das heißt innerhalb der Abfragesyntax) jederzeit bald.

Es klingt wie Sie die mythische ForEach Erweiterungsmethode bedeuten; trivial hinzufügen, aber Eric Lippert unzählige Male über die Kreuzung zwischen nebenwirkungsfreie Funktionscode und Action<T> mit Nebenwirkungen hat kommentiert. Insbesondere sind C # 3.0 / NET 3.5 Ausdrucksbäume lousy an Neben effecs (full lambda Unterstützung heikel machen). Die Runtime-Seite ist viel besser in .NET 4.0 , aber es ist unklar, zur Zeit, wie viel davon wird es in die Sprache (Lambda-Compiler) macht in C # 4.0.

Alles, was Sie (für Delegierten Version) benötigen, ist:

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

Dann von jeder Abfrage können Sie einfach .ForEach(x => /* do something */) verwenden.

Andere Tipps

Für Ihr spezielles Beispiel (Bestücken eines List<XElement>), würde ich es auf diese Weise tun.

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;
}

Auch:. Vergessen Sie nicht, dass List<T> bereits .ForEach<T>() implementiert, so dass es zu verwenden, gegen jede Enumerable<T>, das ist der gesamte Code Sie benötigen

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

Ich glaube nicht, das ist zu hart oder vielleicht bin ich etwas fehlt ...

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

Wenn Sie einfach nur schauen, um eine Funktion aus Ihrer Linq-Anweisung zu rufen, dann können Sie bereits das tun, können Sie einen Anruf tätigen, um eine Funktion in einer Let Zuordnung.

var qry = from e in somelist
          let errorcode = DoSomeProcessing(e)
          select e;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top