Мне нужно повторять и подсчитывать. Что является самым быстрым или предпочтительным: ToArray() или ToList()?

Возможный дубликат:
Лучше ли вызывать ToList() или ToArray() в запросах LINQ?

У меня такой код:

void Foobar(string[] arr, Dictionary<string, string[]>)
{
   var t = arr.Intersect(dic.Keys).ToList(); // .or ToArray() ?
   foreach(var item in t)
   {
      ..
   }

   var j = t.Count; // also I need this
}

какой способ является предпочтительным?

Я мог бы обойтись без каких-либо, но мне нужно знать размер, и я не хочу называть Enumerable.Count<T>() - кажется, делают больше действий, а затем Array<T>.Size или List<T>.Count. Я прав?

Ответ 1

Собственно, в текущей MS-реализации Count (IEnumerable) есть ярлык, который ищет, если IEnumerable является ICollection и вызывает Count на нем. Таким образом, производительность должна быть сопоставимой для подсчета элементов.

ToList и ToArray немного то же самое. Если IEnumerable является ICollection, тогда вместо него вызывается метод CopyTo, который немного быстрее.

Итак, выберите то, что делает ваш код наиболее читаемым, и контрольный показатель для вашего варианта использования, чтобы иметь определенный ответ.

Обновление: Я сделал наивный бенчмарк.

Начиная с массива: var items = Enumerable.Range(1,1000).ToArray();

  • вызов ToList(): 25ms/10000
  • вызов ToArray(): 23 мс /10000

Начиная с IEnumerable: var items = Enumerable.Range(1,1000);

  • вызов ToList(): 168 мс /10000
  • вызов ToArray(): 171 мс /10000

Таким образом, вы получаете сопоставимую производительность.

Ответ 2

Если вы действительно обеспокоены производительностью, вы должны перебрать IEnumerable и считать это, когда идете. Это позволяет избежать создания новой коллекции в целом, и пересечение нужно повторить только один раз:

void Foobar(string[] arr, Dictionary<string, string[]>)
{
   var t = arr.Intersect(dic.Keys);
   int count = 0;
   foreach(var item in t)
   {
      count++;
      ..
   }

   var j = count;
}

Но, как и кто-то другой, это пахнет микро-оптимизацией. Если производительность действительно имеет значение в этой ситуации, по крайней мере, профилирование производительности, чтобы выяснить, какой метод действительно самый быстрый для вас.

Ответ 3

Разница, вероятно, настолько мала, что стоит просто использовать метод, который лучше всего соответствует вашим потребностям. Запахи микро-оптимизации.

И в этом случае, поскольку все, что вы делаете, это перечисление множества и подсчет множества (оба из которых вы можете сделать с IEnumerable), почему бы просто не оставить его как IEnumerable < > ?