Почему List.All (a.this! = That) предпочитает! List.Any (a.this = that) [duplicate]

Указатель NULL - это тот, который указывает на никуда. Когда вы разыскиваете указатель p, вы говорите «дайте мне данные в месте, хранящемся в« p ». Когда p является нулевым указателем, местоположение, хранящееся в p, является nowhere, вы говорите «Дайте мне данные в месте« нигде ». Очевидно, он не может этого сделать, поэтому он выбрасывает NULL pointer exception.

В общем, это потому, что что-то не было правильно инициализировано.

240
задан Jon Hanna 11 May 2015 в 20:09
поделиться

8 ответов

Реализация All в соответствии с ILSpy (как в действительности я пошла и посмотрела, а не «хорошо, этот метод немного похож ...» Я мог бы сделать, если бы мы обсуждали теорию, а не влияние) .

public static bool All<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    if (predicate == null)
    {
        throw Error.ArgumentNull("predicate");
    }
    foreach (TSource current in source)
    {
        if (!predicate(current))
        {
            return false;
        }
    }
    return true;
}

Реализация Any в соответствии с ILSpy:

public static bool Any<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    if (predicate == null)
    {
        throw Error.ArgumentNull("predicate");
    }
    foreach (TSource current in source)
    {
        if (predicate(current))
        {
            return true;
        }
    }
    return false;
}

Конечно, может быть какая-то тонкая разница в произведенном IL. Но нет, нет, нет. IL - это почти то же самое, но для очевидной инверсии возврата истины в соответствие с предикатом по сравнению с возвратом false при несоответствии предикатов.

Это, конечно, linq-for-objects. Возможно, что какой-то другой провайдер linq рассматривает один гораздо лучше, чем другой, но если это так, то довольно случайный, который получает более оптимальную реализацию.

Казалось бы, исключительно для тех, кто чувствует, что if(determineSomethingTrue) проще и читабельнее, чем if(!determineSomethingFalse). И, честно говоря, я думаю, что у них немного точка в том, что я часто нахожу if(!someTest) запутанной *, когда есть альтернативный тест с равной многословностью и сложностью, который вернет true для условия, на которое мы хотим действовать. Тем не менее, на самом деле, я лично не нахожу ничего, чтобы одобрить одну из двух альтернатив, которые вы даете, и, возможно, немного наклонился бы к первому, если бы предикат был более сложным.

* Не путайте, как в I don я не понимаю, но смущаю, как в том, что я беспокоюсь, что есть какая-то тонкая причина для решения, которое я не понимаю, и требуется несколько умственных пропусков, чтобы понять, что «нет, они просто решили сделать это таким образом, подождать, что было Я снова смотрю этот бит кода? ... "

300
ответ дан Jon Hanna 19 August 2018 в 02:21
поделиться
  • 1
    Фантастический ответ - код подтверждает это! – Mark 27 January 2012 в 04:30
  • 2
    Я не уверен, что делается за строками, но для меня гораздо более читабельным является: if (не любое), чем if (все не равные). – VikciaR 7 August 2012 в 07:15
  • 3
    Существует большая разница, когда ваше перечисление не имеет значений. «Any» всегда возвращает FALSE, а «All» всегда возвращает TRUE. Поэтому говорить, что один из них является логическим эквивалентом другого, не совсем верно! – Arnaud 25 March 2013 в 00:41
  • 4
    @Arnaud Any вернет false и, следовательно, !Any вернет true, поэтому они будут идентичны. – Jon Hanna 30 May 2013 в 11:31
  • 5
    – Jim Balter 20 August 2013 в 06:50
  • 6
    @MacsDickinson, это совсем не так, потому что вы не сравниваете противоположные предикаты. Эквивалент !test.Any(x => x.Key == 3 && x.Value == 1), который использует All, равен test.All(x => !(x.Key == 3 && x.Value == 1)) (что действительно эквивалентно test.All(x => x.Key != 3 || x.Value != 1)). – Jon Hanna 18 September 2013 в 15:05

Вы можете обнаружить, что эти методы расширения делают ваш код более удобочитаемым:

public static bool None<TSource>(this IEnumerable<TSource> source)
{
    return !source.Any();
}

public static bool None<TSource>(this IEnumerable<TSource> source, 
                                 Func<TSource, bool> predicate)
{
    return !source.Any(predicate);
}

Теперь вместо исходного

if (!acceptedValues.Any(v => v == someValue))
{
    // exception logic
}

вы можете сказать

if (acceptedValues.None(v => v == someValue))
{
    // exception logic
}
47
ответ дан AakashM 19 August 2018 в 02:21
поделиться
  • 1
    Спасибо. Я уже думал об их реализации в нашей библиотеке, но я еще не решил, что это хорошая идея. Я согласен с тем, что они делают код более удобочитаемым, но я обеспокоен тем, что они не добавляют достаточного значения. – Mark 28 January 2012 в 09:17
  • 2
    Я искал Никого и не нашел. Это очень читаемо. – Rhyous 10 February 2018 в 03:15
  • 3
    Мне пришлось добавить нулевые проверки: return source == null || ! Source.Any (сказуемое); – Rhyous 10 February 2018 в 03:23

All коротких замыканий в первом несоответствии, поэтому это не проблема.

Одна из областей тонкости заключается в том, что

 bool allEven = Enumerable.Empty<int>().All(i => i % 2 == 0); 

Является истинным. Все элементы в последовательности четные.

Подробнее об этом методе см. в документации для Enumerable.All .

17
ответ дан Anthony Pegram 19 August 2018 в 02:21
поделиться
  • 1
  • 2
    @Jon семантически нет! = Все. Таким образом, семантически вы либо не имеете ни одного, либо всего, но в случае .All () none - это всего лишь подмножество всех коллекций, возвращающих true для всех, и это несоответствие может привести к ошибкам, если вы не знаете об этом. +1 для этого Энтони – Rune FS 27 January 2012 в 11:33
  • 3
    @RuneFS Я не следую. Семантически и логически "нет, где это неверно, что ... & quot; действительно то же самое, что и «все, где верно, что». Например. «где ни один из принятых проектов от нашей компании?» всегда будет иметь тот же ответ, что и «где все принятые проекты от других компаний?» ... – Jon Hanna 27 January 2012 в 11:59
  • 4
    ... Теперь, это правда, что у вас могут быть ошибки при допущении & quot; все элементы ... & quot; означает, что существует по меньшей мере один элемент, который является по меньшей мере одним элементом, который выполняет тест, поскольку «все элементы ...» всегда верно для пустого множества, я вообще не оспариваю это. Я добавил, что одна и та же проблема может произойти с допуском «ни одного из элементов ...». означает, что по меньшей мере один элемент не выполняет тест, так как «ни один из элементов ...» также всегда верно для пустого множества. Дело не в том, что я не согласен с точкой Энтони, что, по моему мнению, это относится и к другой из обсуждаемых двух конструкций. – Jon Hanna 27 January 2012 в 12:01
  • 5
    @ Когда вы говорите логику, и я говорю лингвистику. Человеческий мозг не может обработать негатив (прежде чем он обработает положительный результат, в какой момент он может его отрицать), поэтому в этом смысле между ними существует большая разница. Это не делает логику, которую вы предлагаете неправильно – Rune FS 27 January 2012 в 12:09

Оба будут иметь одинаковую производительность, потому что обе стоп-перечисления после результата могут быть определены - Any() по первому элементу, который переданный предикат оценивает true и All() в первом элементе, который предикат оценивает как false.

22
ответ дан BrokenGlass 19 August 2018 в 02:21
поделиться

All() определяет, удовлетворяют ли все элементы последовательности условию. Any() определяет, удовлетворяет ли любой элемент последовательности

var numbers = new[]{1,2,3};

numbers.All(n => n % 2 == 0); // returns false
numbers.Any(n => n % 2 == 0); // returns true
3
ответ дан Hayzum 19 August 2018 в 02:21
поделиться

Поскольку другие ответы хорошо освещены: речь идет не о производительности, а о ясности.

Широкая поддержка обеих ваших опций:

if (!acceptedValues.Any(v => v == someValue))
{
    // exception logic
}

if (acceptedValues.All(v => v != someValue))
{
    // exception logic
}

Но я думаю, что это может обеспечить более широкую поддержку :

var isValueAccepted = acceptedValues.Any(v => v == someValue);
if (!isValueAccepted)
{
    // exception logic
}

Просто вычисляя логическое (и именовав его), прежде чем отрицать что-либо, все это проясняет мне много.

4
ответ дан Michael Haren 19 August 2018 в 02:21
поделиться

Согласно этой ссылке

Any - проверяет хотя бы одно совпадение

All - проверяет, что все совпадают

< / BLOCKQUOTE>
3
ответ дан rcarvalhoxavier 19 August 2018 в 02:21
поделиться
  • 1
    вы правы, но они останавливаются в то же время для данной коллекции. Все прерывания, когда условие терпит неудачу, и Any Breaks, когда он соответствует вашему предикату. Так что технически ничем не отличается, кроме сценарно – WPFKK 14 August 2017 в 21:57

Если вы посмотрите на Enumerable source , вы увидите, что реализация Any и All довольно близка:

public static bool Any<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) {
    if (source == null) throw Error.ArgumentNull("source");
    if (predicate == null) throw Error.ArgumentNull("predicate");
    foreach (TSource element in source) {
        if (predicate(element)) return true;
    }
    return false;
}

public static bool All<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) {
    if (source == null) throw Error.ArgumentNull("source");
    if (predicate == null) throw Error.ArgumentNull("predicate");
    foreach (TSource element in source) {
        if (!predicate(element)) return false;
    }
    return true;
}

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

3
ответ дан Thomas Ayoub 19 August 2018 в 02:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: