Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. The Lounge
  3. .NET's Sometimes Nonsensical Logic

.NET's Sometimes Nonsensical Logic

Scheduled Pinned Locked Moved The Lounge
csharpvisual-studioquestion
45 Posts 23 Posters 3 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P PIEBALDconsult

    I can see what you mean, but I can see the logic as well -- so I agree with MS on this. With Any, you begin by setting the result to false, then iterate the tests, if any of the tests is true, you return true -- so no tests yields false. With All, you begin by setting the result to true, then iterate the tests, if any of the tests is false, you return false -- so no tests yields true. Both have a short-circuit feature, which is a good thing. I definitely agree that MS needed to have a more cohesive development team who communicated and decided on things like this.

    H Offline
    H Offline
    haughtonomous
    wrote on last edited by
    #22

    The trouble is that you're explaining the logic of the implementation, whereas the question concerns the logic of the outcome. The outcomes of .Any() and .All() on empty collections are logically inconsistent. Logically the answer to whether anything in an empty collection or everything in the same collection meet some criterion is "No" in both cases. Similarly a null exception is absurd. My guess is that whoever coded and reviewed one of the two methods didn't first grasp the behaviour of the other. It happens a lot, in my experience.

    P 1 Reply Last reply
    0
    • Richard DeemingR Richard Deeming

      There are certainly some odd decisions in the .NET class libraries. But I don't agree with you on this one. From a purely logical perspective, checking whether all members of an empty set satisfy a particular condition should always return true - there are no members which don't satisfy the condition, so returning false would be senseless. If you want an example of a nonsensical decision, look no further than the System.Text.Json.JsonElement's TryGet... methods, which will throw an exception if the "JSON type" of the element is wrong. So TryGetInt64 will return true for { "id": 42 }; return false for { "id": 3.1415 }; and throw an exception for { "id": "42" }. :wtf: Given the usual TryParse pattern, you might expect these methods to return false for any invalid input. But that's not what they do. They return false for some kinds of invalid input, and throw an exception for other kinds of invalid input.


      "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

      H Offline
      H Offline
      haughtonomous
      wrote on last edited by
      #23

      So if you asked your sergeant if your platoon was all present and correct when in fact they'd all been blown to smithereens and the platoon was now devoid of soldiers, you would still expect the answer "Yes"?

      D 1 Reply Last reply
      0
      • M Martijn Smitshoek

        .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.

        H Offline
        H Offline
        haughtonomous
        wrote on last edited by
        #24

        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!

        P 1 Reply Last reply
        0
        • P Peter Moore Chicago

          Someone really should start a weekly blog of inane .NET logic when it comes to what it does or does not throw an exception for vs. just behaving according to some default arbitrary choice. Entry #1: On an empty collection, `.Any()`, with our without a condition, always returns `false`, as any sane person would expect. However, `.All(condition)`, on an empty collection, returns `true`. HUH? If I look at an empty room and ask "Are all the people in there aliens?" the answer I expect is apparently YES? If ever there were a situation where a method call is so nonsensical that there is no possible objectively right way to handle that which everyone would agree on (thus justifying an Exception), it's asking about `All` the items in an empty collection. It's tantamount to division by zero. And yet on a `null` collection, even though these are all extension methods and perfectly capable of treating `null` as empty, it throws .NET's all time favorite and #1 most useless exception, `NulLReferenceException`. Clearly the .NET developers' goal is to ruin as many of my days as possible.

          L Offline
          L Offline
          lmoelleb
          wrote on last edited by
          #25

          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. :D

          1 Reply Last reply
          0
          • Richard DeemingR Richard Deeming

            No. :) Maybe its a mathematical mindset. "Is this condition true for every member of this (empty) set?" has to return true, since there are no members of the set where the condition is not true. Similarly, "Is this condition true for any member of this (empty) set?" has to return false, since there are no members of the set where the condition is true.


            "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

            P Offline
            P Offline
            Peter Moore Chicago
            wrote on last edited by
            #26

            You're not wrong. But you're not right either. Maths vs. Words :-D

            Richard DeemingR 1 Reply Last reply
            0
            • H haughtonomous

              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!

              P Offline
              P Offline
              Peter Moore Chicago
              wrote on last edited by
              #27

              Oh after this episode I no longer use `All`; instead: public static bool AnyAndAll(this IEnumerable source, Func predicate) { if (source == null) return false; bool any = false; foreach (var item in source) { if (!predicate(item)) return false; any = true; } return any; }

              1 Reply Last reply
              0
              • P Peter Moore Chicago

                Someone really should start a weekly blog of inane .NET logic when it comes to what it does or does not throw an exception for vs. just behaving according to some default arbitrary choice. Entry #1: On an empty collection, `.Any()`, with our without a condition, always returns `false`, as any sane person would expect. However, `.All(condition)`, on an empty collection, returns `true`. HUH? If I look at an empty room and ask "Are all the people in there aliens?" the answer I expect is apparently YES? If ever there were a situation where a method call is so nonsensical that there is no possible objectively right way to handle that which everyone would agree on (thus justifying an Exception), it's asking about `All` the items in an empty collection. It's tantamount to division by zero. And yet on a `null` collection, even though these are all extension methods and perfectly capable of treating `null` as empty, it throws .NET's all time favorite and #1 most useless exception, `NulLReferenceException`. Clearly the .NET developers' goal is to ruin as many of my days as possible.

                M Offline
                M Offline
                MSBassSinger
                wrote on last edited by
                #28

                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?

                1 Reply Last reply
                0
                • P Peter Moore Chicago

                  Someone really should start a weekly blog of inane .NET logic when it comes to what it does or does not throw an exception for vs. just behaving according to some default arbitrary choice. Entry #1: On an empty collection, `.Any()`, with our without a condition, always returns `false`, as any sane person would expect. However, `.All(condition)`, on an empty collection, returns `true`. HUH? If I look at an empty room and ask "Are all the people in there aliens?" the answer I expect is apparently YES? If ever there were a situation where a method call is so nonsensical that there is no possible objectively right way to handle that which everyone would agree on (thus justifying an Exception), it's asking about `All` the items in an empty collection. It's tantamount to division by zero. And yet on a `null` collection, even though these are all extension methods and perfectly capable of treating `null` as empty, it throws .NET's all time favorite and #1 most useless exception, `NulLReferenceException`. Clearly the .NET developers' goal is to ruin as many of my days as possible.

                  P Offline
                  P Offline
                  Peter Moore Chicago
                  wrote on last edited by
                  #29

                  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."

                  1 Reply Last reply
                  0
                  • P Peter Moore Chicago

                    Someone really should start a weekly blog of inane .NET logic when it comes to what it does or does not throw an exception for vs. just behaving according to some default arbitrary choice. Entry #1: On an empty collection, `.Any()`, with our without a condition, always returns `false`, as any sane person would expect. However, `.All(condition)`, on an empty collection, returns `true`. HUH? If I look at an empty room and ask "Are all the people in there aliens?" the answer I expect is apparently YES? If ever there were a situation where a method call is so nonsensical that there is no possible objectively right way to handle that which everyone would agree on (thus justifying an Exception), it's asking about `All` the items in an empty collection. It's tantamount to division by zero. And yet on a `null` collection, even though these are all extension methods and perfectly capable of treating `null` as empty, it throws .NET's all time favorite and #1 most useless exception, `NulLReferenceException`. Clearly the .NET developers' goal is to ruin as many of my days as possible.

                    R Offline
                    R Offline
                    R Kramer
                    wrote on last edited by
                    #30

                    Microsoft is following the definition of Universal Quantification as applied to the empty set. See Universal quantification - Wikipedia[^]

                    P 1 Reply Last reply
                    0
                    • H haughtonomous

                      The trouble is that you're explaining the logic of the implementation, whereas the question concerns the logic of the outcome. The outcomes of .Any() and .All() on empty collections are logically inconsistent. Logically the answer to whether anything in an empty collection or everything in the same collection meet some criterion is "No" in both cases. Similarly a null exception is absurd. My guess is that whoever coded and reviewed one of the two methods didn't first grasp the behaviour of the other. It happens a lot, in my experience.

                      P Offline
                      P Offline
                      PIEBALDconsult
                      wrote on last edited by
                      #31

                      Exactly. A lack of communication. The specs for the methods should have specified what the result should be for an empty set -- probably false.

                      1 Reply Last reply
                      0
                      • R R Kramer

                        Microsoft is following the definition of Universal Quantification as applied to the empty set. See Universal quantification - Wikipedia[^]

                        P Offline
                        P Offline
                        Peter Moore Chicago
                        wrote on last edited by
                        #32

                        That was an interesting read, as was this: [Vacuous truth - Wikipedia](https://en.wikipedia.org/wiki/Vacuous\_truth#:~:text=In mathematics and logic%2C a,does not really say anything.) 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.

                        1 Reply Last reply
                        0
                        • P Peter Moore Chicago

                          Someone really should start a weekly blog of inane .NET logic when it comes to what it does or does not throw an exception for vs. just behaving according to some default arbitrary choice. Entry #1: On an empty collection, `.Any()`, with our without a condition, always returns `false`, as any sane person would expect. However, `.All(condition)`, on an empty collection, returns `true`. HUH? If I look at an empty room and ask "Are all the people in there aliens?" the answer I expect is apparently YES? If ever there were a situation where a method call is so nonsensical that there is no possible objectively right way to handle that which everyone would agree on (thus justifying an Exception), it's asking about `All` the items in an empty collection. It's tantamount to division by zero. And yet on a `null` collection, even though these are all extension methods and perfectly capable of treating `null` as empty, it throws .NET's all time favorite and #1 most useless exception, `NulLReferenceException`. Clearly the .NET developers' goal is to ruin as many of my days as possible.

                          M Offline
                          M Offline
                          Member 10159088
                          wrote on last edited by
                          #33

                          This actually makes perfect sense if you know set theory. It’s called vacuous truth Vacuous truth - Wikipedia[^]

                          1 Reply Last reply
                          0
                          • P Peter Moore Chicago

                            Someone really should start a weekly blog of inane .NET logic when it comes to what it does or does not throw an exception for vs. just behaving according to some default arbitrary choice. Entry #1: On an empty collection, `.Any()`, with our without a condition, always returns `false`, as any sane person would expect. However, `.All(condition)`, on an empty collection, returns `true`. HUH? If I look at an empty room and ask "Are all the people in there aliens?" the answer I expect is apparently YES? If ever there were a situation where a method call is so nonsensical that there is no possible objectively right way to handle that which everyone would agree on (thus justifying an Exception), it's asking about `All` the items in an empty collection. It's tantamount to division by zero. And yet on a `null` collection, even though these are all extension methods and perfectly capable of treating `null` as empty, it throws .NET's all time favorite and #1 most useless exception, `NulLReferenceException`. Clearly the .NET developers' goal is to ruin as many of my days as possible.

                            S Offline
                            S Offline
                            ShawnVN
                            wrote on last edited by
                            #34

                            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.

                            J 1 Reply Last reply
                            0
                            • H haughtonomous

                              So if you asked your sergeant if your platoon was all present and correct when in fact they'd all been blown to smithereens and the platoon was now devoid of soldiers, you would still expect the answer "Yes"?

                              D Offline
                              D Offline
                              David On Life
                              wrote on last edited by
                              #35

                              In your example, the sergeant is probably asking about the set of soldiers assigned to the platoon (regardless of status). In which case, the set isn't empty, and the answer is "no". However, if the sergeant was asking if all soldiers in your platoon who were capable of showing up were there, then the answer is "yes". Note: technically, the set still isn't empty, as you are presumably in your own platoon. However, the logic would still apply if the question was asked about another platoon where no one was left alive - everyone who was capable of showing up would be there...

                              H 1 Reply Last reply
                              0
                              • R Ravi Bhavnani

                                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

                                My new year resolution: 2048 x 1536 Home | Articles | My .NET bits | Freeware ravib(at)ravib(dot)com

                                D Offline
                                D Offline
                                David On Life
                                wrote on last edited by
                                #36

                                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` ).

                                1 Reply Last reply
                                0
                                • J jmaida

                                  I brought it up a while back and there was some back and forth on it. Apparently, malloc( 0 ) not returning NULL is deliberate. Here is what GCC does with some short bit of code printf("Hello world!\n"); printf( "call malloc(0)\n" ); sz = (char*)malloc(ZERO); printf( "Errno %d\n", errno ); if( sz == NULL ) printf( "returned NULL allocated zero bytes\n"); else printf( "NULL not returned from malloc, allocated 8 bytes\n" ); Hello world! call malloc(0) Errno 0 NULL not returned from malloc, allocated 8 bytes Apparently this is allowed by GCC. The argument is that it was successful Haven't tried it in VS.

                                  "A little time, a little trouble, your better day" Badfinger

                                  J Offline
                                  J Offline
                                  jschell
                                  wrote on last edited by
                                  #37

                                  jmaida wrote:

                                  Apparently, malloc( 0 ) not returning NULL is deliberate.

                                  Standard says either is allowed.

                                  jmaida wrote:

                                  allocated 8 bytes

                                  Without the actual standard, which costs money, I suspect the following is authoratative enough. MEM04-C. Beware of zero-length allocations - SEI CERT C Coding Standard - Confluence[^] Keep in mind that without that reference I thought it might have been undefined. Which means it could throw a system exception too. So probably better the way it is.

                                  J 1 Reply Last reply
                                  0
                                  • S ShawnVN

                                    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.

                                    J Offline
                                    J Offline
                                    jschell
                                    wrote on last edited by
                                    #38

                                    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.

                                    1 Reply Last reply
                                    0
                                    • J jschell

                                      jmaida wrote:

                                      Apparently, malloc( 0 ) not returning NULL is deliberate.

                                      Standard says either is allowed.

                                      jmaida wrote:

                                      allocated 8 bytes

                                      Without the actual standard, which costs money, I suspect the following is authoratative enough. MEM04-C. Beware of zero-length allocations - SEI CERT C Coding Standard - Confluence[^] Keep in mind that without that reference I thought it might have been undefined. Which means it could throw a system exception too. So probably better the way it is.

                                      J Offline
                                      J Offline
                                      jmaida
                                      wrote on last edited by
                                      #39

                                      I agree. I have seen this cert referenced before. I wrap malloc with a check for <1 memory request argument and return NULL and an error message.

                                      "A little time, a little trouble, your better day" Badfinger

                                      1 Reply Last reply
                                      0
                                      • P Peter Moore Chicago

                                        Someone really should start a weekly blog of inane .NET logic when it comes to what it does or does not throw an exception for vs. just behaving according to some default arbitrary choice. Entry #1: On an empty collection, `.Any()`, with our without a condition, always returns `false`, as any sane person would expect. However, `.All(condition)`, on an empty collection, returns `true`. HUH? If I look at an empty room and ask "Are all the people in there aliens?" the answer I expect is apparently YES? If ever there were a situation where a method call is so nonsensical that there is no possible objectively right way to handle that which everyone would agree on (thus justifying an Exception), it's asking about `All` the items in an empty collection. It's tantamount to division by zero. And yet on a `null` collection, even though these are all extension methods and perfectly capable of treating `null` as empty, it throws .NET's all time favorite and #1 most useless exception, `NulLReferenceException`. Clearly the .NET developers' goal is to ruin as many of my days as possible.

                                        P Offline
                                        P Offline
                                        Plamen Dragiyski
                                        wrote on last edited by
                                        #40

                                        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.

                                        1 Reply Last reply
                                        0
                                        • P Peter Moore Chicago

                                          You're not wrong. But you're not right either. Maths vs. Words :-D

                                          Richard DeemingR Offline
                                          Richard DeemingR Offline
                                          Richard Deeming
                                          wrote on last edited by
                                          #41

                                          Perhaps you should be programming in Q#[^]? :laugh:


                                          "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

                                          "These people looked deep within my soul and assigned me a number based on the order in which I joined" - Homer

                                          1 Reply Last reply
                                          0
                                          Reply
                                          • Reply as topic
                                          Log in to reply
                                          • Oldest to Newest
                                          • Newest to Oldest
                                          • Most Votes


                                          • Login

                                          • Don't have an account? Register

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • World
                                          • Users
                                          • Groups