Почему делает IQueryable. Все () возвращают true на пустом наборе?

Таким образом, я столкнулся с ситуацией сегодня, где некоторый производственный код перестал работать точно потому что метод, выполненный точно, как зарегистрировано в MSDN. Позор мне для того, чтобы не прочитать документацию. Однако я все еще царапаю голову относительно того, почему она ведет себя этот путь, даже если бы "дизайном", так как это поведение точно противоположно, что я ожидал бы (и другой, знал бы поведения), и поэтому, кажется, нарушает принцип наименьшего количества удивления.

All() метод позволяет Вам предоставлять предикат (такой как лямбда-выражение) для тестирования IQueryable, возврат булева значения, которое указывает, соответствуют ли все участники набора тесту. Пока неплохо. Вот то, где это становится странным. All() также возвраты true если набор пуст. Это кажется полностью назад мне по следующим причинам:

  • Если набор пуст, тест как это, в лучшем случае не определен. Если моя подъездная дорога пуста, я не могу утверждать, что все автомобили, паркуемые там, являются красными. С этим поведением на пустой подъездной дороге все автомобили, паркуемые там, являются красными И синий И шахматная доска - все эти выражения возвратили бы true.
  • Для любого знакомого с понятием SQL тот ПУСТОЙ УКАЗАТЕЛЬ! = ПУСТОЙ УКАЗАТЕЛЬ, это - неожиданное поведение.
  • Any() метод ведет себя как ожидалось и (правильно) возвращает false, потому что он не имеет никаких участников, которые соответствуют предикату.

Таким образом, мой вопрос, почему делает All() вести себя этот путь? Какую проблему это решает? Это нарушает принцип наименьшего количества удивления?

Я отметил этот вопрос как.NET 3.5, хотя поведение также относится к.NET 4.0 также.

ОТРЕДАКТИРУЙТЕ хорошо, таким образом, я схватываю логический аспект к этому, как так превосходно размечено Jason и остальной частью Вас. По общему признанию пустой набор является чем-то вроде пограничного случая. Я предполагаю, что мой вопрос базирован в борьбе, которая, просто потому что что-то логично, не означает, что это обязательно имеет смысл, если Вы не находитесь в корректном настроении.

47
задан 3 revs, 2 users 100% 4 February 2010 в 00:19
поделиться

9 ответов

Если моя дорога пуста, я не могу утверждать, что все машины, припаркованные там, красные.

Рассмотрим следующие утверждения.

S1 : Моя подъездная дорожка пуста.

S2 : Все машины, припаркованные у меня на подъездной дорожке, красные.

Я утверждаю, что S1 влечет S2 . То есть утверждение S1 => S2 верно. Я сделаю это, показав, что его отрицание ложно. В этом случае отрицание S1 => S2 есть S1 ^ ~ S2 ; это потому, что S1 => S2 ложно только тогда, когда S1 истинно, а S2 ложно. Что является отрицанием S2 ? Это

~ S2 : На моей подъездной дорожке припаркована машина не красного цвета.

Каково истинное значение S1 ^ ~ S2 ? Давайте запишем это

S1 ^ ~ S2 : Моя подъездная дорожка пуста, а на моей подъездной дорожке припаркована машина не красного цвета.

Единственный способ, которым S1 ^ ~ S2 может быть истинным, - это если оба S1 и ~ S2 истинны. Но S1 говорит, что моя подъездная дорожка пуста, а S2 говорит, что на моей подъездной дорожке стоит машина. Моя подъездная дорожка не может быть одновременно пустой и содержать машину. Таким образом, невозможно, чтобы S1 и ~ S2 оба были истинными. Следовательно, S1 ^ ~ S2 ложно, поэтому его отрицание S1 => S2 истинно.

Следовательно, если ваша подъездная дорожка пуста, вы можете утверждать, что все припаркованные там машины красные.

Итак, теперь давайте рассмотрим IEnumerable elements и Predicate p . Предположим, что элементов пусто. Мы хотим узнать значение

bool b = elements.All(x => p(x));

. Давайте рассмотрим его отрицание

bool notb = elements.Any(x => !p(x));

Чтобы notb было истинным, должен быть хотя бы один x в элементах для которого верно ! p (x) . Но элементов пусто, поэтому невозможно найти x , для которого ! P (x) истинно. Следовательно, notb не может быть истинным, поэтому оно должно быть ложным. Поскольку notb ложно, его отрицание истинно. Следовательно, b истинно и элементов. Все (x => p (x)) должны быть истинными, если элементов пусто.

Вот еще один способ подумать об этом. Предикат p истинен, если для всех x в элементах вы не можете найти ни одного , для которого он ложен. Но если в элементах нет элементов, то невозможно найти любой , для которого он является ложным. Таким образом, для пустого набора элементов , p истинно для всех x в элементах

А что насчет элементы.Any (x => p (x)) , когда elements является пустым IEnumerable и p является Predicate как указано выше? Мы уже знаем, что результат будет ложным, потому что мы знаем, что его отрицание истинно, но давайте все равно рассмотрим его; интуиция ценна. Для элементов. Любой (x => p (x)) , чтобы быть истинным, должен быть хотя бы один x в элементах , для которого p ( x) верно. Но если нет каких-либо x в элементах , невозможно найти какие-либо x , для которых p (x) верно. Следовательно, elements.Any (x => p (x)) ложно, если elements пусто.

Наконец, вот связанное с объяснение того, почему s.StartsWith (String.Empty) истинно, когда s является ненулевым экземпляром ] строка :

43
ответ дан 26 November 2019 в 19:49
поделиться

"Если коллекция пуста, такой тест , в лучшем случае, не определен. Если моя подъездная дорога пусто, я не могу утверждать , что все припаркованные там машины красные »

Да, можно.

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

Для любого, кто знаком с понятием SQL, что NULL! = NULL, это неожиданное поведение.

Это причуда SQL (и не совсем верно: NULL = NULL и NULL <> NULL оба не определены, и ни один из них не соответствует ни одной строке.)

4
ответ дан 26 November 2019 в 19:49
поделиться

Думаю, это имеет смысл. В логике дополнения FOR ALL НЕТ (ТАКОЕ СУЩЕСТВУЕТ). FOR ALL похож на All () . THERE EXIST похож на Any () .

Итак, IQueryable.All () эквивалентен ! IQueryable.Any () . Если ваш IQueryable пуст, то оба возвращают истину на основе документа MSDN.

3
ответ дан 26 November 2019 в 19:49
поделиться

Это очень похоже на базовую концепцию числа ноль. Несмотря на то, что он представляет собой существование отсутствия, он все же обладает и представляет ценность. IQueryable.All () должен возвращать true, потому что он успешно вернет всех членов коллекции. Так получилось, что если коллекция пуста, функция не вернет никаких членов, но не потому, что функция не смогла вернуть какие-либо члены. Это произошло только потому, что не было членов, которые могли бы вернуться. При этом, почему IQueryable.All () должен терпеть неудачу из-за отсутствия поддержки со стороны коллекции? Он был готов, он мог ... он был способен. Для меня это звучит так, как будто коллекция не могла выполнить свою часть сделки ...

http://mathforum.org/dr.math/faq/faq.divideby0.html

0
ответ дан 26 November 2019 в 19:49
поделиться

Если количество возвращаемых элементов истина равно то же самое, что и количество всех элементов, затем вернуть true . Вот так просто:

Driveway.Cars(a => a.Red).Count() == Driveway.Cars.Count()

Связанное объяснение: Почему "abcd" .StartsWith ("") возвращает истину?

9
ответ дан 26 November 2019 в 19:49
поделиться

Any() и All() - это всего лишь реализации обычных математических операторов ∃ ("экзистенциальный кватификатор" или "существует") и ∀ ("универсальный кватификатор" или "для всех").

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

"Все" означает, что не существует никакого элемента, для которого предикат является ложным. Для пустой коллекции это всегда будет правдой.

3
ответ дан 26 November 2019 в 19:49
поделиться

Такое поведение довольно часто встречается в других областях математики или информатики.

Оператор SUM в математике возвращает 0 (нейтральный элемент +) в случаях, когда диапазоны недействительны (SUM от 0 до -1). Оператор MULTIPYL вернёт 1 (нейтральный элемент для умножения).

Теперь, если у вас есть булевы выражения, то это очень похоже: нейтральный элемент для ИЛИ равен false (a OR false = a), в то время как нейтральный элемент для И равен true.

Теперь на Linq'е ЛЮБОЙ и ВСЕ : Они похожи на это:

ANY = a OR b OR c OR d ...
ALL = a AND b AND c AND d ...

Так что такое поведение - это то, чего "вы бы ожидали", если у вас есть математический/школьный фон.

1
ответ дан 26 November 2019 в 19:49
поделиться

Возвращение истинного также логично. У вас есть два утверждения: "У вас есть машина?" и "Она красная?" Если первое утверждение является ложным , неважно, что такое второе утверждение, результат будет истинным по modus ponens .

1
ответ дан 26 November 2019 в 19:49
поделиться

Ложно означает, что запрос не вернул результатов даже без предиката. Это просто неполный способ указать, что Dested опубликовал, когда я печатал это.

0
ответ дан 26 November 2019 в 19:49
поделиться
Другие вопросы по тегам:

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