Achei que seria bom fazer algo assim (com o lambda fazendo um retorno de rendimento):
public IList<T> Find<T>(Expression<Func<T, bool>> expression) where T : class, new()
{
IList<T> list = GetList<T>();
var fun = expression.Compile();
var items = () => {
foreach (var item in list)
if (fun.Invoke(item))
yield return item; // This is not allowed by C#
}
return items.ToList();
}
Porém, descobri que não posso usar o yield no método anônimo. Estou me perguntando por quê. Os documentos de rendimento apenas dizem que não é permitido.
Como não era permitido, acabei de criar a lista e adicionar os itens a ela.
c#
yield
anonymous-methods
yield-return
Lance Fisher
fonte
fonte
async
lambdas anônimos permitindo oawait
interior no C # 5.0, estou interessado em saber por que eles ainda não implementaram iteradores anônimos com oyield
interior. Mais ou menos, é o mesmo gerador de máquina de estado.Respostas:
Eric Lippert escreveu recentemente uma série de posts sobre por que a produção não é permitida em alguns casos.
EDIT2:
Você provavelmente encontrará a resposta lá ...
EDIT1: isso é explicado nos comentários da Parte 5, na resposta de Eric ao comentário de Abhijeet Patel:
Q:
UMA :
fonte
Eric Lippert escreveu uma excelente série de artigos sobre as limitações (e decisões de design que influenciam essas escolhas) nos blocos iteradores
Em particular, os blocos iteradores são implementados por algumas transformações de código do compilador sofisticadas. Essas transformações impactariam nas transformações que acontecem dentro de funções anônimas ou lambdas, de modo que, em certas circunstâncias, ambos tentariam 'converter' o código em alguma outra construção incompatível com a outra.
Como resultado, eles são proibidos de interação.
O modo como os blocos de iteradores funcionam nos bastidores é bem tratado aqui .
Como um exemplo simples de incompatibilidade:
O compilador deseja simultaneamente converter isso para algo como:
e, ao mesmo tempo, o aspecto do iterador está tentando fazer seu trabalho para fazer uma pequena máquina de estado. Certos exemplos simples podem funcionar com uma boa quantidade de verificação de sanidade (primeiro lidando com os fechamentos aninhados (possivelmente arbitrariamente)) e depois ver se as classes resultantes de nível inferior poderiam ser transformadas em máquinas de estado iterador.
No entanto, isso seria
Em seu exemplo:
fonte
Magic
classe deveria serMagic<T>
.Infelizmente, não sei por que eles não permitiram isso, já que é perfeitamente possível imaginar como isso funcionaria.
No entanto, os métodos anônimos já são uma peça da "mágica do compilador", no sentido de que o método será extraído para um método na classe existente ou até mesmo para uma classe totalmente nova, dependendo se ela lida com variáveis locais ou não.
Além disso, métodos iterativos usando
yield
também são implementados usando a mágica do compilador.Meu palpite é que um desses dois torna o código não identificável para a outra mágica e que foi decidido não perder tempo fazendo esse trabalho para as versões atuais do compilador C #. Claro, pode não ser uma escolha consciente, e simplesmente não funciona porque ninguém pensou em implementá-la.
Para uma pergunta 100% precisa, sugiro que você use o site Microsoft Connect e relate uma pergunta, tenho certeza de que você receberá algo utilizável em troca.
fonte
Eu faria isso:
É claro que você precisa do System.Core.dll referenciado do .NET 3.5 para o método Linq. E inclui:
Felicidades,
Astuto
fonte
Talvez seja apenas uma limitação de sintaxe. No Visual Basic .NET, que é muito semelhante ao C #, é perfeitamente possível, embora seja difícil de escrever
Observe também os parênteses
' here
; a função lambdaIterator Function
...End Function
retorna umIEnumerable(Of Integer)
mas não é esse objeto em si. Deve ser chamado para obter esse objeto.O código convertido por [1] gera erros em C # 7.3 (CS0149):
Eu discordo veementemente do motivo dado nas outras respostas que é difícil para o compilador manipular. O que
Iterator Function()
você vê no exemplo VB.NET é criado especificamente para iteradores lambda.No VB, existe a
Iterator
palavra - chave; não tem contrapartida em C #. IMHO, não há razão real para que isso não seja um recurso do C #.Portanto, se você realmente deseja funções iteradoras anônimas, use atualmente o Visual Basic ou (não o verifiquei) F #, conforme declarado em um comentário da Parte # 7 na resposta de @Thomas Levesque (use Ctrl + F para F #).
fonte