bil*_*aya 15 .net c# vb.net generics collections
在C#.NET和VB.NET中迭代强类型泛型List的最佳方法是什么?
mbi*_*ard 30
对于C#:
foreach(ObjectType objectItem in objectTypeList)
{
// ...do some stuff
}
Run Code Online (Sandbox Code Playgroud)
从Purple Ant回答VB.NET :
For Each objectItem as ObjectType in objectTypeList
'Do some stuff '
Next
Run Code Online (Sandbox Code Playgroud)
Kei*_*ith 20
对于IEnumerable的任何通用实现,最好的方法是:
//C#
foreach( var item in listVariable) {
//do stuff
}
Run Code Online (Sandbox Code Playgroud)
但是有一个重要的例外.IEnumerable涉及Current()和MoveNext()的开销,这是foreach循环实际编译成的内容.
当你有一个简单的结构数组:
//C#
int[] valueTypeArray;
for(int i=0; i < valueTypeArray.Length; ++i) {
int item = valueTypeArray[i];
//do stuff
}
Run Code Online (Sandbox Code Playgroud)
更快.
更新
在与@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();
Run Code Online (Sandbox Code Playgroud)
所以,我在发布中运行了所有优化:
list foreach: 00:00:00.5137506
list for : 00:00:00.2417709
array foreach: 00:00:00.1085653
array for : 00:00:00.0954890
Run Code Online (Sandbox Code Playgroud)
然后调试没有优化:
list foreach: 00:00:01.1289015
list for : 00:00:00.9945345
array foreach: 00:00:00.6405422
array for : 00:00:00.4913245
Run Code Online (Sandbox Code Playgroud)
所以它看起来相当一致,for比foreach数组更快,而且数组比通用列表更快.
然而,这是100,000,000次迭代,差异大约是最快和最慢方法之间的.4秒.除非你正在进行大规模的性能关键循环,否则不值得担心.
C#
myList<string>().ForEach(
delegate(string name)
{
Console.WriteLine(name);
});
Run Code Online (Sandbox Code Playgroud)
匿名委托目前未在 VB.Net 中实现,但 C# 和 VB.Net 都应该能够执行 lambdas:
C#
myList<string>().ForEach(name => Console.WriteLine(name));
Run Code Online (Sandbox Code Playgroud)
VB.Net
myList(Of String)().ForEach(Function(name) Console.WriteLine(name))
Run Code Online (Sandbox Code Playgroud)
正如 Grauenwolf 指出的那样,上面的 VB 不会编译,因为 lambda 不返回值。正如其他人所建议的那样,一个普通的 ForEach 循环现在可能是最简单的,但像往常一样,它需要一段代码来完成 C# 可以在一行中完成的工作。
这是一个说明为什么这可能有用的陈腐示例:这使您能够从 IEnumerable 所在的其他范围传入循环逻辑,因此如果您不想,您甚至不必公开它。
假设您有一个要设为绝对的相对 url 路径列表:
public IEnumerable<String> Paths(Func<String> formatter) {
List<String> paths = new List<String>()
{
"/about", "/contact", "/services"
};
return paths.ForEach(formatter);
}
Run Code Online (Sandbox Code Playgroud)
那么你可以这样调用函数:
var hostname = "myhost.com";
var formatter = f => String.Format("http://{0}{1}", hostname, f);
IEnumerable<String> absolutePaths = Paths(formatter);
Run Code Online (Sandbox Code Playgroud)
给你"http://myhost.com/about", "http://myhost.com/contact"等等。显然在这个特定的例子中有更好的方法来实现这一点,我只是想演示基本原理。