Since there seems some debate about how much faster it would be to use List.FindIndex()
instead of Linq to find the index, I wrote a test program.
This assumes that you only care about finding the index of the first matching item in a list. It doesn't handle multiple matching items.
Also note that this test is worst-case in that the matching item is at the very end of the list.
My results for an x86 release build (run on Windows 8 x64, quad core processor):
Calling Via FindIndex() 100 times took 00:00:00.9326057
Calling Via Linq 100 times took 00:00:04.0014677
Calling Via FindIndex() 100 times took 00:00:00.8994282
Calling Via Linq 100 times took 00:00:03.9179414
Calling Via FindIndex() 100 times took 00:00:00.8971618
Calling Via Linq 100 times took 00:00:03.9134804
Calling Via FindIndex() 100 times took 00:00:00.8963758
showing that List.FindIndex()
is roughly four times faster than using Linq.
Here's the test code:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace Demo
{
class Test
{
public string FilePath;
}
class Program
{
private void run()
{
int count = 1000000;
List<Test> list = new List<Test>(count);
for (int i = 0; i < count; ++i)
list.Add(new Test{ FilePath = i.ToString()});
string target = (count-1).ToString();
for (int trial = 0; trial < 4; ++trial)
{
Action viaFindIndex =
(
() =>
{
int index = list.FindIndex(x => (x != null) && (x.FilePath == target));
}
);
Action viaLinq =
(
() =>
{
int index = list.Select((x, i) => new { Item = x, Index = i })
.First(x => (x != null) && (x.Item.FilePath == target))
.Index;
}
);
viaFindIndex.TimeThis("Via FindIndex()", 100);
viaLinq.TimeThis("Via Linq", 100);
}
}
private static void Main()
{
new Program().run();
}
}
static class DemoUtil
{
public static void TimeThis(this Action action, string title, int count = 1)
{
var sw = Stopwatch.StartNew();
for (int i = 0; i < count; ++i)
action();
Console.WriteLine("Calling {0} {1} times took {2}", title, count, sw.Elapsed);
}
}
}
So given that List.FindIndex()
is both much faster AND much easier to read than using the Linq, I can see no reason to use Linq to solve this particular problem.
int index = list.FindIndex(x => (x != null) && (x.FilePath == target));
versus
int index = list.Select((x, i) => new { Item = x, Index = i })
.First(x => (x != null) && (x.Item.FilePath == target))
.Index;
The first version wins on all counts IMO.