Pregunta

Aquí hay un método simple con un bucle 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 poco feo. Si hubiera algún operador en LINQ que significa "hacer algo" (por ejemplo, realice una Action para cada seleccionado en la instrucción LINQ), se vería mejor, más 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;
}

Me doy cuenta de que es subjetivo, y solo mi opinión. Para un bucle foreach que tiene una línea que simplemente invoca un método, un " do " operador tiene sentido, en mi opinión. Pero me pregunto si alguien en MS ha pensado lo mismo. ¿Está previsto dicho operador LINQ en los próximos lanzamientos (por ejemplo, junto con el debut de C # 4.0)?

Aquí hay otro ejemplo, con un predicado, donde el operador ficticio do realmente haría que el código se vea más limpio. Esto:

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. esto:

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;
}
¿Fue útil?

Solución

No, no espero ningún soporte directo de idioma (es decir, dentro de la sintaxis de la consulta) en el corto plazo.

Parece que te refieres al mítico método de extensión ForEach ; trivial para agregar, pero Eric Lippert ha comentado numerosas veces sobre el cruce entre el código funcional sin efectos secundarios y Action < T > con efectos secundarios. En particular, los árboles de expresión C # 3.0 / .NET 3.5 son pésimos en los efectos laterales (lo que hace que el soporte completo de lambda sea complicado). El lado de tiempo de ejecución es mucho mejor en .NET 4.0 , pero no está claro en este momento, cuánto de esto llegará al lenguaje (compilador lambda) en C # 4.0.

Todo lo que necesita (para la versión delegada) es:

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

Luego, desde cualquier consulta, simplemente puede usar .ForEach (x = > / * hacer algo * /) .

Otros consejos

Para su ejemplo específico (rellenando una List < XElement > ), lo haría de esta manera.

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

Además: no olvide que List < T > ya implementa .ForEach < T > () , para usarlo contra cualquier Enumerable < T > ; , este es todo el código que necesita.

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

No creo que esto sea demasiado difícil o tal vez me estoy perdiendo algo ...

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

Si simplemente está buscando llamar a una función desde su instrucción linq, entonces ya puede hacerlo, puede llamar a una función en una asignación Let.

var qry = from e in somelist
          let errorcode = DoSomeProcessing(e)
          select e;
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top