C#13Expansion
C#13Expansion
[email protected]
THE C# PLAYER’S GUIDE
C# 13 EXPANSION
.NET 9 PROJECTS
Read after Level 2: Getting an IDE.
To use the features in this expansion, you must have .NET 9 installed.
For Visual Studio, if you already have the correct workflow installed (described in the book), you will need to
update Visual Studio to 17.12 (or newer). If you have an older version, rerun the Visual Studio Installer and
update it.
You will know that you have the correct version if you see .NET 9 (or newer) as an option when making a new
project:
Sold to
[email protected]
You can also upgrade an existing project to .NET 9 by right-clicking on the project in the Solution Explorer,
choosing Properties, and then changing the Target framework setting:
This command starts with \e, which indicates that what follows isn’t text to display, but a command to the
console window itself. These commands all start with [ and end with m, with metadata between those two
markers. The 38 indicates that we want to change the foreground color. The 2 indicates that the color data is
in a full color scheme. The 255, 127, and 0 are the red, green, and blue channel values for the color we want
to use. A value of 0 means that color channel is off, a value of 255 is fully on, with a continuum between. You
can find the RGB values for any color you want online, but (255, 127, 0) is a vibrant orange color.
To use this command, embed it in a string that you send to the console window. For example:
Console.WriteLine("The following will be \e[38;2;255;127;0morange.");
I often separate the specific commands I’m using into their own variable to improve the readability of the
code:
string foregroundOrange = "\e[38;2;255;127;0m";
You can reset the foreground color to its defaults with the command code \e[39m, so to get just the text
orange to be orange, we can do this:
string foregroundOrange = "\e[38;2;255;127;0m";
string foregroundReset = "\e[39m";
The background color can also be set using 48 and reset with 49.
You can do much more with these standardized command codes, including things like underlining, italics,
strikethrough, etc. I won’t get into too many details here, but if you want to explore it further, you can read
more here: https://en.wikipedia.org/wiki/ANSI_escape_code.
It’s also worth a brief discussion on escape sequences vs. the escape character. The two are similar
Soldconcepts
to
that begins with a \ and indicates
that operate at different levels. An escape sequence is a C# string [email protected]
that the character that follows is not a plain character but a shortcut for something else. The escape sequences
\n (new line) and \t (tab) are good examples. The escape character is a specific char value (\u001b or
0x1b) that most console windows will recognize as the beginning of a command to change properties of the
window itself, like color and cursor location, rather than as raw data to display. We’ve always been able to
use the escape character in C#, but \e is a new C# 13 escape sequence for the escape character that makes it
easier to do (and that mirrors what a number of other languages can do).
Purpose: Try out the escape character and use more than the sixteen colors defined in ConsoleColor.
Objectives:
• Write code to display the six staffs (no color needed yet), as shown below.
---*
---*
---*
---*
---*
---*
• Modify the text to display each line in the henge’s color, as shown in the table above, by using the foreground color
escape sequence described in this expansion.
• Hint: You may find your code more readable if you define strings for each of the six colors, as shown in this expansion,
and then use string interpolation with $ and {...} to embed those color-based escape sequences into your string.
• Note: Most console windows support these escape sequences, but if yours does not, that’s fine. The sixteen color
options in ConsoleColor give you enough variation for most console projects. It’s not worth a lot of trouble trying
to run your program in a different console window. Feel free to simplify or adapt any color aspects of the other
challenges in this expansion. Sold to
[email protected]
After the Challenge: The staffs glow with soft, colored light; they are working again! If only you knew where to find the
henges they control. Those could make a difference against the Uncoded One’s forces. Ada believes she can find some
scrolls at the remnants of the guild hall in Consolas that might have information on their resting places. She promises to
search and send word by rider.
• Hint: When you’ve displayed all six henges, they should form a triangular shape.
After the Challenge: You’ve decoded the binary locations of the henges! Ada thinks that if you repair them, they’d make
a big difference in your fight against the Uncoded One. You’ll need to go out of your way to find these henges—and who
knows how long they’ll take to repair—but you can use all the help you can get.
Objectives:
• Repair the Location class by giving it X and Y properties. These should be settable, because the location may change
over time. (Include a constructor if you’d like, but it isn’t required.)
• Repair the Color class by (1) giving it get-only properties for R, G, and B, then (2) add a constructor to Color so that
you can make a new color with specific values for the red, green, and blue channels.
• Repair the Henge class. This is the trickiest of the three. (1) Add properties for the henge’s location, color, and
representation, which should use the types Location, Color, and char, respectively. (Note: This is the first time
we’ve used a class of our own making used as a field’s type, but this is very common.) (2) Fix the constructor so that
the parameters passed in are assigned to the fields for later use. (3) Fix the Display method. We saw code that does
this in the previous challenge, using Console’s SetCursorPosition and Write methods.
• Create a main method that creates two instances of the Henge class and displays them. This may be your first time
making multiple instances of a class in a single program. This ultimately means making two Location and two Color
instances (as well as two char values), and handing all of that off to the constructor for two Henge instances. You can
make variables for each of those if you want, to break it into smaller steps, or create them all inline. That means you’ll
see the new keyword in there six times, as you create all these objects. The table below shows the data needed for
the two henges you have recovered so far:
Sold to
[email protected]
Henge Location Representation Color
Amaranth (3, 2) A (240, 24, 79)
Jasmine (1, 5) J (246, 215, 141)
• Note: Keep this code for the next challenge. It will build upon this one.
After the Challenge: The two henges tower in front of you, bull-like in form, with glowing vine-like tendrils running
across the surface of their massive stone forms—Amaranth a deep red and jasmine a golden yellow. They’re alive. You’ve
done it. They don’t seem intelligent, but they are decidedly powerful. You’ll use them to gather the last four henges, and
then see if you can do anything to make them smarter.
while (true)
{
Console.Clear();
foreach (Crate target in crates)
target.Display();
foreach (Henge henge in henges)
henge.Display();
• Patch up the missing pieces. (1) Create an array of Henge instances containing the six henges from the data in the
henge table below. (2) Create an array of crates from the data in the crate table below. (3) Using the y-axis movement
as a template, insert code to account for movement along the x-axis, if the pressed key is LeftArrow and
RightArrow. (4) Using the D1 and D2 code as a template, change current to the other four henges if the D3, D4, D5,
or D6 keys are pressed. (The D1 through D9 and D0 values represent the number keys above the letters on the
keyboard, in contrast to the number pad (which are NumPad1, etc.).)
Henge Start Location Representation Color
Tekhelet (0, 0) T (89, 12, 131)
Mauveine (1, 0) M (143, 48, 161)
Amaranth (2, 0) A (240, 24, 79)
Jasmine (3, 0) J (246, 215, 141)
Keppel (4, 0) K (70, 179, 165)
Bice (5, 0) B (46, 109, 146)
Crate Location
1 (5, 4)
2 (0, 7)
3 (2, 8)
4 (4, 2)
• Run your program and verify its correctness. You should be able to use the arrow keys to move the active henge
around, the number keys 1 through 6 to pick a specific henge to move, and spacebar to destroy a crate in the henge’s
current location.
After the Challenge: The henges make quick work of the target crates. The henges are working! There’s a problem:
controlling them is complicated, and takes a bit of finesse that will only come from practice. You know you don’t have
time to practice with the henges. You need to get on with your journey toward the Catacombs of the Class. Shel has
volunteered to take care of the henges and to begin experimenting and training with them, and will send for the people
in Ada’s conclave to join him. When the Final Battle arrives, you have hope that this group will be able to use the henges
to make a difference.
The compiler reworks these calls into a new array full of the specified values.
Before C# 13, params only worked with arrays. That constraint has now been lifted, and it works with
basically any collection type, including IEnumerable<T> and List<T>.
Sold to
[email protected]
THE LOCK TYPE
Read after Level 43: Threads.
There are a lot of synchronization tools in C#, but the one we focus on in the main book is the lock statement,
which uses a class called Monitor behind the scenes. The approach used by Monitor is that you “enter” a
lock on an object—it can be any object at all—and while a thread has acquired a lock on that object, other
threads that attempt to enter the lock are stopped until the first thread exits the lock.
This approach has served C# well for nearly a quarter of a century, but it isn’t as efficient as it could be. In C#
13, a new type was added that is more efficient: System.Threading.Lock. While you can use the methods
that Monitor or Lock provide directly, the C# compiler understands the Lock class and will use its more
efficient version when you use a Lock-typed object in a lock statement.
The bottom line is this. In earlier versions of C#, the guidance was to make a new plain object instance and
use that for your locks. Now, for better performance, use the Lock type instead:
class SharedData
{
private readonly Lock _numberLock = new Lock();
Note that this is about the compile-time type, because the compiler is the one making the decision. Consider
what happens if you make the field’s type object while still making a new Lock object:
private readonly object _numberLock = new Lock(); // WARNING!
In this case, for the lock statements, the compiler isn’t sure that _numberLock will be of type Lock since
its declared type is object. So this falls back to the old style instead, which compiles, but misses out on the
performance benefits.
Sold to
[email protected]