0% found this document useful (0 votes)
26 views

C#13Expansion

The C# 13 Expansion is designed for users of The C# Player’s Guide, covering new features and providing additional challenges for hands-on experience. It introduces the escape character represented by , allowing for enhanced console window commands, such as changing text colors beyond the standard ConsoleColor options. The document includes several programming challenges related to C# 13 features, including tasks involving enumerations, tuples, and color manipulation in console applications.

Uploaded by

Joe Waters
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
26 views

C#13Expansion

The C# 13 Expansion is designed for users of The C# Player’s Guide, covering new features and providing additional challenges for hands-on experience. It introduces the escape character represented by , allowing for enhanced console window commands, such as changing text colors beyond the standard ConsoleColor options. The document includes several programming challenges related to C# 13 features, including tasks involving enumerations, tuples, and color manipulation in console applications.

Uploaded by

Joe Waters
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 10

Sold to

[email protected]
THE C# PLAYER’S GUIDE
C# 13 EXPANSION

ABOUT THIS EXPANSION


This C# 13 Expansion is for people with the 5th Edition of The C# Player’s Guide. However, it should also work
well for anybody with the 4th Edition or earlier.
This expansion covers C# 13 features, though this update is a small one.
I’m also including a series of additional interconnected challenges that aren’t directly related to C# 13. These
challenges will give readers more hands-on experience with some of the areas that I’ve seen readers struggle
with, and where I think a few more challenges will help. This expansion contains four more challenges worht
a total of 650 XP.
While I think you’ll get the most from this expansion by going through it in parallel with the main book, you
can also go through it after completing the main book.

.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:

THE ESCAPE CHARACTER


Read after Level 8: Console 2.0.
C# 13 added yet another escape sequence, and I could take the easy route and just say that \e is a shorthand
way to write \u001b or \x1b, like how \n is a way to write a newline character. The \e escape sequence is
for the escape character (which is confusing, I know, but we’ll address that soon). Most C# programmers won’t
use the escape character much, so I could arguably skip this. Except… the escape character has some
interesting uses in console windows, which happens to be our focus, meaning \e might actually be useful to
us. So let’s explore what the escape character does. Sold to
[email protected]
First, some history. A lot of old devices, such as terminals (like console windows) and printers, worked by
sending them a sequence of characters to display. But these devices could do more than just display
characters, such as ringing a bell, change colors, move the cursor around, etc. These devices didn’t have a
separate way to control these extra features. Instead, commands to control them were embedded directly in
the data. To indicate that upcoming data was to be interpreted as a command instead of data, you’d insert a
specific character—the escape character—to tell the device to treat it differently. The specific escape
character, as well as the supported commands, different from device to device.
While most modern devices don’t intermix data and commands in this same way, a lot of console windows
do. Conveniently, they’ve also standardized on what escape character to use as well as what the various
commands look like. That is, we’ll be able to embed a command to do something like change to an orange
forground color and most console windows will correctly change to orange.
With that said, if a console window does not support one of the standardized commands, most typically know
enough to ignore it, rather than crashing or rendering the command as plain text. For example, if a console
window doesn’t support orange text, it may stick to black and white, but it won’t blow up in our faces.
By tapping into these commands through the escape character, we can get our console window to do a lot
more than we can through the Console class. The Console class is limited to a set of capabilities that nearly
every console window should be capable of supporting. But by using the escape character, you can get the
vast majority of console windows to do much more. For example, we can change the foreground color of the
console window by setting Console.ForegroundColor to one of the sixteen ConsoleColor values. But
none of those are orange. With an escape character and the right command, we can work outside of this
system and make our text orange (in most console windows).
Starting in C# 13, the escape character is now represented with \e—similar to how \n is a newline and \t
is a tab. The line below is the full command to tell the console window to use a foreground color of orange:
\e[38;2;255;127;0m

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";

Console.WriteLine($"The following will be {foregroundOrange}orange.");

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";

Console.WriteLine($"The following will be {foregroundOrange}orange{foregroundReset}.");

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).

Challenge The Six Staffs of Elegedd 100 XP


Complete after Level 8: Console 2.0.
Description: After hearing rumors that an enclave of former programmers are living in a slot canyon near the city of
Consolas, you seek them out. Upon finding them, you discover that they are not programmers, but may still have some
secrets to share. They are led by an old woman, Ada, who worked as a porter at a programming guild hall in Consolas when
she was young, just before the Uncoded One arrived.
Ada worked under a renowned programmer, Elegedd, who was adept at a style of programming magic that involved
infusing programming power into physical objects—object-oriented programming magic. Elegedd’s life work was building
six henges—towering bull-like creatures made of rock, held together with rope and vines, and infused with programming
power to animate them. These henges were designed for moving and crushing large, heavy objects to clear land and make
mountain roads. Each henge was controlled by a staff that shined a light of a specific color on the henge’s target, shown
in the table below:

Henge Name Color (RGB)


Tekhelet 89, 12, 131
Mauveine 143, 48, 161
Amaranth 240, 24, 79
Jasmine 246, 215, 141
Keppel 70, 179, 165
Bice 46, 109, 146
The henges move to and then pick up any object colored with its specific color.
When the Uncoded One arrived and Algol summoned all programmers for a final defense, Elegedd and his guild reworked
the henges for war instead of construction. But the Uncoded One won, Elegedd was killed in battle, the henges were
destroyed, and Ada barely escaped with the staffs, which then fell into disrepair, locked away in a chest and buried to keep
them secret.
Ada is over-protective of the staffs—she’s guarded them for a lifetime—but you’re the first she’s encountered that has
any chance of repairing them. She hesitantly retrieves them and hands them to you for repair.

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.

Challenge Finding the Henges 150 XP


Complete after Level 17: Tuples.
Purpose: Get more experience with tuples and enumerations. Coincidentally, you’ll also get some hands-on experience
with binary number literals, though that is for storytelling reasons instead of practical ones.
Description: As you sit in the tavern of the Three Coppers Inn (which you note costs far more than that for a night’s stay),
a mud-caked, young man comes through the door, briefly letting the blustery, wet weather in with him. He calls your name,
and you wave him over to your table near the hearth. His name is Shel, and he’s the rider Ada promised to send after
looking for information about the locations of the destroyed henges. Shel says they found coordinates for all six henges,
but that they were written in some form of binary, and none of them could decipher it. Ada hoped you could figure it out.

Henge X Y Symbol Color


Tekhelet 0b1000 0b0000 T 89, 12, 131
Mauveine 0b1011 0b0011 M 143, 48, 161
Amaranth 0b0000 0b0111 A 240, 24, 79
Jasmine 0b0011 0b0011 J 246, 215, 141
Keppel 0b0111 0b0111 K 70, 179, 165
Bice 0b1110 0b0111 B 46, 109, 146
Fortunately, you’ve got some ideas. Your programmer magic may be able to turn those binary coordinates into a map.
Objectives:
• Create a Henge enumeration that lists the six henges by name.
• Create a method with the signature (int, int, string) GetInformation(Henge henge)—that is a method
with an enumeration parameter and a tuple return type. This method should return a tuple containing the X- and Y-
coordinates and text to display for a given henge. For example, for the Henge value of Henge.Keppel, you would
return the tuple (0b0111, 0b0111, "\e[38;2;70;179;165mK") Note that C# understands these binary literals
that start with 0b. You don’t need to convert them yourself.
• Hint: The entire body of this GetInformation method could be a single switch expression.
• In your main method, create a Henge[] array containing the six enumeration values. Then loop through the array,
call GetInformation to gather the information about that henge, and display the henge in its correct color at its
correct location, using the code below as a starting point:
int x = 3;
int y = 5;
Console.SetCursorPosition(x, y);
Console.Write("T");

• 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.

Challenge Amaranth and Jasmine 200 XP


Complete after Level 23: Object-Oriented Design.
Purpose: Get experience making multiple data-centric classes that work together, instead of just a single class and
instance.
Sold to
[email protected]
Description: You’ve recovered two of the henges—the ones named Amaranth and Jasmine. As Ada said, they’re in terrible
condition. But Elegedd knew what he was doing. These are master crafts, and Elegedd must have spent years on these.
You convinced a nearby ranchhand to assist you with a team of oxen, which you used to drag the henges to a wooded
thicket near Vin Fletcher’s shop. The henges were large and heavy enough to scrape the road flat for the miles you moved
them. You’re sure people will be confused about the scrapes and come looking for the cause. If you want to keep the
henges secret—and who knows what eyes and ears the Uncoded One has out here—you’d better move quickly to get
these two running again.
Within the crushed programmed components of the henges, you find a chunk of code that looks like the key parts you
need to repair to get Amaranth and Jasmine operational again. You begin by commenting out the parts that look broken
beyond repair, leaving you with this code as your starting point:
// Main method here...
/* rEOX8zHCLFsoZ)f-"&sl#IH8Z#e?=4#? */

public class Location


{
/* u~:rv@Pmi{~4,%o9k[U+z89=ka.87+ST */
}

public class Color


{
/* Q)%GKes0O-BE(y<[<XSVBR8LF\0@%8L5 */

public string GetColorText() => $"\e[38;2;{R};{G};{B}m";


}

public class Henge


{
/* FX$/#/7yEzTnXRvSn`7.=4>qnPph|v&j */

public Henge(Location location, Color color, char representation)


{
/* >NkwNu)M1AU[:oE0L:r];1gyoFdE%N+y */
}

public void Display()


{
/* L&iIkUU=M+F%hk;O,+xm@2:jZxF ?~}\ */
}
}

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.

Challenge The Henges of Elegedd 200 XP


Complete after Level 23: Object-Oriented Design and after the Amaranth and Jasmine challenge above.
Purpose: We’ll continue to get experience working with multiple objects and also spend time working on previously
written code—both your own from the previous challenge and partial code supplied in this challenge. Reworking existing
code is an important skill when building larger programs.
Description: You use Amaranth and Jasmine to collect the last four henges, which are all now working at a basic level.
But they are not in fighting shape yet. Vin Fletcher has a number of wooden crates available that will serve as targets to
send the henges after. But creating a training area for the henges is the easy part.
The hard part is going to be reactivating the henges’ fighting code. After carefully studying the inner workings of the
henges, you find the program Elegedd wrote to turn the henges into combatants. But as you try to reconnect it, the parts
crumble to blue dust in your fingers. It’s not your fault; you’re lucky there is anything left at all. But you’ve got your work
cut out for you.
Objectives:
• Note: Elegedd isn’t here anymore. This code is completely yours. Make any changes you want or need to match your
goals and vision of the code. The provided sample code is meant to give you a framework and hints, not dictate a
specific way to complete the challenge.
• Start by adding a Crate class. Our program needs to represent a crate, including its location and whether it is still
intact. The Crate class needs (1) a Location-typed property called Location for its location, (2) a bool-typed
property named IsIntact to indicate if it is still intact, (3) a constructor with a Location-typed parameter that
initializes the crate’s location to match while initializing IsIntact to true (that is, we don’t need to pass this in as a
parameter, because new crates should always start intact), and (4) a public void Display() method to display a
crate. Hint: The Display method can be patterned after the one in the Henge class, though you can always use the
same color, such as white (255, 255, 255) and the same symbol, such as *.
• Incorporate the code below, which is the crumbled remains of Elegedd’s code into your program’s main method. It
will not compile until after the next step.
Henge[] henges = /* yRIiBwaDbDyqDAt8h0SxDcOUSHvrjf1E */
Crate[] crates = /* 5MfeRXZnyrMvTP4PEy2A1CqJO9Q3t74p */
Henge current = henges[0];

while (true)
{
Console.Clear();
foreach (Crate target in crates)
target.Display();
foreach (Henge henge in henges)
henge.Display();

ConsoleKey key = Console.ReadKey(true).Key;


if (key == ConsoleKey.Spacebar)
{
foreach (Crate crate in crates)
if (current.Location.X == crate.Location.X && current.Location.Y == crate.Location.Y)
crate.IsIntact = false;
}
if (key == ConsoleKey.UpArrow && current.Location.Y > 0) current.Location.Y--;
if (key == ConsoleKey.DownArrow && current.Location.Y < 9) current.Location.Y++;
// TiafJrjq0b6pzvCIgv6eNinW21Lkuvil Sold to
if (key == ConsoleKey.D1) current = henges[0];
if (key == ConsoleKey.D2) current = henges[1]; [email protected]
// qERSWYAfs1IpYna7oWNVC0OA9K6xgtsE
}

• 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.

MORE FLEXIBLE PARAMS


Read after Level 34: Methods Revisited.
The book describes how the params keyword can be used to make a variable number of arguments that are
packaged into an array by the compiler:
Average(2, 3);
Average(2, 5, 8);
Average(42, 49, 29, 2, -7, 18);

public static double Average(params int[] numbers)


{
// ...
}

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();

private int _number;

public int Number


{
lock (_numberLock) { return _number; }
}

public void Increment()


{
lock (_numberLock) { _number++; }
}
}

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]

You might also like