3 ms·
Change your recursive-descent parser so it pulls source tokens from a socket as opposed to RAM. All networking IO is expected to fail. You probably don’t want t
by Const-me 6y ago
Change your recursive-descent parser so it pulls source tokens from a socket as opposed to RAM. All networking IO is expected to fail. You probably don’t want to handle socket errors in the parser because there’s nothing you can do about them there. You want to handle them very far away, telling user you’re unable to parse stuff due to a network error.
Some libraries expose parallel APIs for these two cases. For example, hash maps from C# standard library exposes both operator[] which throws exceptions when trying to get a value that does not exist, and TryLookup which returns a boolean.
Overall, I think exceptions are solid in C#. There’s only one class of exceptions there, they can include lower-level ones, can aggregate multiple of them, for native interop they have 32-bit integer codes and runtime support to converting codes to/from exceptions, have runtime support to preserve contexts to re-throw later (e.g. on another thread). Uncaught exceptions become hard crashes.
- flowerlad 6y ago> Overall, I think exceptions are solid in C#. ... Uncaught exceptions become hard crashes. Do you see the problem, these two sentences are juxtaposed? When exceptions are not part of the contract you would have to read the source code of every method you call (and methods they call) to know what exceptions to catch. Even then, a method you call can be modified later to throw a new exception and your code will crash. The only solution is to use the root Exception class which everyone agrees is a bad idea.
- Const-me 6y ago> When exceptions are not part of the contract you would have to read the source code of every method you call (and methods they call) to know what exceptions to catch. Even that won’t help you to find that out when the API takes callbacks or interfaces. > is to use the root Exception class which everyone agrees is a bad idea It allows to use lambdas (called delegates but that’s technicalities) and interfaces in APIs. Unlike C++ which allows to throw anything (probably because the standard library with std::exception was too late to the party), in C# the language guarantees that will cover 100% of the exceptions. The idea is decades old and probably predates exceptions. For example, some pieces of Linux kernel APIs say in the documentation something like “return negative error code if failed”. What you see in almost 100% of use cases of error handling is if( result < 0 ) condition, not a switch-case testing for individual codes or their ranges. Catching individual exception types is usually a bad idea. Software is incredibly complicated these days; we use tons of APIs and libraries implemented by unrelated people from different continents. If the language doesn’t make them part of the verifiable contract, you’ll get runtime errors once the implementation changes and a new version starts throwing another exception type. If the language makes them part of the contract, you’ll be wasting a lot of time making your code compile again after a dependency is updated. This creates an incentive to never update them.
- Mawr 6y ago>Even then, a method you call can be modified later to throw a new exception and your code will crash. The only solution is to use the root Exception class which everyone agrees is a bad idea. This view was (is?) very widespread in the Python community, which led me astray as a beginner. Trying to find each individual exception that a function can throw when you really only care if it errored or not is a fool's errand. These days I just catch the base Exception, and only catch specific subclasses of it if there's an actual need to.