C# Brainteasers Unpuzzled
Back in November 2024 I announced that my book C# Brainteasers had been released in beta. In that blog I set a bit of a joke challenge to try to figure out what the puzzle titles meant.
One of the hallmarks of the Brainteasers Collection by the Pragmatic Bookshelf is the whimsical nature of the puzzle titles. It's fun to dream them up, and to try to "tease" the reader, but some folks have asked for a guide to what the book actually contains.
The tl;dr on the content is this: from loops and closures to user-defined conversions the puzzles take you on a journey via strings, enums, value semantics, record types, primary constructors, optional parameters, asynchronicity, LINQ, static members, the Dispose pattern, and exceptions. It's not possible to cover everything, but it covers quite a lot of ground.
The book was properly released in Spring 2025. I had a whole lot of fun writing it, and (despite thinking of myself as a C# veteran) learned a huge amount about the language.
So here it is: a guide to the cryptic titles.
1. All the Things
Lambda functions permit a terse yet easily-understood syntax for expressing complex behavior. Along with anonymous and local functions, lambdas can capture the variables declared in an outer scope. This puzzle looks behind the curtain to examine their inner workings.
2. Advance With Caution
There are elements of the humble for loop that are often under-appreciated; this puzzle re-visits closures to examine some of the ways a for loop differs from a foreach loop.
3. Nothing to See Here
Strings have always had sophisticated support in C#, but there are aspects of string handling that still cause confusion for programmers. In this puzzle we’ll examine why one feature of the string type can be particularly perplexing.
4. What was the Year?
The built-in types such as int and string, also known as intrinsic types, are general purpose building blocks, but an over-reliance on them can be a cause of confusion. This puzzle demonstrates how ambiguity can arise due to dependence on the most simple types in a program.
5. Unexpected Item in the Bagging Area
Enumeration types are a specialized form of value type that define a set of related constant values. However, enumerations also support a limited form of arithmetic, and this puzzle examines one case that’s the cause of subtle errors, and is easily missed if you’re not paying close attention.
6. Precision Instruments
Numerical calculations are such a common feature of computer programs it’s easy to forget that working with floating point values requires some extra care, as shown in this puzzle.
7. Inequality Among Equals
Writing code to correctly manage floating-point values is prone to several well-documented problems that are easily under-appreciated. This puzzle looks at one area where floating-point values have unconventional behavior.
8. Double Jeopardy
Managing floating point values in code suffers from quite a bit of bad press. This puzzle looks at one area where criticism of floating point values is unjustified under some conditions.
9. So, What’s Left?
Computers are—famously—very quick at doing arithmetic, but modular arithmetic has special properties. This puzzle tests your understanding of how C# handles the modulo (%) operator.
10. New Tricks
Writing robust code requires defensive coding practices, and avoiding the dreaded NullReferenceException caused by attempting to access an object via a null reference can require some thought. Reference type fields and properties are a major cause of NullReferenceExceptions because it’s easy to forget to properly initialize them with a "real" value. In this puzzle we explore some modern techniques that help prevent unnecessary null references from causing avoidable errors.
11. Property Development
The advice to always make value types immutable is common, but the reasons behind the advice are not always obvious. This puzzle demonstrates one problem that can occur if the advice is ignored.
12. Default Setting
Relatively new C# features such as records and record structs, property initializers (for value types), and primary constructors all offer convenient and concise techniques for reducing the amount of code you have to type in order to express complex ideas. This puzzle explores some of their limitations.
13. Chicken or Egg?
Static data is a convenient way to represent values that are common to all instances of a type. This puzzle tests how well you understand how static fields and properties get their values.
14. The Optional Default
Optional parameters offer a way for expressing default values for method parameters, including constructors as well as primary constructors. In this puzzle we’ll look at how mis-using optional parameters can cause confusion.
15. Deferred Judgement
LINQ is a central and long-standing feature of C# that makes dealing with sequences of objects intuitive and convenient. However, like any powerful technique, there are hidden complexities to LINQ as this puzzle explores.
16. A Promising Future
Writing and managing asynchronous code to keep a program responsive to the user benefits greatly from the async/await language feature first introduced in C# v5.0. This puzzle demonstrates that while async/await is usually intuitive and straightforward, there are nevertheless hazards that await (ahem) the unwary programmer.
17. Fire and Forget
The async/await feature of C# makes writing asynchronous code easy—perhaps too easy. This puzzle explores one specific problem that can cause serious problems for your applications and can be very difficult to spot.
18. Exceptional Circumstances
The Dispose pattern is an important feature of C# for managing object lifetimes. C# programs benefit from automatic memory management, but memory is only one kind of resource that requires management. This puzzle tests how well you understand the mechanics of the using statement.
19. Hanging Around
The use of exceptions to indicate errors in a program is common in many languages, and a long-standing feature of C# supported by the using statement. However, there remain aspects of the relationship between Dispose and exceptions that catch unwary programmers by surprise, as this puzzle demonstrates.
20. The Sentinel
There is much more to exception safety than catching exceptions. Safety here means that all resources—including but not limited to memory—are properly managed, even when exceptions occur. This puzzle demonstrates that achieving exception safety can be harder than it looks.
21. A Narrowing Experience
User-defined conversion operators permit arbitrary type conversions, but whether they are implicit or explicit, they need to be used with caution, as this puzzle demonstrates
Comments
Post a Comment