Visual Basic中的Action(Of T)和List(Of T).ForEach。

11
我已经费尽心思寻找如何使用此功能的文档。虽然我可以编写简单且不需要时间的循环,但我真的想学习如何使用它。
基本上,我有一个类,比如说,Widget,其中包含一个返回空值的Save()子程序。因此:
Dim w as New Widget()
w.Save()

基本上是保存小部件。现在假设我有一个通用集合List(Of Widget),名称为widgetList(Of Widget),我想在该列表中的每个项目上运行Save()。它说我可以这样做:

widgetList.ForEach([enter Action(Of T) here])

但是这到底是如何工作的呢?在内部博客上完全找不到任何文档。非常感激提供帮助。


PS:我对Lambda函数进行了一些研究,并尝试了一些技巧,但是我无法使它们中的任何一个起作用...唉... - Jason
如果您正在使用Visual Studio 2005,则无法在VB中访问Lamda表达式。 - Patrick McDonald
5个回答

17

嗯,我现在已经过时了... :-) 但在VB中是这样的:

widgetList.ForEach(Sub(w) w.Save())

或者更加复杂的情况:

widgetList.ForEach(New Action(Of Widged)(Sub(w As Widged) w.Save()))

13
如果您正在使用VB9(VS2008),我认为您将无法轻松使用匿名函数 - 据我所知,VB9中的匿名函数必须是真正的函数(即它们必须返回一个值),而Action<T>并不返回任何内容。C# 2的匿名方法和C# 3的lambda表达式更加通用,这就是为什么您会看到许多使用C#的List<T>.ForEach示例,但很少有使用VB的原因 :(
您可以潜在地编写一个MakeAction包装器,它接受Function<T,TResult>并返回一个Action<T>,但我怀疑VB9匿名函数的其他限制会使这种做法变得不切实际。
好消息是,VB10具有更多的匿名函数支持。(C#4和VB10正在获得彼此的功能 - 我相信微软正在尝试从现在开始实现语言平衡,比以前更大程度上。)
在那之前,要使用List<T>.ForEach,您需要编写一个适当的Sub并使用AddressOf从中创建委托。这是一个小例子:
Imports System
Imports System.Collections.Generic

Public Class Test

    Shared Sub Main()
        Dim names as New List(Of String)
        names.Add("Jon")
        names.Add("Holly")
        names.ForEach(AddressOf PrintMe)

    End Sub

    Shared Sub PrintMe(ByVal text as String)
        Console.WriteLine(text)
    End Sub

End Class

谢谢你,也感谢你提供的例子!我希望有一种更好的方法,而不是让我的类函数列表变得更加混乱,但现在这个方法可以用! - Jason
这不是特别实际,对吧? - Filip Ekberg

1
new Action(Of T)(AddressOf Widget.Save) 

如果 Widget 有一个名为 Save 的公共函数,那就没问题。

我尝试了其他所有的评论都是错误的。


0
假设VB不支持lambda表达式,您可以使用以下语法在VB中创建Action(of T)委托的实例:
new Action(Of T)(AddressOf Widget.Save)

-2

以下代码应该可以工作,但我对VB.Net不是很熟悉,所以你可能需要进行相应的调整。

widgetList.ForEach(w => w.Save())

2
这就是问题所在... C#和VB在这方面有很大的不同,所以我需要VB的语法..... - Jason

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接