c# - ¿Algún plan para el operador "hacer"/Action LINQ?
c#-4.0 (4)
Aquí hay un método simple 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;
}
Algo feo Si hubiera algún operador en LINQ que significara "hacer algo" (por ejemplo, realizar una Action
para cada uno de los seleccionados en la declaración LINQ), se vería mejor, más escueto:
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 operador de " do
" tiene sentido, en mi opinión. Pero me pregunto si alguien en MS ha pensado lo mismo. ¿Está previsto 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. Esta:
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;
}
contra 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;
}
No creo que esto sea demasiado difícil o quizás me esté perdiendo algo ...
IEnumerable<XElement> FieldsToXElements(object instance)
{
return instance.GetType()
.GetFields(instance)
.Select( f => new XElement( f.Name,
f.GetValue(instance) ) );
}
No, no espero ningún soporte de lenguaje directo (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 de 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 es mucho mejor en .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 necesitas (para la versión de 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, desde cualquier consulta, puede usar .ForEach(x => /* do something */)
.
Si simplemente está buscando llamar a una función desde su instrucción linq, entonces ya puede hacerlo, 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;
Para su ejemplo específico ( List<XElement>
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>()
, así que para usarlo contra cualquier Enumerable<T>
, este es todo el código que necesita.
myEnumerable.ToList().ForEach( x => myAction(x) );