Ответ 1
Для С#:
foreach(ObjectType objectItem in objectTypeList)
{
// ...do some stuff
}
Ответ для VB.NET от Фиолетовый Ant:
For Each objectItem as ObjectType in objectTypeList
'Do some stuff '
Next
Каков наилучший способ перебора строго типизированного списка в С#.NET и VB.NET?
Для С#:
foreach(ObjectType objectItem in objectTypeList)
{
// ...do some stuff
}
Ответ для VB.NET от Фиолетовый Ant:
For Each objectItem as ObjectType in objectTypeList
'Do some stuff '
Next
При любой общей реализации 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
Таким образом, он выглядит достаточно согласованным, for
быстрее, чем foreach
, а массивы быстрее, чем общие списки.
Однако это более 100 000 000 итераций, и разница составляет около 0,4 секунды между самыми быстрыми и самыми медленными методами. Если вы не делаете массивные критические кривые производительности, просто не стоит беспокоиться.
Для VB.NET:
For Each tmpObject as ObjectType in ObjectTypeList
'Do some stuff '
Next
С#
myList<string>().ForEach(
delegate(string name)
{
Console.WriteLine(name);
});
Анонимные делегаты в настоящее время не реализованы в VB.Net, но оба С# и VB.Net должны иметь возможность делать lambdas:
С#
myList<string>().ForEach(name => Console.WriteLine(name));
VB.Net
myList(Of String)().ForEach(Function(name) Console.WriteLine(name))
Как отметил Грауэнволф, вышеупомянутый VB не будет компилироваться, поскольку лямбда не возвращает значение. Обычный цикл ForEach, как и другие, предположил, вероятно, самый простой на данный момент, но, как обычно, блок блок выполняет то, что С# может делать в одной строке.
Вот банальный пример того, почему это может быть полезно: это дает вам возможность передавать логику цикла из другой области, кроме IEnumerable, поэтому вам даже не нужно ее раскрывать, если вы не хотите к.
Скажите, что у вас есть список относительных путей URL, которые вы хотите сделать абсолютными:
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"
и т.д. Очевидно, что есть лучшие способы выполнить это в этом конкретном примере, я просто пытаюсь продемонстрировать основной принцип.
Не зная внутренней реализации списка, я думаю, что лучший способ перебора по ней - это цикл foreach. Поскольку foreach использует IEnumerator для переходов по списку, это зависит от самого списка, чтобы определить, как перемещаться из объекта в объект.
Если внутренняя реализация была, скажем, связанным списком, то простой цикл был бы довольно медленным, чем foreach.
Это имеет смысл?
Это зависит от вашего приложения:
Мне может быть что-то не хватает, но повторение через общий список должно быть довольно простым, если вы используете мои примеры ниже. Класс List < > реализует интерфейсы IList и IEnumerable, так что вы можете легко перебирать их в основном любым способом, который вы хотите.
Наиболее эффективным способом было бы использовать цикл for:
for(int i = 0; i < genericList.Count; ++i)
{
// Loop body
}
Вы также можете использовать цикл foreach:
foreach(<insertTypeHere> o in genericList)
{
// Loop body
}