【问题标题】:Writing Extension methods with Action / Func / Delegates / Lambda in VB and C#在 VB 和 C# 中使用 Action / Func / Delegates / Lambda 编写扩展方法
【发布时间】:2009-05-05 03:15:42
【问题描述】:

首先,我无法理解 .NET 3.5 的功能/Lambda 方面。我每天在 LINQ 中使用这些功能,但我的问题是理解实现,以及它们的真正含义(Lambda?System.Func?等)

考虑到这一点,如何实现以下目标:

例如,我想要一个 List(Of T) 的扩展方法,它将 List 中所有对象的属性设置为某个值,并返回更新后的 List(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() 之类的实现方式,即我对上述问题的解决方案的实现感兴趣。

【问题讨论】:

  • 但是,ForEach 不会返回您可以分配给变量的文本框列表(在您的示例代码中无论如何都是空的)。

标签: .net functional-programming delegates lambda extension-methods


【解决方案1】:

你真的是在这里模仿和匹配扩展方法。它几乎是 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;
}

【讨论】:

  • + 1 嗯...有趣。请原谅我的无知,所以你是说,通过在方法调用中表达一个 lambda 表达式,即“obj=>obj.date = Now”,我在实现中所要做的就是执行那个委托/动作/函数?
  • @andy 是的。此版本将对集合中的每个对象执行一次。
  • 不应该是 IEnumerable 的“收益回报”吗?
  • @Benjol,没有。这样做会创建一组 IEnumerable 的返回值。我想返回一个 IEnumerable
【解决方案2】:

除了您将修改列表而不是返回新列表之外,这只是一个.ForEach() 调用。

要真正理解其工作原理,请多考虑IEnumerables 而不是列表。想想为什么下面的两个表达式有相同的结果为什么后者通常更可取:

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

为了帮助实现这一点,使用 C# 的 yield 关键字重新实现一些标准的 IEnumerable 扩展。一旦你真正明白为什么 2nd 表现更好,你应该处于良好状态。

至于不同的基本委托类型,您只需要了解它们即可。将Func 视为您的基本公共委托,您可以在其中指定泛型类型参数的实参类型和返回类型。然后将Action 视为Func 的特例,返回类型为void,Predicate 视为返回类型为bool 的特例。

【讨论】:

  • + 1 嘿乔尔,感谢您对不同代表类型的提醒。用简单的英语解释它很有用。我明白你对 .ForEach() 的意思,但无论如何你可以告诉我它是如何实现的?我只是需要看到它开始理解它,你知道的,干杯
【解决方案3】:

扩展是通过静态方法在静态类中实现的,这些静态方法将扩展的目标作为第一个参数,前面带有 this 关键字。为了实现你的例子,我会这样做:

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

并在带有 3 个文本框的 Windows 窗体上使用它:

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

抱歉 - 不要说 VB。

希望这会有所帮助。

【讨论】:

  • 哈哈,没问题,我才刚开始C#。很酷,我不知道 ForEach,但我更感兴趣的是,例如 ForEach 是如何实现的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-01
相关资源
最近更新 更多