|
To add to this, what universality (All) is really saying is that "nothing exists that violates this constraint", whereas existentiality (Any) is really saying "at least one thing exists that obeys this constraint."
With [].All(constraint), nothing exists to violate the constraint, so All() returns true.
With [].Any(constraint), nothing exists to obey the constraint, so Any() returns false.
|
|
|
|
|
I agree. I find the behavior of All() on an empty collection strange.
If I'm told "all the members of a list of integers are greater than zero" I would expect Any(p => p > 0) on that list to return true . But if the list is empty, Any(p => p > 0) returns false . That seems wrong.
/ravi
|
|
|
|
|
Good point. So, you're saying that if list.All(>0) then we should be able to assume that list.Any(>0) is also true? Makes sense.
However, it also makes sense that if list.All(>0) then list.Any(<=0) should be false, which it is, and we should be able to expect that if not list.Any(<=0) then list.All(>0) would be true, which it is (but wouldn't be if we changed it to work in your example).
The problem is that either way, when working with null sets, we end up with some relationship which isn't fully transitive.
For example, in SQL x = null and x <> null are both false (regardless of whether x is null or not, the only way to test for null is explicitly: x is null or x is not null ).
|
|
|
|
|
I feel what you feel but!
If you walk in a room and ask if anyone is there and there is no reply you have to note that down as false.
If you walk in a room and ask if all of them are aliens, but no one denies (cause nobody there) you note that down as true.
If there is no room you can walk into you can't ask questions in there, hence you trip and fall into the backrooms (nullException)
So MS is right, although it seems a bit off.
Rules for the FOSW ![ ^]
MessageBox.Show(!string.IsNullOrWhiteSpace(_signature)
? $"This is my signature:{Environment.NewLine}{_signature}": "404-Signature not found");
|
|
|
|
|
.NET's behavior is similar to the Principle of explosion
It is not a fallacy, it is a matter of "careful what you wish, you just might get it".
If you ask for multiple elements to satisfy a condition, you should be aware that you are, in fact, asking 2 questions:
1. I want at least 1 element
2. Each one of them satisfies the criterion.
Do not count on the tooth fairy to satisfy your hidden criterion #1, make it explicit instead.
|
|
|
|
|
I agree - code defensively. Check that the collection has something to interrogate, and if it has, proceed to do so. Otherwise define the behaviour you want if it is empty.
Don't be lazy!
|
|
|
|
|
Oh after this episode I no longer use All ; instead:
public static bool AnyAndAll<T>(this IEnumerable<T> source, Func<T, bool> predicate)
{
if (source == null)
return false;
bool any = false;
foreach (var item in source)
{
if (!predicate(item))
return false;
any = true;
}
return any;
}
|
|
|
|
|
Wikipedias page on Empty set[^] shows the properties of an empty set - which defined this behavior.
Personally I would have been very surprised if All() on an empty set would ever return false - as I one or another time managed to get "everything applies to all elements in the empty set" stuck in my head.
|
|
|
|
|
I figured I might be in the minority here, but suprised how overwhelmingly folks agree with Microsoft on [Empty].All() == true .
Mathematically I totally get it. None of the items is false. Fine.
But consider a real-world application and what I, as someone giving orders, would expect:
Darth Vader is commanding the Imperial fleet and approaching a suspected Rebel base but is uncharacteristically concerned about civilian casualties for once. "Are there any civilian inhabitants of this planet, commander?"
"No, Lord Vader," the commander replies.
"Good, so they're all rebels?"
"Yes, milord."
"Sterilize the planet," Vader commands.
The fleet spends the next four hours bombarding the planet, burning the entire surface and boiling the oceans, while Vader waits impatiently as he is eager to proceed to the next suspected target. Finally when the carnage is over, Vader asks, "Well done, Commander. How many Rebels did we kill?"
"Well, um, none, milord," the commander meekly replies.
"What do you mean?"
"The planet was uninhabited."
Vader initiates a force choke. "You said there were Rebels here!"
The commander struggles to spit out his last words.
"I said the inhabitants were all Rebels, not that there were any inhabitants."
|
|
|
|
|
This may be considered a "dumb" response, but why not check for null and if not null, get a count, on your collection before attempting an action that presumes items in the collection?
|
|
|
|
|
|
That was an interesting read, as was this:
Vacuous truth - Wikipedia
I don't pretend to be a mathematician, but if all conditions can be satisfied by all members of an empty set, then all members of the empty set would satisfy the condition that their parent set is non-empty.
If we took the other approach and said that no condition can be satisfied by all members of an empty set, then all members of the empty set would fail to satisfy the condition that their parent set is empty.
Both approaches lead to contradictions, which is why the answer seems like it should be undefined.
|
|
|
|
|
|
I know I may be alone on this but .. I just do not like Linq.
It biases for easy-to-write at the expense of easy-to-understand (to say nothing of perf implications of making non-inlineable callbacks for each item in the list).
Semantic details (like your example) matter, and I've spent way more hours debugging unexpected nuances like this, than I've saved by not writing a foreach loop in a little helper method.
|
|
|
|
|
ShawnVN wrote: I just do not like Linq.
Yep.
And even worse when it was forced down as a database layer. Now I have to do a database profile on every single usage just to make sure it actually does the expected SQL rather than deciding to do something non-sensical.
|
|
|
|
|
The All seems to work the same as any other language conjunctions. Search for "vacuous truth" to read about the underlying set theory origin of this definition in logic, which all (or at least all non-esoteric) programming languages define all. The same logic you can find at least in Python, JavaScript, C/C++, PHP, etc.
But on the other hand, if C# makes the method All does not return true without error on empty set, it will make C# special and unique language, so there might be benefits.
|
|
|
|
|
Have you ever heard of first-order logic - the logic which has been used formally for about 200 years (and informally much longer; on the order of 2000 years) for all sound reasoning in mathematics? Where it is obviously correct that "there is no x where P(x) is false" is equivalent with "for all x, P(x) holds" - because otherwise, that calculus would explode in your face ... Have you ever heard about vacuous truth?
If not, please take some time to learn about these things. That's neither a .Net nor a Microsoft thing - it's basic logic knowledge.
H.M.
|
|
|
|
|
One more for MS is right here (what??? how is that possible.)
Not really different from what others already wrote, but this is how I see it...
For me, Any(x) is the same as All(!x) so this must be true:
if list.Any(x) == false then list.All(!x) == true
which is true with the current implementation.
What you expect results in:
list.Any(x) == false and list.All(!x) == false.
... it's correct under your assumption, but to me it's illogic logic .
|
|
|
|
|
What was it like, being a WWII baby?
Freedom is the freedom to say that two plus two make four. If that is granted, all else follows.
-- 6079 Smith W.
|
|
|
|
|
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
The idea is that, being born on February 29th, you only have a birthday once every 4 years...and so you get older at a pace of 1/4th of everybody else.
Someone born on February 29th 1940 would only be "21" today...
Ok, I'm done mansplaining.
|
|
|
|
|
Thank you - I'd forgotten about the leap year "calculation"
|
|
|
|
|
OK Thanks for the explanation. Makes sense.
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
Actually you get older at the same rate as anyone else, but you only get 1/4 of the parties.
Alternatively your lifespan is only a quarter of those born in a "normal" year and you can expect to be an ex-you before you reach 22.
Either way, it seems a bum deal to me.
|
|
|
|
|
Realistically it's more about bragging rights than anything else.
Now imagine twins being born on a February 29th.
|
|
|
|