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

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;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top