Algum plano para o operador LINQ "DO"/Action?
Pergunta
Aqui está um método simples com um foreach
ciclo:
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;
}
Meio feio. Se havia algum operador em Linq que significa "fazer algo" (por exemplo, execute um Action
Para cada um selecionado na declaração LINQ), ficaria melhor e mais 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;
}
Percebo que isso é subjetivo e apenas minha opinião. Para um loop foreach que tem uma linha que simplesmente invoca um método, um "do
"O operador faz sentido, na minha opinião. Mas estou me perguntando se alguém da MS pensou a mesma coisa. Esse operador LINQ está planejado em qualquer lançamento (por exemplo, ao lado da estréia do C# 4.0)?
Aqui está outro exemplo, com um predicado, onde o fictício do
O operador realmente faria o código parecer mais limpo. 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;
}
vs. isto:
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;
}
Solução
Não, eu não espero nenhum direto Língua Suport (ou seja, dentro da sintaxe de consulta) em breve.
Parece que você quer dizer o mítico ForEach
método de extensão; trivial para acrescentar, mas Eric Lippert comentou várias vezes sobre o cruzamento entre o código funcional sem efeito colateral e Action<T>
com efeitos colaterais. Em particular, as árvores de expressão C# 3.0 / .NET 3.5 são ruins em efeitos colaterais (tornando complicado o suporte completo do lambda). O lado do tempo de execução é muito melhor no .net 4.0, mas não está claro no momento quanto disso chegará ao idioma (compilador Lambda) em C# 4.0.
Tudo o que você precisa (para a versão delegada) é:
public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{ // note: omitted arg/null checks
foreach(T item in source) { action(item); }
}
Depois de qualquer consulta que você possa simplesmente usar .ForEach(x => /* do something */)
.
Outras dicas
Para o seu exemplo específico (preenchendo um List<XElement>
), Eu faria dessa maneira.
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;
}
Além disso: não se esqueça disso List<T>
já implementa .ForEach<T>()
, então para usá -lo contra qualquer Enumerable<T>
, esse é todo o código que você precisa.
myEnumerable.ToList().ForEach( x => myAction(x) );
Eu não acho que isso seja muito difícil ou talvez eu esteja perdendo alguma coisa ...
IEnumerable<XElement> FieldsToXElements(object instance)
{
return instance.GetType()
.GetFields(instance)
.Select( f => new XElement( f.Name,
f.GetValue(instance) ) );
}
Se você está simplesmente olhando para chamar uma função de dentro da sua instrução LINQ, já pode fazer isso, pode fazer uma chamada para uma função em uma atribuição de LEST.
var qry = from e in somelist
let errorcode = DoSomeProcessing(e)
select e;