2009-01-24 8 views
11

Aquí es un método simple con un bucle foreach:¿Hay algún plan para "hacer"/operador Action LINQ?

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 hubo algún operador en LINQ que significa "hacer algo" (por ejemplo, realizar una Action para cada seleccionado en la declaración de LINQ), se vería más bonito, más concisa:

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

Soy consciente de que es subjetivo, y sólo mi opinión. Para un bucle Foreach que tiene una línea que simplemente invoca un método, un operador "do" tiene sentido, en mi opinión. Pero me pregunto si alguien en MS ha pensado lo mismo. ¿Se planifica dicho operador LINQ en próximos lanzamientos (por ejemplo, junto con el debut en 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. Este:

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

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

Respuesta

15

No, no espero ningún idioma suport directa (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; Es trivial agregar, pero Eric Lippert ha comentado en numerosas ocasiones sobre el cruce entre el código funcional libre de 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 secundarios (haciendo que el soporte completo de lambda sea complicado). El lado del tiempo de ejecución is much better in .NET 4.0, pero no está claro en este momento cuánto de esto se convertirá en el lenguaje (compilador lambda) en C# 4.0.

todo lo que necesita (para la versión delegado) 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 de cualquier consulta puede simplemente usar .ForEach(x => /* do something */).

1

No creo que esto es demasiado difícil o tal vez me falta algo ...

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

La tarea es trivial. Estoy más interesado en la "belleza" del código. :) – core

1

Si simplemente está buscando en llamar a una función desde dentro de su declaración de LINQ a continuación, ya se puede hacer eso , puede realizar una llamada a una función en una asignación de Dejar.

var qry = from e in somelist 
      let errorcode = DoSomeProcessing(e) 
      select e; 
+0

El único problema aquí es DoSomeProcessing es un Func <>, no una Acción <> :) – core

+0

Un poco no precioso, pero complicado :) – Teejay

3

Para su ejemplo específico (llenar 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; 
} 

También: No olvide que List<T> ya implementa .ForEach<T>(), por lo que para usarlo en contra de cualquier Enumerable<T>, esto es todo el código que necesita.

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

¡Muy bonito! No pensé en eso.Aunque lo acortaría ligeramente solo haciendo: return (from field in ...). ToList() sin definir List fieldElements. ¡Gracias de nuevo! – core

Cuestiones relacionadas