От моего наставника: Предпочитайте собственные методы (реализованные непосредственно в коллекции) над методами расширения IEnumerable, потому что:
Методы расширения LINQ-to-Objects реализованы на IEnumerable, это означает, что в худшем случае сценарий (когда предмет, который вы ищете не существует в коллекции) ты придется перечислять через все элементы. Если у вас есть Contains или Существует метод, реализованный непосредственно на коллекцию, он мог бы использовать внутренние знания и, возможно, просто поиск по хеш-таблице или другой быстрый
Я был глубоко сбит с толку, потому что считаю, что Microsoft уже должна была реализовать хеш-таблицу для IEnumerable Contains / Exists. Быстрый тест с помощью List и IEnumerable не показал различий:
static void Main(string[] args)
{
Console.Write("input the number of elements: ");
int count = Convert.ToInt32(Console.ReadLine());
Console.Write("input the number of loops: ");
int loop = Convert.ToInt32(Console.ReadLine());
Random r = new Random();
Stopwatch sw = new Stopwatch();
for (int i = 0; i < loop; i++)
{
var list = CreateListOfInt(count);
sw.Start();
for (int j = 0; j < count; j++)
{
DoContains(list, r.Next());
}
sw.Stop();
}
Console.WriteLine("List<T> native method: Iterated {0} times on {1} elements, elapsed :{2}",loop,count,sw.Elapsed);
sw.Reset();
for (int i = 0; i < loop; i++)
{
var list = CreateListOfInt(count);
sw.Start();
for (int j = 0; j < count; j++)
{
DoContainsEnumerable(list, r.Next());
}
sw.Stop();
}
Console.WriteLine("IEnumerable<T> extension method: Iterated {0} times on {1} elements, elapsed :{2}", loop, count, sw.Elapsed);
sw.Reset();
for (int i = 0; i < loop; i++)
{
var list = CreateListOfInt2(count);
sw.Start();
for (int j = 0; j < count; j++)
{
//make sure that the element is not in the list
DoContains(list, r.Next(20000, 50000));
}
sw.Stop();
}
Console.WriteLine("List<T> native method: element does not exist:Iterated {0} times on {1} elements, elapsed :{2}", loop, count, sw.Elapsed);
sw.Reset();
for (int i = 0; i < loop; i++)
{
var list = CreateListOfInt2(count);
sw.Start();
for (int j = 0; j < count; j++)
{
//make sure that the element is not in the list
DoContainsEnumerable(list, r.Next(20000, 50000));
}
sw.Stop();
}
Console.WriteLine("IEnumerable<T> extension method: element does not exist: Iterated {0} times on {1} elements, elapsed :{2}", loop, count, sw.Elapsed);
Console.ReadKey();
}
static List<int> CreateListOfInt(int count)
{
Random r = new Random(1000);
List<int> numbers = new List<int>(count);
for (int i = 0; i < count; i++)
{
numbers.Add(r.Next());
}
return numbers;
}
static bool DoContains(List<int> list, int number)
{
return list.Contains(number);
}
static bool DoContainsEnumerable(IEnumerable<int> list, int number)
{
return list.Contains(number);
}
//define the scope of randomly created number, to make sure that lookup number will not in the List
static List<int> CreateListOfInt2(int count)
{
Random r = new Random(1000);
List<int> numbers = new List<int>(count);
for (int i = 0; i < count; i++)
{
numbers.Add(r.Next(0,10000));
}
return numbers;
}
}
Edit: Я пробовал реализацию HashSet, которая значительно увеличивает производительность:
sw.Reset();
for (int i = 0; i < loop; i++)
{
var list = CreateListOfInt2(count);
HashSet<int> hashtable = new HashSet<int>(list);
sw.Start();
for (int j = 0; j < count; j++)
{
//make sure that the element is not in the list
hashtable.Contains(r.Next(20000, 50000));
}
sw.Stop();
}
Console.WriteLine("IEnumerable<T> extension method: element does not exist: Iterated {0} times on {1} elements, elapsed :{2}", loop, count, sw.Elapsed);
Тем не менее, что вы думаете о том, что говорит мой наставник?
Кто-нибудь может прояснить для меня? Прав ли мой наставник? Если он прав, что не так с моим кодом?
Большое спасибо