迭代强类型泛型List <t>的最佳方法是什么?</t>

时间:2008-08-18 20:49:22

标签: c# .net vb.net generics collections

在C#.NET和VB.NET中迭代强类型泛型List的最佳方法是什么?

7 个答案:

答案 0 :(得分:30)

对于C#:

foreach(ObjectType objectItem in objectTypeList)
{
    // ...do some stuff
}

Purple Ant

回答VB.NET
For Each objectItem as ObjectType in objectTypeList
    'Do some stuff '
Next

答案 1 :(得分:20)

对于IEnumerable的任何通用实现,最好的方法是:

//C#
foreach( var item in listVariable) {
    //do stuff
}

但是有一个重要的例外。 IEnumerable涉及Current()和MoveNext()的开销,这是foreach循环实际编译成的内容。

当你有一个简单的结构数组时:

//C#
int[] valueTypeArray;
for(int i=0; i < valueTypeArray.Length; ++i) {
     int item = valueTypeArray[i];
     //do stuff
}

更快。


<强>更新

在与@Steven Sudit讨论之后(见评论)我认为我的原始建议可能已经过时或有误,所以我进行了一些测试:

// create a list to test with
var theList = Enumerable.Range(0, 100000000).ToList();

// time foreach
var sw = Stopwatch.StartNew();
foreach (var item in theList)
{
    int inLoop = item;
}
Console.WriteLine("list  foreach: " + sw.Elapsed.ToString());

sw.Reset();
sw.Start();

// time for
int cnt = theList.Count;
for (int i = 0; i < cnt; i++)
{
    int inLoop = theList[i];
}
Console.WriteLine("list  for    : " + sw.Elapsed.ToString());

// now run the same tests, but with an array
var theArray = theList.ToArray();

sw.Reset();
sw.Start();

foreach (var item in theArray)
{
    int inLoop = item;
}
Console.WriteLine("array foreach: " + sw.Elapsed.ToString());

sw.Reset();
sw.Start();

// time for
cnt = theArray.Length;
for (int i = 0; i < cnt; i++)
{
    int inLoop = theArray[i];
}
Console.WriteLine("array for    : " + sw.Elapsed.ToString());

Console.ReadKey();

所以,我在发布时运行了所有优化:

list  foreach: 00:00:00.5137506
list  for    : 00:00:00.2417709
array foreach: 00:00:00.1085653
array for    : 00:00:00.0954890

然后调试没有优化:

list  foreach: 00:00:01.1289015
list  for    : 00:00:00.9945345
array foreach: 00:00:00.6405422
array for    : 00:00:00.4913245

所以看起来相当一致,forforeach更快,数组比通用列表更快。

然而,这是100,000,000次迭代,差异大约是最快和最慢方法之间的.4秒。除非你正在进行大规模的性能关​​键循环,否则不值得担心。

答案 2 :(得分:4)

对于VB.NET:

For Each tmpObject as ObjectType in ObjectTypeList
    'Do some stuff '
Next

答案 3 :(得分:4)

C#

myList<string>().ForEach(
    delegate(string name)
    {
        Console.WriteLine(name);
    });

匿名委托目前尚未在VB.Net中实现,但C#和VB.Net都应该能够执行lambdas:

C#

myList<string>().ForEach(name => Console.WriteLine(name));

VB.Net

myList(Of String)().ForEach(Function(name) Console.WriteLine(name))

正如Grauenwolf指出的那样,上面的VB不会编译,因为lambda没有返回值。正如其他人所建议的那样,正常的ForEach循环现在可能是最简单的,但像往常一样,需要一段代码来完成C#在一行中可以做的事情。


这是一个很有用的例子,说明为什么这可能有用:这使你能够从IEnumerable存在的另一个范围传递循环逻辑,所以如果你不想要你甚至不必暴露它到。

假设您有一个绝对的相对网址路径列表:

public IEnumerable<String> Paths(Func<String> formatter) {
    List<String> paths = new List<String>()
    {
        "/about", "/contact", "/services"
    };

    return paths.ForEach(formatter);
}

那么你可以用这种方式调用函数:

var hostname = "myhost.com";
var formatter = f => String.Format("http://{0}{1}", hostname, f);
IEnumerable<String> absolutePaths = Paths(formatter);

给你"http://myhost.com/about", "http://myhost.com/contact"等。显然,在这个具体的例子中有更好的方法可以实现这一点,我只是想证明基本原则。

答案 4 :(得分:2)

在不知道列表的内部实现的情况下,我认为通常迭代它的最佳方法是foreach循环。因为foreach使用IEnumerator遍历列表,所以由列表本身决定如何从对象移动到对象。

如果内部实现是一个链表,那么一个简单的for循环会比foreach慢一点。

这有意义吗?

答案 5 :(得分:2)

这取决于您的申请:

  • for循环,如果效率是优先考虑的话
  • foreach循环或ForEach方法,无论哪个更清楚地传达您的意图

答案 6 :(得分:1)

我可能会遗漏一些东西,但如果您使用下面的示例,则迭代通用列表应该相当简单。列表&lt;&gt; class实现IList和IEnumerable接口,以便您可以基本上以任何方式轻松地遍历它们。

最有效的方法是使用for循环:

for(int i = 0; i < genericList.Count; ++i) 
{
     // Loop body
}

您也可以选择使用foreach循环:

foreach(<insertTypeHere> o in genericList)
{
    // Loop body
}