Domanda

Ecco un metodo semplice con un ciclo 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 po 'brutto. Se ci fosse qualche operatore in LINQ che significa "fai qualcosa" (ad es. esegui un Azione per ciascuno selezionato nell'istruzione LINQ), sembrerebbe più bello, più conciso:

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

Mi rendo conto che è soggettivo e solo la mia opinione. Per un ciclo foreach che ha una riga che invoca semplicemente un metodo, un " do " operatore ha senso, secondo me. Ma mi chiedo se qualcuno in MS abbia pensato la stessa cosa. Tale operatore LINQ è previsto nelle prossime versioni (ad es. Accanto al debutto in C # 4.0)?

Ecco un altro esempio, con un predicato, in cui l'operatore fittizio do renderebbe il codice più pulito. Questo:

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. in questo modo:

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;
}
È stato utile?

Soluzione

No, non mi aspetto alcun linguaggio diretto (cioè all'interno della sintassi della query) in qualunque momento presto.

Sembra che tu intenda il mitico metodo di estensione ForEach ; banale da aggiungere, ma Eric Lippert ha commentato numerose volte l'incrocio tra codice funzionale privo di effetti collaterali e Azione < T > con effetti collaterali. In particolare, gli alberi delle espressioni C # 3.0 / .NET 3.5 sono pessimi in termini di effetti collaterali (rendendo complicato il supporto completo lambda). Il lato runtime è molto meglio in .NET 4.0 , ma non è chiaro al momento, quanto di tutto ciò verrà inserito nel linguaggio (compilatore lambda) in C # 4.0.

Tutto ciò che serve (per la versione delegata) è:

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

Quindi da qualsiasi query puoi semplicemente usare .ForEach (x = > / * fare qualcosa * /) .

Altri suggerimenti

Per il tuo esempio specifico (compilando un Elenco < XElement > ), lo farei in questo modo.

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

Inoltre: non dimenticare che Elenca < T > implementa già . ; , questo è tutto il codice che ti serve.

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

Non penso che sia troppo difficile o forse mi manca qualcosa ...

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

Se stai semplicemente cercando di chiamare una funzione dall'istruzione linq, puoi già farlo, puoi effettuare una chiamata a una funzione in un compito Let.

var qry = from e in somelist
          let errorcode = DoSomeProcessing(e)
          select e;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top