Page 50: Correction: Trapezoid link is on the wrong line
The area of a trapezoid code sample has the Wikipedia link on its own line, but that would make it not compile.
Ultimately, this was just a line that soft wrapped when it shouldn’t have.
It could be fixed by ensuring it stays on the line before it.
It could also be fixed by adding
// immediately before it, to make sure that the compiler doesn’t try to parse it.
Page 265: Correction: Swap method is wrong
The code for the
Swap method has the following:
int temporary = a; a = b; b = a;
That’s wrong. It should read:
int temporary = a; a = b; b = temporary;
Page 268: More Information: Extension methods can be applied to all types, not just those listed
The first sentence in the section called Extension Methods lists some types that extension methods can be applied to. It specifically calls out classes, structs, enumerations, and interfaces. It does not specifically call out records, but those work too.
Page 268: Minor Improvement: ToUpper and ToLower vs. lowercase and uppercase
This is a very minor thing, but it would be better to keep the ordering consistent. Instead of, “…the ToUpper and ToLower methods that produce lowercase and uppercase versions of the string,” it would be better to say “… the ToUpper and ToLower methods that produce uppercase and lowercase versions of the string.”
Page 273: Correction: Exception handler, not event handler
The book states “When looking for an event handler, the order matters.” But this should read, “When looking for an exception handler, the order matters.”
Event and exception handlers are both C# concepts, but in this level, it is exception handlers that matter.
Page 282: Consistency:
This isn’t technically wrong, but is not as consistent as it ought to be.
The Speedrun has an example with
NumberDelegate with two parameters, then assigns it a method named
AddOne, which would be more logical as a delegate with only one parameter.
On the line below that, it invokes it with two parameters. Then in the level, a single-parameter
NumberDelegate is used.
For consistency, it would be better to treat the
NumberDelegate defined in the Speedrun in the same way it is defined on page 283, with just a single parameter, and then invoke it on the fourth bullet point with a single parameter instead of two.
Delegates can use any number of parameters, so there is nothing technically wrong with what is stated here, it is just clearer with everything being single-parameter delegates in the Speedrun.
Page 282: Typo
“They may not seem like a big deal…” –> “That may not seem like a big deal…”
Pages 289 and 290: Minor Improvement: Health <= 0 instead of < 0
There are four places on these two pages where the book raises a
ShipExploded event when
Health < 0.
It’s not impossible that a game could treat “dead” as health under zero, but it’s not common.
All four of those places would be better if they checked if
Health <= 0.
Page 290: Correction: Code example doesn’t compile
The code sample on page 290 does not compile as the book is written.
PlaySound with a string and a float, but the method defined in that sample doesn’t have a
float volume parameter.
This could be fixed by calling it without the
CalculateVolume result or by changing the signature to allow the
I think the second one makes more sense, because otherwise, there’s not a lot of value in the event including the location as a parameter either, which was the point of the sample in the first place.
Page 292: More Information: Nuances of custom event accessors
The 3rd edition called out something that inadvertently got dropped in the 4th edition.
When you make custom event accessors, there is one thing you need to know about it:
You cannot invoke the event directly when you do custom event accessors (with the
Instead, you must invoke the delegate behind the event, if one exists.
(That last part is why you can’t invoke/raise the event directly.
The compiler does not know which delegate–or indeed, if there even is a delegate or perhaps even multiple delegates–underlies the event, so it puts that burden on the programmer.)
Page 301: Clarity:
WriteAllLines allows any string collection, not just
The book calls out that you use a
string instead of a single
string, and then in the code sample uses
List<string> instead of
There is an overload of
WriteAllLines that uses
string, but there is also one that is
IEnumerable<string>, so any collection type can be used, not just
Submit a Problem
If you think you may have found an error (large or small) in the C# Player’s Guide, please let me know about it so that I can get it fixed.
One great approach is to submit an issue or discussion on the book’s GitHub page.
Other ways to reach out are found on the contact page, and they will all get the job done as well.