It's dangerous to code alone! Take this.


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 ref-based 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: AddOne and NumberDelegate

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. It calls 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 float parameter. 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 add and remove accessors). 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 string[]

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 string[]. 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 string[].


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.