métodos de escrita de extensão com ação / Func / delegados / lambda em VB e C #
-
05-07-2019 - |
Pergunta
Em primeiro lugar eu não posso colocar minha cabeça em torno dos aspectos funcionais / Lambda de .NET 3.5. Eu uso esses recursos todos os dias em LINQ, mas o meu problema é entender a implementação, eo que eles realmente querem dizer (Lambda? System.Func? Etc etc)
Com isto em mente, como seria o seguinte ser alcançado:
Como um exemplo, eu gostaria de ter um método de extensão para List (Of T), que define as propriedades de todos os objetos na lista para um determinado valor, e retorna a lista atualizada (Of T). Ele seria chamado assim:
VB:
Dim someList As List(Of TextBox) = (New List(Of TextBox)).UpdateExtension(Function(txtb) txtb.Text = "something")
C #:
List<TextBox> someList = (new List<TextBox>()).UpdateExtension(txtb => txtb.Text = "something");
O que seria o método visual de extensão como, tanto em VB e C #?
ou seja:
<Extension()> _
Public Function UpdateExtension(Of T)(ByVal source As List(Of T), ByVal predicate As ??) As List(Of T)
'??
End Function
aplausos!
Editar
Como muitos têm apontado, o acima pode ser alcançado, mais ou menos, com .ForEach (). Mas o meu interesse é em understading como algo como .ForEach () é implementado, ou seja, eu estou interessado na implementação da solução para o problema acima.
Solução
Realmente você está microfonação e métodos de extensão de harmonização aqui. É quase uma combinação de Select e ForEach. Parece que você quer um método que irá permitir-lhe ambos os elementos Modificar do uma lista e voltar a enumeração originais. A seguir deve fazer o truque para você.
VB.Net
<Extension()> _
Public Function UpdateExtension(Of T)(ByVal source As IEnumerable(Of T), ByVal del As Action(Of T)) As IEnumerable(Of T)
For Each cur in source
del(cur)
Next
Return source
End Function
C #
public static IEnumerable<T> UpdateExtension<T>(this IEnumerable<T> source, Action<T> del) {
foreach ( var cur in source ) {
del(cur);
}
return source;
}
Outras dicas
Com a excepção de que iria modificar a lista no lugar em vez de retornar um novo, esta é apenas uma chamada .ForEach()
.
Para realmente entender como isso funciona, pense mais em termos de IEnumerable
s que listas. Pense sobre por que as duas expressões abaixo têm o mesmo resultado e porque o último é geralmente preferível:
MyEnumerable.Count() > 2
MyEnumerable.Skip(2).Any()
Para ajudar a alcançar este objetivo, re-implementar algumas extensões IEnumerable padrão usando C # 's yield
palavra-chave. Uma vez que você realmente entendo porque o 2º executa melhor que você deve estar em boa forma.
Como para os diferentes tipos básicos de delegado, você só precisa aprender deles. Pense Func
como seu delegado comum básico, onde é possível especificar o tipo de argumento e tipo de retorno para os parâmetros de tipo genérico. Então, pense em Action
como um caso especial de Func
onde o tipo de retorno é nulo e Predicate
como um caso especial em que o tipo de retorno é bool.
Extensões são implementados em uma classe estática por métodos estáticos que tomam o alvo da extensão como o primeiro parâmetro precedido pela palavra-chave this. Para implementar o exemplo que eu faria:
public static class ListBoxExtensions
{
public static List<TextBox> SetToValue(this List<TextBox> txtBoxes, string sValue)
{
txtBoxes.ForEach(txtBox => txtBox.Text = sValue);
return txtBoxes;
}
}
e usar isso em um formulário do Windows com 3 caixas de texto:
private void Form1_Load(object sender, EventArgs e)
{
List<TextBox> boxes = new List<TextBox>
{
textBox1,
textBox2,
textBox3
}.SetToValue("Hello");
}
Sorry -. Não falam VB
Espero que isso ajude.