Вопрос интервью: .Any () против if (.Length> 0) для проверки наличия в коллекции элементов - PullRequest
17 голосов
/ 07 июня 2010

В недавнем интервью меня спросили, в чем разница между .Any() и .Length > 0 и почему я буду использовать любой из них при тестировании, чтобы увидеть, есть ли в коллекции элементы.

Это меня немного смутило, так как это кажется немного очевидным, но я чувствую, что могу что-то упустить.

Я предложил использовать .Length, когда вам просто нужно знать, что в коллекции есть элементы, и .Any(), когда вы хотите отфильтровать результаты.

Предположительно .Any() также снижает производительность, поскольку должен выполнять цикл / запрос внутри.

Ответы [ 8 ]

24 голосов
/ 07 июня 2010

Length существует только для некоторых типов коллекций, таких как Array.

Any - это метод расширения, который можно использовать с любой коллекцией, которая реализует IEnumerable<T>.

Если присутствует Length, вы можете использовать его, в противном случае используйте Any.


Предположительно. Любой () также снижает производительность, поскольку он должен выполнить цикл / запрос внутри.

Enumerable.Any не зацикливается. Он выбирает итератор и проверяет, возвращает ли MoveNext значение true. Вот исходный код .NET Reflector .

public static bool Any<TSource>(this IEnumerable<TSource> source)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    using (IEnumerator<TSource> enumerator = source.GetEnumerator())
    {
        if (enumerator.MoveNext())
        {
            return true;
        }
    }
    return false;
}
12 голосов
/ 07 июня 2010

Я предполагаю, что интервьюер, возможно, хотел спросить о проверке Any() против Count() > 0 (в отличие от Length > 0).

По сути, вот сделка.

Any() будет эффективно пытаться определить, есть ли в коллекции какие-либо члены, путем перечисления по одному элементу. (Существует перегрузка для проверки заданного критерия с использованием Func<T, bool>, но я предполагаю, что интервьюер ссылался на версию Any(), которая не принимает аргументов.) Это делает его O (1).

Count() сначала проверит свойство Length или Count (из T[] или ICollection или ICollection<T>). Обычно это будет O (1). Однако, если это недоступно, он будет считать элементы в коллекции, перечисляя все это. Это будет O (n).

A Count или Length свойство , если оно доступно, скорее всего будет иметь значение O (1) точно так же, как Any(), и, вероятно, будет работать лучше, поскольку вообще не потребует перечисления. Но метод расширения Count() не гарантирует этого. Поэтому иногда это O (1), иногда O (n).

Предположительно, если вы имеете дело с невзрачным IEnumerable<T> и не знаете, реализует ли он ICollection<T> или нет, вам гораздо лучше использовать Any(), чем Count() > 0, если вы намерены просто убедиться, что коллекция не пуста .

1 голос
/ 07 июня 2010

.Длина ... System.Array .Any ... IEnumerable (метод расширения).

Я бы предпочел использовать "длину" всякий раз, когда я могу ее найти. Свойство в любом случае легче, чем любой вызов метода.

Хотя реализация «Any» не будет делать ничего, кроме приведенного ниже кода.

 private static bool Any<T>(this IEnumerable<T> items)
        {
            return items!=null && items.GetEnumerator().MoveNext();
        }

Кроме того, Лучшим вопросом могла бы быть разница между ".Count" и ".Length", что сказать:).

1 голос
/ 07 июня 2010

Length является свойством типов массивов, а Any() является методом расширения Enumerable. Следовательно, вы можете использовать длину только при работе с массивами. При работе с более абстрактными типами (IEnumerable<T>) вы можете использовать Any ().

0 голосов
/ 14 декабря 2011

.Length перебирает коллекцию и возвращает количество элементов.Сложность O(n)

.Any проверяет наличие в коллекции хотя бы одного элементаСложность O(1).

0 голосов
/ 07 июня 2010

Мы знаем, что .Length используется только для массивов, а .Any () - для коллекций IEnumerable.

Вы можете поменять .Count на .Length, и у вас возникнет один и тот же вопрос по работе с коллекциями IEnumberable

Оба .Any () и .Count выполняют нулевую проверку перед запуском перечислителя.Так что в отношении производительности они одинаковы.

Что касается массива, давайте предположим, что у нас есть следующая строка:

int[] foo = new int[10];

Здесь foo.Length равно 10. Хотя это правильно, это можетэто не тот ответ, который вы ищете, потому что мы еще ничего не добавили в массив.Если foo имеет значение null, он выдаст исключение.

0 голосов
/ 07 июня 2010

Звучит очень похоже на вопрос Stackoverflow о разнице между .Count и .Any для проверки существования результата: Проверка на наличие результата в Linq-to-xml

В этом случае лучше использовать Any, а затем Count, поскольку Count будет повторять все элементы IEnumerable

0 голосов
/ 07 июня 2010

Я думаю, что это более общий вопрос о том, что выбрать, если у нас есть 2 способа что-то выразить.В такой ситуации я бы предложил следующее высказывание Питера Норвига «Будьте конкретны» в его книге «PAIP»

«Будьте конкретны, используйте то, что лучше всего описывает, что вы делаете».Таким образом, вы хотите сказать что-то вроде:

collection.isEmpty()

Если у вас нет такой конструкции, я выберу общую идиому, которую используют сообщества.Для меня .Length > 0 не самый лучший, так как он предполагает, что вы можете определить размер объекта.Предположим, вы реализуете бесконечный список..Lenght, очевидно, не будет работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...