Написание методов расширения с помощью Action / Func / Delegates / Lambda на VB и C#

StackOverflow https://stackoverflow.com/questions/823157

Вопрос

Во-первых, я не могу разобраться в функциональных / лямбда-аспектах .NET 3.5.Я использую эти функции каждый день в LINQ, но моя проблема заключается в понимании реализации и того, что они на самом деле означают (Lambda?Система.Функция?и т.д. и т.п.)

Имея это в виду, как можно было бы достичь следующего:

В качестве примера, я хотел бы иметь метод расширения для List (Of T), который присваивает свойствам всех объектов в списке определенное значение и возвращает обновленный список (Of T).Это было бы названо так:

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");

Как бы выглядел метод расширения как в VB, так и в C #?

т.е.:

 <Extension()> _
 Public Function UpdateExtension(Of T)(ByVal source As List(Of T), ByVal predicate As ??) As List(Of T)
        '??
 End Function

ваше здоровье!

Редактировать

Как многие отмечали, вышесказанное может быть достигнуто, более или менее, с помощью .ForEach() .Но мой интерес заключается в понимании того, как реализуется что-то вроде .ForEach(), т. е.Я заинтересован в реализации решения вышеуказанной проблемы.

Это было полезно?

Решение

На самом деле вы здесь подбираете и сопоставляете методы расширения.Это почти комбинация Select и ForEach .Похоже, вам нужен метод, который позволит вам как изменять элементы списка, так и возвращать исходное перечисление.Следующее должно сделать свое дело за вас.

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;
}

Другие советы

За исключением того, что вы изменили бы список на месте, а не возвращали новый, это всего лишь .ForEach() звони.

Чтобы действительно понять, как это работает, больше думайте в терминах IEnumerables, чем Списки.Подумайте о том, почему два приведенных ниже выражения дают одинаковый результат и почему последнее, как правило, предпочтительнее:

MyEnumerable.Count() > 2
MyEnumerable.Skip(2).Any()

Чтобы помочь достичь этого, повторно реализуйте некоторые стандартные IEnumerable расширения, используя C # yield ключевое слово.Как только вы действительно поймете, почему 2-й работает лучше, вы должны быть в хорошей форме.

Что касается различных базовых типов делегатов, вам просто нужно их изучить.Подумайте о Func в качестве вашего базового общего делегата, где вы указываете тип аргумента и возвращаемый тип для параметров универсального типа.Тогда подумайте о Action как частный случай Func где возвращаемый тип равен void и Predicate как особый случай, когда возвращаемым типом является bool.

Расширения реализуются в статическом классе статическими методами, которые принимают целевой объект расширения в качестве первого параметра, которому предшествует ключевое слово this.Чтобы реализовать ваш пример, я бы сделал:

public static class ListBoxExtensions
{
  public static List<TextBox> SetToValue(this List<TextBox> txtBoxes, string sValue)
  {
    txtBoxes.ForEach(txtBox => txtBox.Text = sValue);
    return txtBoxes;
  }
}

и использовать это в форме Windows с 3 текстовыми полями:

private void Form1_Load(object sender, EventArgs e)
{
  List<TextBox> boxes = new List<TextBox>
                        {
                          textBox1,
                          textBox2,
                          textBox3
                        }.SetToValue("Hello");
}

Извините - не говорите на VB.

Надеюсь, это поможет.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top