From 2c346570f147b0aeb7b0dad3ba83abbd54962446 Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Tue, 2 Dec 2025 14:57:15 -0500 Subject: [PATCH 01/13] First pass edit. --- .../tour-of-csharp/tutorials/hello-world.md | 54 +++--- .../snippets/HelloWorld/HelloWorld.csproj | 2 +- .../tutorials/snippets/HelloWorld/Program.cs | 154 ++++++++---------- 3 files changed, 92 insertions(+), 118 deletions(-) diff --git a/docs/csharp/tour-of-csharp/tutorials/hello-world.md b/docs/csharp/tour-of-csharp/tutorials/hello-world.md index 16b21ad0ebcab..34e6530b76024 100644 --- a/docs/csharp/tour-of-csharp/tutorials/hello-world.md +++ b/docs/csharp/tour-of-csharp/tutorials/hello-world.md @@ -1,23 +1,21 @@ --- -title: Hello World - Introductory interactive tutorial -description: In this tutorial, you use your browser to learn C# interactively. You write C# code and see the results of compiling and running your code directly in the browser. -ms.date: 03/05/2025 +title: Hello World - Introductory tutorial +description: In this tutorial, you create your first C# apps. You write C# code and learn basic structure and types in C#. +ms.date: 12/02/2025 --- -# Introduction to C# - interactive tutorial +# Introduction to C# - tutorial -This tutorial teaches you C# interactively, using your browser to write C# and see the results of compiling and running your code. It contains a series of lessons that begin with a "Hello World" program. These lessons teach you the fundamentals of the C# language. - -> [!TIP] -> -> When a code snippet block includes the "Run" button, that button opens the interactive window, or replaces the existing code in the interactive window. When the snippet doesn't include a "Run" button, you can copy the code and add it to the current interactive window. +This tutorial teaches you C#. You write your first C# and see the results of compiling and running your code. It contains a series of lessons that begin with a "Hello World" program. These lessons teach you the fundamentals of the C# language. ## Run your first program -Run the following code in the interactive window. +TODO: `dotnet new` or create a file. -:::code language="csharp" interactive="try-dotnet-method" source="./snippets/HelloWorld/Program.cs" id="HelloWorld"::: +Type the following code in your new `cs` file: -Congratulations! You ran your first C# program. It's a simple program that prints the message "Hello World!" It used the method to print that message. `Console` is a type that represents the console window. `WriteLine` is a method of the `Console` type that prints a line of text to that text console. +:::code language="csharp" source="./snippets/HelloWorld/Program.cs" id="HelloWorld"::: + +TODO: To run the program, type `dotnet run` (or) `dotnet file.cs` at the command prompt. Congratulations! You ran your first C# program. It's a simple program that prints the message "Hello World!" It used the method to print that message. `Console` is a type that represents the console window. `WriteLine` is a method of the `Console` type that prints a line of text to that text console. Let's move on and explore more. The rest of this lesson explores working with the `string` type, which represents text in C#. Like the `Console` type, the `string` type has methods. The `string` methods work with text. @@ -27,18 +25,18 @@ Your first program printed the `string` "Hello World!" on the screen. > [!TIP] > -> As you explore C# (or any programming language), you make mistakes when you write code. The **compiler** finds those errors and report them to you. When the output contains error messages, look closely at the example code, and the code in the interactive window to see what to fix. That exercise helps you learn the structure of C# code. +> As you explore C# (or any programming language), you make mistakes when you write code. The **compiler** finds those errors and report them to you. When the output contains error messages, look closely at the example code, and the code in your `.cs` file to see what to fix. That exercise helps you learn the structure of C# code. Your first program is limited to printing one message. You can write more useful programs by using *variables*. A *variable* is a symbol you can use to run the same code with different values. Let's try it! Start with the following code: -:::code language="csharp" interactive="try-dotnet-method" source="./snippets/HelloWorld/Program.cs" id="Variables"::: +:::code language="csharp" source="./snippets/HelloWorld/Program.cs" id="Variables"::: The first line declares a variable, `aFriend`, and assigns it a value, "Bill". The second line prints the name. -You can assign different values to any variable you declare. You can change the name to one of your friends. Add these two lines in the preceding interactive window following the code you already added. Make sure you keep the declaration of the `aFriend` variable and its initial assignment. +You can assign different values to any variable you declare. You can change the name to one of your friends. Add these two lines following the code you already added. Make sure you keep the declaration of the `aFriend` variable and its initial assignment. > [!IMPORTANT] -> Don't delete the declaration of `aFriend`. Add the following code at the end of the preceding interactive window: +> Don't delete the declaration of `aFriend`. Add the following code at the end of the preceding code: :::code language="csharp" source="./snippets/HelloWorld/Program.cs" id="Assignment"::: @@ -48,7 +46,7 @@ You might notice that the word "Hello" was missing in the last two messages. Let :::code language="csharp" source="./snippets/HelloWorld/Program.cs" id="ConcatMessage"::: -Select **Run** again to see the results. +TODO: Run the app again using `dotnet run` (or) `dotnet file.cs` to see the results. You've been using `+` to build strings from **variables** and **constant** strings. There's a better way. You can place a variable between `{` and `}` characters to tell C# to replace that text with the value of the variable. @@ -56,25 +54,25 @@ This process is called [String interpolation](../../language-reference/tokens/in If you add a `$` before the opening quote of the string, you can then include variables, like `aFriend`, inside the string between curly braces. Give it a try: -Select **Run** again to see the results. Instead of "Hello {aFriend}", the message should be "Hello Maira". - :::code language="csharp" source="./snippets/HelloWorld/Program.cs" id="Interpolation"::: +TODO: Run the app again using `dotnet run` (or) `dotnet file.cs` to see the results. Instead of "Hello {aFriend}", the message should be "Hello Maira". + ## Work with strings Your last edit was our first look at what you can do with strings. Let's explore more. -You're not limited to a single variable between the curly braces. Try the following code: +You're not limited to a single variable between the curly braces. Try the following code at the bottom of your app: -:::code language="csharp" interactive="try-dotnet-method" source="./snippets/HelloWorld/Program.cs" id="WorkWithStrings"::: +:::code language="csharp" source="./snippets/HelloWorld/Program.cs" id="WorkWithStrings"::: -Strings are more than a collection of letters. You can find the length of a string using `Length`. `Length` is a **property** of a string and it returns the number of characters in that string. Add the following code at the bottom of the interactive window: +Strings are more than a collection of letters. You can find the length of a string using `Length`. `Length` is a **property** of a string and it returns the number of characters in that string. Add the following code at the bottom of your app: :::code language="csharp" source="./snippets/HelloWorld/Program.cs" id="Properties"::: > [!TIP] > -> Now is a good time to explore on your own. You learned that `Console.WriteLine()` writes text to the screen. You learned how to declare variables and concatenate strings together. Experiment in the interactive window. The window has a feature called *IntelliSense* that makes suggestions for what you can do. Type a `.` after the `d` in `firstFriend`. You see a list of suggestions for properties and methods you can use. +> Now is a good time to explore on your own. You learned that `Console.WriteLine()` writes text to the screen. You learned how to declare variables and concatenate strings together. Experiment in your code. Your editor has a feature called *IntelliSense* that makes suggestions for what you can do. Type a `.` after the `d` in `firstFriend`. You see a list of suggestions for properties and methods you can use. You've been using a *method*, , to print messages. A *method* is a block of code that implements some action. It has a name, so you can access it. @@ -83,7 +81,7 @@ You've been using a *method*, method and related methods and do that work. You can just use those methods to remove leading and trailing spaces. Try the following code: -:::code language="csharp" interactive="try-dotnet-method" source="./snippets/HelloWorld/Program.cs" id="Trim"::: +:::code language="csharp" source="./snippets/HelloWorld/Program.cs" id="Trim"::: The square brackets `[` and `]` help visualize what the `Trim`, `TrimStart,` and, `TrimEnd` methods do. The brackets show where whitespace starts and ends. @@ -93,7 +91,7 @@ This sample reinforces a couple of important concepts for working with strings. There are other methods available to work with a string. For example, you probably used a search and replace command in an editor or word processor before. The method does something similar in a string. It searches for a substring and replaces it with different text. The method takes two **parameters**. These parameters are the strings between the parentheses. The first string is the text to search for. The second string is the text to replace it with. Try it for yourself. Add this code. Type it in to see the hints as you start typing `.Re` after the `sayHello` variable: -:::code language="csharp" interactive="try-dotnet-method" source="./snippets/HelloWorld/Program.cs" id="Replace"::: +:::code language="csharp" source="./snippets/HelloWorld/Program.cs" id="Replace"::: Two other useful methods make a string ALL CAPS or all lower case. Try the following code. Type it in to see how **IntelliSense** provides hints as you start to type `To`: @@ -103,7 +101,7 @@ Two other useful methods make a string ALL CAPS or all lower case. Try the follo The other part of a *search and replace* operation is to find text in a string. You can use the method for searching. It tells you if a string contains a substring inside it. Try the following code to explore : -:::code language="csharp" interactive="try-dotnet-method" source="./snippets/HelloWorld/Program.cs" id="SearchStrings"::: +:::code language="csharp" source="./snippets/HelloWorld/Program.cs" id="SearchStrings"::: The method returns a *boolean* value which tells you if the string you were searching for was found. A *boolean* stores either a `true` or a `false` value. When displayed as text output, they're capitalized: `True` and `False`, respectively. You learn more about *boolean* values in a later lesson. @@ -122,11 +120,11 @@ Did you come up with something like the following (expand to see the answer):
-:::code language="csharp" interactive="try-dotnet-method" source="./snippets/HelloWorld/Program.cs" id="Challenge"::: +:::code language="csharp" source="./snippets/HelloWorld/Program.cs" id="Challenge":::
-You completed the "Hello C#" introduction to C# tutorial. You can select the **Numbers in C#** tutorial to start the next interactive tutorial, or you can visit the [.NET site](https://dotnet.microsoft.com/learn/dotnet/hello-world-tutorial/intro) to download the .NET SDK, create a project on your machine, and keep coding. The "Next steps" section brings you back to these tutorials. +You completed the "Hello C#" introduction to C# tutorial. You can select the **Numbers in C#** tutorial to start the next tutorial, or you can visit the [.NET site](https://dotnet.microsoft.com/learn/dotnet/hello-world-tutorial/intro) to download the .NET SDK, create a project on your machine, and keep coding. The "Next steps" section brings you back to these tutorials. For further reading on the `string` type: diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/HelloWorld/HelloWorld.csproj b/docs/csharp/tour-of-csharp/tutorials/snippets/HelloWorld/HelloWorld.csproj index fd4bd08da2987..ed9781c223ab9 100644 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/HelloWorld/HelloWorld.csproj +++ b/docs/csharp/tour-of-csharp/tutorials/snippets/HelloWorld/HelloWorld.csproj @@ -2,7 +2,7 @@ Exe - net9.0 + net10.0 enable enable diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/HelloWorld/Program.cs b/docs/csharp/tour-of-csharp/tutorials/snippets/HelloWorld/Program.cs index fe73550748b2e..29a26f376bada 100644 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/HelloWorld/Program.cs +++ b/docs/csharp/tour-of-csharp/tutorials/snippets/HelloWorld/Program.cs @@ -1,93 +1,69 @@ -PageOne(); -PageTwo(); -PageThree(); -PageFour(); -PageFive(); -PageSix(); -Challenge(); - -void PageOne() -{ - // - Console.WriteLine("Hello, World!"); - // -} - -void PageTwo() -{ - // - string aFriend = "Bill"; - Console.WriteLine(aFriend); - // - - // - aFriend = "Maira"; - Console.WriteLine(aFriend); - // - - // - Console.WriteLine("Hello " + aFriend); - // - - // - Console.WriteLine($"Hello {aFriend}"); - // -} - -void PageThree() -{ - // - string firstFriend = "Maria"; - string secondFriend = "Sage"; - Console.WriteLine($"My friends are {firstFriend} and {secondFriend}"); - // - - // - Console.WriteLine($"The name {firstFriend} has {firstFriend.Length} letters."); - Console.WriteLine($"The name {secondFriend} has {secondFriend.Length} letters."); - // -} - -void PageFour() -{ - // - string greeting = " Hello World! "; - Console.WriteLine($"[{greeting}]"); +// +Console.WriteLine("Hello, World!"); +// + +// +string aFriend = "Bill"; +Console.WriteLine(aFriend); +// + +// +aFriend = "Maira"; +Console.WriteLine(aFriend); +// + +// +Console.WriteLine("Hello " + aFriend); +// + +// +Console.WriteLine($"Hello {aFriend}"); +// + +// +string firstFriend = "Maria"; +string secondFriend = "Sage"; +Console.WriteLine($"My friends are {firstFriend} and {secondFriend}"); +// + +// +Console.WriteLine($"The name {firstFriend} has {firstFriend.Length} letters."); +Console.WriteLine($"The name {secondFriend} has {secondFriend.Length} letters."); +// + +// +string greeting = " Hello World! "; +Console.WriteLine($"[{greeting}]"); + +string trimmedGreeting = greeting.TrimStart(); +Console.WriteLine($"[{trimmedGreeting}]"); + +trimmedGreeting = greeting.TrimEnd(); +Console.WriteLine($"[{trimmedGreeting}]"); + +trimmedGreeting = greeting.Trim(); +Console.WriteLine($"[{trimmedGreeting}]"); +// + +// +string sayHello = "Hello World!"; +Console.WriteLine(sayHello); +sayHello = sayHello.Replace("Hello", "Greetings"); +Console.WriteLine(sayHello); +// + +// +Console.WriteLine(sayHello.ToUpper()); +Console.WriteLine(sayHello.ToLower()); +// + +// +string songLyrics = "You say goodbye, and I say hello"; +Console.WriteLine(songLyrics.Contains("goodbye")); +Console.WriteLine(songLyrics.Contains("greetings")); +// - string trimmedGreeting = greeting.TrimStart(); - Console.WriteLine($"[{trimmedGreeting}]"); - - trimmedGreeting = greeting.TrimEnd(); - Console.WriteLine($"[{trimmedGreeting}]"); - - trimmedGreeting = greeting.Trim(); - Console.WriteLine($"[{trimmedGreeting}]"); - // -} - -void PageFive() -{ - // - string sayHello = "Hello World!"; - Console.WriteLine(sayHello); - sayHello = sayHello.Replace("Hello", "Greetings"); - Console.WriteLine(sayHello); - // - - // - Console.WriteLine(sayHello.ToUpper()); - Console.WriteLine(sayHello.ToLower()); - // -} - -void PageSix() -{ - // - string songLyrics = "You say goodbye, and I say hello"; - Console.WriteLine(songLyrics.Contains("goodbye")); - Console.WriteLine(songLyrics.Contains("greetings")); - // -} +Challenge(); void Challenge() { From 160a109b9672a59f6e97378733ec1c3227ed9c2e Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Tue, 2 Dec 2025 16:23:18 -0500 Subject: [PATCH 02/13] First pass at the numbers tutorial --- .../tutorials/numbers-in-csharp.md | 167 ++++++++++++++---- .../NumbersInCsharp/NumbersInCsharp.csproj | 2 +- .../snippets/NumbersInCsharp/Program.cs | 74 ++++---- 3 files changed, 174 insertions(+), 69 deletions(-) diff --git a/docs/csharp/tour-of-csharp/tutorials/numbers-in-csharp.md b/docs/csharp/tour-of-csharp/tutorials/numbers-in-csharp.md index 40034751c60bb..fa17a36ec25df 100644 --- a/docs/csharp/tour-of-csharp/tutorials/numbers-in-csharp.md +++ b/docs/csharp/tour-of-csharp/tutorials/numbers-in-csharp.md @@ -1,73 +1,165 @@ --- -title: Work with Numbers - Introductory interactive tutorial -description: In this tutorial about numeric types, you use your browser to learn C# interactively. You're going to write C# code and see the results of compiling and running your code directly in the browser. -ms.date: 03/06/2025 +title: Work with Numbers - Introductory tutorial +description: This tutorial teaches you about the numeric types in C#. The tutorial contains a series of lessons that explore numbers and math operations in C#. +ms.date: 12/02/2025 --- # How to use integer and floating point numbers in C\# This tutorial teaches you about the numeric types in C#. You write small amounts of code, then you compile and run that code. The tutorial contains a series of lessons that explore numbers and math operations in C#. These lessons teach you the fundamentals of the C# language. -> [!TIP] -> -> When a code snippet block includes the "Run" button, that button opens the interactive window, or replaces the existing code in the interactive window. When the snippet doesn't include a "Run" button, you can copy the code and add it to the current interactive window. +## Explore integer math ## Explore integer math -Run the following code in the interactive window. +Create a directory named *numbers-quickstart*. Make it the current directory and run the following command: + +```dotnetcli +dotnet new console -n NumbersInCSharp -o . +``` + +Open *Program.cs* in your favorite editor, and replace the contents of the file with the following code: -:::code language="csharp" interactive="try-dotnet-method" source="./snippets/NumbersInCsharp/Program.cs" id="Addition"::: +:::code language="csharp" source="./snippets/NumbersInCsharp/Program.cs" id="Addition"::: +Addition -The preceding code demonstrates fundamental math operations with integers. The `int` type represents an **integer**, a positive or negative whole number. You use the `+` symbol for addition. Other common mathematical operations for integers include: +Run this code by typing `dotnet run` in your command window. + +You've seen one of the fundamental math operations with integers. The `int` type represents an **integer**, a zero, positive, or negative whole number. You use the `+` symbol for addition. Other common mathematical operations for integers include: - `-` for subtraction - `*` for multiplication - `/` for division -Start by exploring those different operations. Modify the third line to try each of these operations. For example, to try subtraction, replace the `+` with a `-` as shown in the following line: +Start by exploring those different operations. Add these lines after the line that writes the value of `c`: -```csharp -int c = a - b; -``` +:::code language="csharp" source="./snippets/NumbersInCsharp/Program.cs" id="OtherOperations"::: + +Run this code by typing `dotnet run` in your command window. -Try it. Select the "Run" button. Then, try multiplication, `*` and, division, `/`. You can also experiment by writing multiple mathematics operations in the same line, if you'd like. +You can also experiment by writing multiple mathematics operations in the same line, if you'd like. Try `c = a + b - 12 * 17;` for example. Mixing variables and constant numbers is allowed. > [!TIP] -> -> As you explore C# (or any programming language), you make mistakes when you write code. The **compiler** finds those errors and report them to you. When the output contains error messages, look closely at the example code, and the code in the interactive window to see what to fix. That exercise helps you learn the structure of C# code. +> As you explore C# (or any programming language), you'll make mistakes when you write code. The **compiler** will find those errors and report them to you. When the output contains error messages, look closely at the example code and the code in your window to see what to fix. That exercise will help you learn the structure of C# code. + +You've finished the first step. Before you start the next section, let's move the current code into a separate *method*. A method is a series of statements grouped together and given a name. You call a method by writing the method's name followed by `()`. Organizing your code into methods makes it easier to start working with a new example. When you finish, your code should look like this: + +```csharp +WorkWithIntegers(); + +void WorkWithIntegers() +{ + int a = 18; + int b = 6; + int c = a + b; + Console.WriteLine(c); + + + // subtraction + c = a - b; + Console.WriteLine(c); + + // multiplication + c = a * b; + Console.WriteLine(c); + + // division + c = a / b; + Console.WriteLine(c); +} +``` ## Explore order of operations -The C# language defines the precedence of different mathematics operations with rules consistent with the rules you learned in mathematics. Multiplication and division take precedence over addition and subtraction. Explore that by running the following code in the interactive window: +Comment out the call to `WorkingWithIntegers()`. It will make the output less cluttered as you work in this section: + +```csharp +//WorkWithIntegers(); +``` + +The `//` starts a **comment** in C#. Comments are any text you want to keep in your source code but not execute as code. The compiler doesn't generate any executable code from comments. Because `WorkWithIntegers()` is a method, you need to only comment out one line. + +The C# language defines the precedence of different mathematics operations with rules consistent with the rules you learned in mathematics. Multiplication and division take precedence over addition and subtraction. Explore that by adding the following code after the call to `WorkWithIntegers()`, and executing `dotnet run`: -:::code language="csharp" interactive="try-dotnet-method" source="./snippets/NumbersInCsharp/Program.cs" id="Precedence"::: +:::code language="csharp" source="./snippets/NumbersInCsharp/Program.cs" id="Precedence"::: The output demonstrates that the multiplication is performed before the addition. -You can force a different order of operation by adding parentheses around the operation or operations you want performed first. Add the following lines to the interactive window: +You can force a different order of operation by adding parentheses around the operation or operations you want performed first. Add the following lines and run again: :::code language="csharp" source="./snippets/NumbersInCsharp/Program.cs" id="Parentheses"::: -Explore more by combining many different operations. Replace the fourth line in the preceding code with something like this: +Explore more by combining many different operations. Add something like the following lines. Try `dotnet run` again. :::code language="csharp" source="./snippets/NumbersInCsharp/Program.cs" id="CompoundExpression"::: -You might notice an interesting behavior for integers. Integer division always produces an integer result, even when you'd expect the result to include a decimal or fractional portion. +You may have noticed an interesting behavior for integers. Integer division always produces an integer result, even when you'd expect the result to include a decimal or fractional portion. + +If you haven't seen this behavior, try the following code: + +:::code language="csharp" source="./snippets/NumbersInCsharp/Program.cs" id="Truncation"::: -Try the following code: +Type `dotnet run` again to see the results. -:::code language="csharp" interactive="try-dotnet-method" source="./snippets/NumbersInCsharp/Program.cs" id="Truncation"::: +Before moving on, let's take all the code you've written in this section and put it in a new method. Call that new method `OrderPrecedence`. Your code should look something like this: + +```csharp +// WorkWithIntegers(); +OrderPrecedence(); + +void WorkWithIntegers() +{ + int a = 18; + int b = 6; + int c = a + b; + Console.WriteLine(c); + + + // subtraction + c = a - b; + Console.WriteLine(c); + + // multiplication + c = a * b; + Console.WriteLine(c); + + // division + c = a / b; + Console.WriteLine(c); +} + +void OrderPrecedence() +{ + int a = 5; + int b = 4; + int c = 2; + int d = a + b * c; + Console.WriteLine(d); + + d = (a + b) * c; + Console.WriteLine(d); + + d = (a + b) - 6 * c + (12 * 4) / 3 + 12; + Console.WriteLine(d); + + int e = 7; + int f = 4; + int g = 3; + int h = (e + f) / g; + Console.WriteLine(h); +} +``` ## Explore integer precision and limits -That last sample showed you that integer division truncates the result. You can get the **remainder** by using the **remainder** operator, the `%` character: +That last sample showed you that integer division truncates the result. You can get the **remainder** by using the **remaimnder** operator, the `%` character. Try the following code after the method call to `OrderPrecedence()`: -:::code language="csharp" interactive="try-dotnet-method" source="./snippets/NumbersInCsharp/Program.cs" id="QuotientAndRemainder"::: +:::code language="csharp" source="./snippets/NumbersInCsharp/Program.cs" id="QuotientAndRemainder"::: The C# integer type differs from mathematical integers in one other way: the `int` type has minimum and maximum limits. Try the following code to see those limits: :::code language="csharp" source="./snippets/NumbersInCsharp/Program.cs" id="MinAndMax"::: -If a calculation produces a value that exceeds those limits, you have an **underflow** or **overflow** condition. The answer appears to wrap from one limit to the other. To see an example, add these two lines in the interactive window: +If a calculation produces a value that exceeds those limits, you have an **underflow** or **overflow** condition. The answer appears to wrap from one limit to the other. To see an example, add these two lines to your code: :::code language="csharp" source="./snippets/NumbersInCsharp/Program.cs" id="Overflow"::: @@ -77,21 +169,19 @@ There are other numeric types with different limits and precision that you would ## Work with the double type -The `double` numeric type represents a double-precision floating point number. Those terms might be new to you. A **floating point** number is useful to represent nonintegral numbers that might be large or small in magnitude. **Double-precision** is a relative term that describes the number of binary digits used to store the value. **Double precision** numbers have twice the number of binary digits as **single-precision**. On modern computers, it's more common to use double precision than single precision numbers. **Single precision** numbers are declared using the `float` keyword. Let's explore. Run the following code and see the result: +The `double` numeric type represents a double-precision floating point number. Those terms may be new to you. A **floating point** number is useful to represent non-integral numbers that may be very large or small in magnitude. **Double-precision** is a relative term that describes the number of binary digits used to store the value. **Double precision** numbers have twice the number of binary digits as **single-precision**. On modern computers, it's more common to use double precision than single precision numbers. **Single precision** numbers are declared using the `float` keyword. Let's explore. Add the following code and see the result: -:::code language="csharp" interactive="try-dotnet-method" source="./snippets/NumbersInCsharp/Program.cs" id="FloatingPoint"::: +:::code language="csharp" source="./snippets/NumbersInCsharp/Program.cs" id="FloatingPoint"::: Notice that the answer includes the decimal portion of the quotient. Try a slightly more complicated expression with doubles. You can use the following values, or substitute other numbers: :::code language="csharp" source="./snippets/NumbersInCsharp/Program.cs" id="ChangeDoubleValues"::: -The range of a double value is greater than integer values. Try the following code in the interactive window: +The range of a double value is much greater than integer values. Try the following code below what you've written so far: :::code language="csharp" source="./snippets/NumbersInCsharp/Program.cs" id="MinMax"::: -These values are printed in scientific notation. The number before the `E` is the significand. The number after the `E` is the exponent, as a power of 10. - -Just like decimal numbers in math, doubles in C# can have rounding errors. Try this code: +These values are printed in scientific notation. The number to the left of the `E` is the significand. The number to the right is the exponent, as a power of 10. Just like decimal numbers in math, doubles in C# can have rounding errors. Try this code: :::code language="csharp" source="./snippets/NumbersInCsharp/Program.cs" id="RoundingError"::: @@ -99,13 +189,15 @@ You know that `0.3` is `3/10` and not exactly the same as `1/3`. Similarly, `0.3 ***Challenge*** -Try other calculations with large numbers, small numbers, multiplication, and division using the `double` type. Try more complicated calculations. +Try other calculations with large numbers, small numbers, multiplication, and division using the `double` type. Try more complicated calculations. After you've spent some time with the challenge, take the code you've written and place it in a new method. Name that new method `WorkWithDoubles`. ## Work with decimal types -There's one other type to learn: the `decimal` type. The `decimal` type has a smaller range but greater precision than `double`. Let's take a look: +You've seen the basic numeric types in C#: integers and doubles. There's one other type to learn: the `decimal` type. The `decimal` type has a smaller range but greater precision than `double`. Let's take a look: + +:::code language="csharp" source="./snippets/NumbersInCsharp/Program.cs" id="Decimal"::: -:::code language="csharp" interactive="try-dotnet-method" source="./snippets/NumbersInCsharp/Program.cs" id="Decimal"::: +There's one other type to learn: the `decimal` type. The `decimal` type has a smaller range but greater precision than `double`. Let's take a look: Notice that the range is smaller than the `double` type. You can see the greater precision with the decimal type by trying the following code: @@ -117,10 +209,11 @@ The `M` suffix on the numbers is how you indicate that a constant should use the > [!NOTE] > The letter `M` was chosen as the most visually distinct letter between the `double` and `decimal` keywords. +Notice that the math using the decimal type has more digits to the right of the decimal point. ***Challenge*** -Write code that calculates the area of a circle whose radius is 2.50 centimeters. Remember that the area of a circle is the radius squared multiplied by PI. One hint: .NET contains a constant for PI, that you can use for that value. , like all constants declared in the `System.Math` namespace, is a `double` value. For that reason, you should use `double` instead of `decimal` values for this challenge. +Now that you've seen the different numeric types, write code that calculates the area of a circle whose radius is 2.50 centimeters. Remember that the area of a circle is the radius squared multiplied by PI. One hint: .NET contains a constant for PI, that you can use for that value. , like all constants declared in the `System.Math` namespace, is a `double` value. For that reason, you should use `double` instead of `decimal` values for this challenge. You should get an answer between 19 and 20. @@ -135,7 +228,7 @@ Once you try it, open the details pane to see how you did: Try some other formulas if you'd like. -You completed the "Numbers in C#" interactive tutorial. You can select the **Tuples and types** link to start the next interactive tutorial, or you can visit the [.NET site](https://dotnet.microsoft.com/learn/dotnet/hello-world-tutorial/intro) to download the .NET SDK, create a project on your machine, and keep coding. The "Next steps" section brings you back to these tutorials. +You completed the "Numbers in C#" tutorial. You can select the **Tuples and types** link to start the next tutorial, or you can visit the [.NET site](https://dotnet.microsoft.com/learn/dotnet/hello-world-tutorial/intro) to download the .NET SDK, create a project on your machine, and keep coding. The "Next steps" section brings you back to these tutorials. You can learn more about numbers in C# in the following articles: diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/NumbersInCsharp/NumbersInCsharp.csproj b/docs/csharp/tour-of-csharp/tutorials/snippets/NumbersInCsharp/NumbersInCsharp.csproj index fd4bd08da2987..ed9781c223ab9 100644 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/NumbersInCsharp/NumbersInCsharp.csproj +++ b/docs/csharp/tour-of-csharp/tutorials/snippets/NumbersInCsharp/NumbersInCsharp.csproj @@ -2,7 +2,7 @@ Exe - net9.0 + net10.0 enable enable diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/NumbersInCsharp/Program.cs b/docs/csharp/tour-of-csharp/tutorials/snippets/NumbersInCsharp/Program.cs index d320628b0b1bf..0f8bee593b7f0 100644 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/NumbersInCsharp/Program.cs +++ b/docs/csharp/tour-of-csharp/tutorials/snippets/NumbersInCsharp/Program.cs @@ -1,22 +1,12 @@  -PageOne(); -PageTwo(); -MorePageTwo(); -PageThree(); -PageFour(); -PageFive(); - -// Bonus calculation: -// -double a = 19; -double b = 23; -double c = 8; -double d = (a + b) / c; -Console.WriteLine(d); -// - - -void PageOne() +WorkWithIntegers(); +OrderPrecedence(); +QuotientAndRemainder(); +FloatingPoint(); +Decimal(); +Challenge(); + +void WorkWithIntegers() { // int a = 18; @@ -24,9 +14,23 @@ void PageOne() int c = a + b; Console.WriteLine(c); // + + // + // subtraction + c = a - b; + Console.WriteLine(c); + + // multiplication + c = a * b; + Console.WriteLine(c); + + // division + c = a / b; + Console.WriteLine(c); + // } -void PageTwo() +void OrderPrecedence() { // int a = 5; @@ -45,20 +49,17 @@ void PageTwo() d = (a + b) - 6 * c + (12 * 4) / 3 + 12; Console.WriteLine(d); // -} -void MorePageTwo() -{ // - int a = 7; - int b = 4; - int c = 3; - int d = (a + b) / c; - Console.WriteLine(d); + int e = 7; + int f = 4; + int g = 3; + int h = (e + f) / g; + Console.WriteLine(h); // } -void PageThree() +void QuotientAndRemainder() { // int a = 7; @@ -80,10 +81,9 @@ void PageThree() int what = max + 3; Console.WriteLine($"An example of overflow: {what}"); // - } -void PageFour() +void FloatingPoint() { // double a = 5; @@ -105,7 +105,7 @@ void PageFour() // } -void PageFive() +void Decimal() { // decimal min = decimal.MinValue; @@ -129,3 +129,15 @@ void PageFive() Console.WriteLine(area); // } + +void Challenge() +{ + // + double a = 19; + double b = 23; + double c = 8; + double d = (a + b) / c; + Console.WriteLine(d); + // +} + From cd575720f31761e06038d6e7139ca3134c6a2c1f Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Wed, 3 Dec 2025 14:51:40 -0500 Subject: [PATCH 03/13] First pass of Tuples and types First edit pass on tuples and types. --- .../snippets/TuplesAndTypes/PointEvolution.cs | 15 ---- .../snippets/TuplesAndTypes/PointStruct.cs | 31 ------- .../snippets/TuplesAndTypes/Program.cs | 85 ++++++++++++------- .../TuplesAndTypes/TuplesAndTypes.csproj | 2 +- .../tutorials/tuples-and-types.md | 48 ++++++----- 5 files changed, 78 insertions(+), 103 deletions(-) delete mode 100644 docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/PointEvolution.cs delete mode 100644 docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/PointStruct.cs diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/PointEvolution.cs b/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/PointEvolution.cs deleted file mode 100644 index 1edbac77c5f4f..0000000000000 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/PointEvolution.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace PointEvolution; - -public static class SampleTwo -{ - // - public record Point(int X, int Y); - - public static void Main() - { - Point pt = new Point(1, 1); - var pt2 = pt with { Y = 10 }; - Console.WriteLine($"The two points are {pt} and {pt2}"); - } - // -} diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/PointStruct.cs b/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/PointStruct.cs deleted file mode 100644 index 2ee93b8cf47f7..0000000000000 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/PointStruct.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace FinalRecord -{ - public static class SampleThree - { - // - public record Point(int X, int Y) - { - public double Slope() => (double)Y / (double)X; - } - // - public static void Main() - { - Point pt = new Point(1, 1); - var pt2 = pt with { Y = 10 }; - // - double slope = pt.Slope(); - Console.WriteLine($"The slope of {pt} is {slope}"); - // - } - } -} - -namespace MoreStruct -{ - // - public record struct Point(int X, int Y) - { - public double Slope() => (double) Y / (double) X; - } - // -} diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/Program.cs b/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/Program.cs index 291fb75394c85..b88b1f1cebec8 100644 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/Program.cs +++ b/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/Program.cs @@ -1,37 +1,56 @@ - -using System.Xml.Linq; - -FirstExample(); +// +var pt = (X: 1, Y: 2); + +var slope = (double)pt.Y / (double)pt.X; +Console.WriteLine($"A line from the origin to the point {pt} has a slope of {slope}."); +// + +// +pt.X = pt.X + 5; +Console.WriteLine($"The point is now at {pt}."); +// + +// +var pt2 = pt with { Y = 10 }; +Console.WriteLine($"The point 'pt2' is at {pt2}."); +// + +// +var subscript = (A: 0, B: 0); +subscript = pt; +Console.WriteLine(subscript); +// + +// +var namedData = (Name: "Morning observation", Temp: 17, Wind: 4); +var person = (FirstName: "", LastName: ""); +var order = (Product: "guitar picks", style: "triangle", quantity: 500, UnitPrice: 0.10m); +// + +// +Point pt3 = new Point(1, 1); +var pt4 = pt3 with { Y = 10 }; +Console.WriteLine($"The two points are {pt} and {pt2}"); +// + +// +double slopeResult = pt4.Slope(); +Console.WriteLine($"The slope of {pt4} is {slopeResult}"); +// + +// +public record struct Point(int X, int Y) +// +// +{ + public double Slope() => (double)Y / (double)X; +} +// -void FirstExample() +namespace PrimaryRecord { - // - var pt = (X: 1, Y: 2); - - var slope = (double)pt.Y / (double)pt.X; - Console.WriteLine($"A line from the origin to the point {pt} has a slope of {slope}."); - // - - // - pt.X = pt.X + 5; - Console.WriteLine($"The point is now at {pt}."); - // - - // - var pt2 = pt with { Y = 10 }; - Console.WriteLine($"The point 'pt2' is at {pt2}."); - // - - // - var subscript = (A: 0, B: 0); - subscript = pt; - Console.WriteLine(subscript); - // - - // - var namedData = (Name: "Morning observation", Temp: 17, Wind: 4); - var person = (FirstName: "", LastName: ""); - var order = (Product: "guitar picks", style: "triangle", quantity: 500, UnitPrice: 0.10m); - // + // + public record Point(int X, int Y); + // } diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/TuplesAndTypes.csproj b/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/TuplesAndTypes.csproj index fd4bd08da2987..ed9781c223ab9 100644 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/TuplesAndTypes.csproj +++ b/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/TuplesAndTypes.csproj @@ -2,7 +2,7 @@ Exe - net9.0 + net10.0 enable enable diff --git a/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md b/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md index 7dd87fe4b1b60..541522bc86f3d 100644 --- a/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md +++ b/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md @@ -1,37 +1,36 @@ --- -title: Tuples and types - Introductory interactive tutorial -description: In this tutorial about creating types, you use your browser to learn C# interactively. You're going to write C# code and see the results of compiling and running your code directly in the browser. -ms.date: 04/03/2025 +title: Tuples and types - Introductory tutorial +description: This tutorial teaches you to create types in C#. You write C# code and see the results of compiling and running your code as you learn the structure of types. +ms.date: 12/03/2025 --- # Create types in C\# This tutorial teaches you about creating types in C#. You write small amounts of code, then you compile and run that code. The tutorial contains a series of lessons that explore different kinds of types in C#. These lessons teach you the fundamentals of the C# language. -> [!TIP] -> When a code snippet block includes the "Run" button, that button opens the interactive window, or replaces the existing code in the interactive window. When the snippet doesn't include a "Run" button, you can copy the code and add it to the current interactive window. - The preceding tutorials worked with text and numbers. Strings and Numbers are *simple types*: They each store one single value. As your programs grow larger, you need to work with more sophisticated data structures. C# provides different kinds of types you can define when you need data structures with more fields, properties, or behavior. Let's start to explore those types. +TODO: Create sample. + ## Tuples -*Tuples* are an ordered sequence of values with a fixed length. Each element of a tuple has a type and an optional name. The following code declares a tuple that represents a 2D point. Select the "Run" button to paste the following code into the interactive window and run it. +*Tuples* are an ordered sequence of values with a fixed length. Each element of a tuple has a type and an optional name. The following code declares a tuple that represents a 2D point. Copy the following code to your file and type `dotnet run`. -:::code language="csharp" interactive="try-dotnet-method" source="./snippets/TuplesAndTypes/Program.cs" id="CreateTuple"::: +:::code language="csharp" source="./snippets/TuplesAndTypes/Program.cs" id="CreateTuple"::: > [!TIP] -> As you explore C# (or any programming language), you make mistakes when you write code. The **compiler** finds those errors and reports them to you. When the output contains error messages, look closely at the example code and the code in the interactive window to see what to fix. That exercise helps you learn the structure of C# code. +> As you explore C# (or any programming language), you make mistakes when you write code. The **compiler** finds those errors and reports them to you. When the output contains error messages, look closely at the example code and your code to see what to fix. That exercise helps you learn the structure of C# code. You can also ask Copilot to find differences or spot any mistakes. -You can reassign any member of a tuple. Add the following code in the interactive window after the existing code. Press "Run" again to see the results. +You can reassign any member of a tuple. Add the following code after the existing code. Type `dotnet run` again to see the results. :::code language="csharp" source="./snippets/TuplesAndTypes/Program.cs" id="Modify"::: -You can also create a new tuple that's a modified copy of the original using a `with` expression. Add the following code after the code already in the interactive window and press "Run" to see the results: +You can also create a new tuple that's a modified copy of the original using a `with` expression. Add the following code after the existing code and type `dotnet run` to see the results: :::code language="csharp" source="./snippets/TuplesAndTypes/Program.cs" id="Wither"::: The tuple `pt2` contains the `X` value of `pt` (6), and `pt2.Y` is 10. -Tuples are structural types. In other words, tuple types don't have names like `string` or `int`. A tuple type is defined by the number of members, referred to as *arity*, and the types of those members. The member names are for convenience. You can assign a tuple to a tuple with the same arity and types even if the members have different names. You can add the following code after the code you already wrote in the interactive window and try it: +Tuples are structural types. In other words, tuple types don't have names like `string` or `int`. A tuple type is defined by the number of members, referred to as *arity*, and the types of those members. The member names are for convenience. You can assign a tuple to a tuple with the same arity and types even if the members have different names. You can add the following code after the code you already wrote and try it: :::code language="csharp" source="./snippets/TuplesAndTypes/Program.cs" id="NamedAssignment"::: @@ -41,32 +40,35 @@ Tuples are easy to create: You declare multiple members enclosed in parentheses. :::code language="csharp" source="./snippets/TuplesAndTypes/Program.cs" id="TupleTypes"::: -Tuples are easy to create, but they're limited in their capabilities. Tuple types don't have names, so you can't convey meaning to the set of values. Tuple types can't add behavior. C# has other kinds of types you can create when your type defines behavior. +While tuples are easy to create, they're limited in their capabilities. Tuple types don't have names, so you can't convey meaning to the set of values. Tuple types can't add behavior. C# has other kinds of types you can create when your type defines behavior. ## Create record types Tuples are great for those times when you want multiple values in the same structure. They're lightweight, and can be declared as they're used. As your program goes, you might find that you use the same tuple type throughout your code. If your app does work in the 2D graph space, the tuples that represent points might be common. Once you find that, you can declare a `record` type that stores those values and provides more capabilities. The following code sample uses a `Main` method to represent the entry point for the program. That way, you can declare a `record` type preceding the entry point in the code. Press the "Run" button on the following code to replace your existing sample with the following code. -> [!WARNING] -> Don't copy and paste. The interactive window must be reset to run the following sample. If you make a mistake, the window hangs, and you need to refresh the page to continue. +The following code declares and uses a `record` type to represent a `Point`: + +:::code language="csharp" source="./snippets/TuplesAndTypes/PointEvolution.cs" id="PointRecord"::: + +The preceding code must be at the bottom of your source file. Type declarations like `record` declarations must follow executable statements in a file-based app. -The following code declares and uses a `record` type to represent a `Point`, and then uses that `Point` structure in the `Main` method: +Add the following code preceding the `record` declaration: -:::code language="csharp" interactive="try-dotnet-class" source="./snippets/TuplesAndTypes/PointEvolution.cs" id="PointVersion2"::: +:::code language="csharp" source="./snippets/TuplesAndTypes/PointEvolution.cs" id="UsePointRecord"::: -The `record` declaration is a single line of code for the `Point` type that stores the values `X` and `Y` in readonly properties. You use the name `Point` wherever you use that type. Properly named types, like `Point`, provide information about how the type is used. The `Main` method shows how to use a `with` expression to create a new point that's a modified copy of the existing point. The line `pt2 = pt with { Y = 10 }` says "`pt2` has the same values as `pt` except that `Y` is assigned to 10." You can add any number of properties to change in a single `with` expression. +The `record` declaration is a single line of code for the `Point` type that stores the values `X` and `Y` in readonly properties. You use the name `Point` wherever you use that type. Properly named types, like `Point`, provide information about how the type is used. The additional code shows how to use a `with` expression to create a new point that's a modified copy of the existing point. The line `pt4 = pt3 with { Y = 10 }` says "`pt4` has the same values as `pt3` except that `Y` is assigned to 10." You can add any number of properties to change in a single `with` expression. -The preceding `record` declaration is a single line of code that ends in `;`, like all C# statements. You can add behavior to a `record` type by declaring *members*. A record member can be a function, or more data elements. The members of a type are in the type declaration, between `{` and `}` characters. Replace the record declaration you made with the following code: +The preceding `record` declaration is a single line of code that ends in `;`. You can add behavior to a `record` type by declaring *members*. A record member can be a function, or more data elements. The members of a type are in the type declaration, between `{` and `}` characters. Delete the `;` and add the following lines of code after the `record` declaration: -:::code language="csharp" source="./snippets/TuplesAndTypes/PointStruct.cs" id="PointVersion3"::: +:::code language="csharp" source="./snippets/TuplesAndTypes/PointStruct.cs" id="AddSlopeMethod"::: -Then, add the following code to the `Main` method after the line containing the `with` expression: +Then, add the following code before the `record` declaration, after the line containing the `with` expression: :::code language="csharp" source="./snippets/TuplesAndTypes/PointStruct.cs" id="UseSlope"::: You added formality to the *tuple* representing an `X` and `Y` value. You made it a `record` that defined a named type, and included a member to calculate the slope. A `record` type is a shorthand for a `record class`: A `class` type that includes extra behavior. You can modify the `Point` type to make it a `record struct` as well: -:::code language="csharp" source="./snippets/TuplesAndTypes/PointStruct.cs" id="RecordStruct"::: +:::code language="csharp" source="./snippets/TuplesAndTypes/PointStruct.cs" id="RecordStructPoint"::: A `record struct` is a `struct` type that includes the extra behavior added to all `record` types. @@ -86,7 +88,7 @@ You can also define `interface` types to declare behavioral contracts that diffe You typically use all these types in larger programs and libraries. Once you install the .NET SDK, you can explore those types using tutorials on [classes](../../fundamentals/tutorials/classes.md) in the fundamentals section. -You completed the "Create types in C#" interactive tutorial. You can select the **Branches and Loops** link to start the next interactive tutorial, or you can visit the [.NET site](https://dotnet.microsoft.com/learn/dotnet/hello-world-tutorial/intro) to download the .NET SDK, create a project on your machine, and keep coding. The "Next steps" section brings you back to these tutorials. +You completed the "Create types in C#" tutorial. You can select the **Branches and Loops** link to start the next tutorial. You can learn more about types in C# in the following articles: From 0e5c7719913177dc0a84a20df9062ad7f2617c0a Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Wed, 3 Dec 2025 14:52:05 -0500 Subject: [PATCH 04/13] First edit pass on branches and loops First edit pass updating the branches and loops tutorial. --- .../tutorials/branches-and-loops.md | 79 ++++++++++--------- .../BranchesAndLoops/BranchesAndLoops.csproj | 2 +- .../snippets/BranchesAndLoops/Program.cs | 41 ++++++++++ 3 files changed, 84 insertions(+), 38 deletions(-) diff --git a/docs/csharp/tour-of-csharp/tutorials/branches-and-loops.md b/docs/csharp/tour-of-csharp/tutorials/branches-and-loops.md index 63ef54f90d20f..f70e19595b619 100644 --- a/docs/csharp/tour-of-csharp/tutorials/branches-and-loops.md +++ b/docs/csharp/tour-of-csharp/tutorials/branches-and-loops.md @@ -1,57 +1,50 @@ --- title: Branches and loops - Introductory tutorial description: In this tutorial about branches and loops, you write C# code to explore the language syntax that supports conditional branches and loops to execute statements repeatedly. You write C# code and see the results of compiling and running your code directly in the browser. -ms.date: 03/06/2025 +ms.date: 12/03/2025 --- # C# `if` statements and loops - conditional logic tutorial This tutorial teaches you how to write C# code that examines variables and changes the execution path based on those variables. You write C# code and see the results of compiling and running it. The tutorial contains a series of lessons that explore branching and looping constructs in C#. These lessons teach you the fundamentals of the C# language. -> [!TIP] -> -> When a code snippet block includes the "Run" button, that button opens the interactive window, or replaces the existing code in the interactive window. When the snippet doesn't include a "Run" button, you can copy the code and add it to the current interactive window. +TODO: Build an app, create a file. -Run the following code in the interactive window. Select **Run**: +Open *Program.cs* in your favorite editor, and replace the contents with the following code: -:::code language="csharp" interactive="try-dotnet-method" source="./snippets/BranchesAndLoops/Program.cs" id="FirstIf"::: +:::code language="csharp" source="./snippets/BranchesAndLoops/Program.cs" id="FirstIf"::: -Modify the declaration of `b` so that the sum is less than 10: +Try this code by typing `dotnet run` in your console window. You should see the message "The answer is greater than 10." printed to your console. Modify the declaration of `b` so that the sum is less than 10: ```csharp int b = 3; ``` -Select the **Run** button again. Because the answer is less than 10, nothing is printed. The **condition** you're testing is false. You don't have any code to execute because you only wrote one of the possible branches for an `if` statement: the true branch. +Type `dotnet run` again. Because the answer is less than 10, nothing is printed. The **condition** you're testing is false. You don't have any code to execute because you've only written one of the possible branches for an `if` statement: the true branch. > [!TIP] -> -> As you explore C# (or any programming language), you make mistakes when you write code. The **compiler** finds those errors and report them to you. When the output contains error messages, look closely at the example code, and the code in the interactive window to see what to fix. That exercise helps you learn the structure of C# code. - -This first sample shows the power of `if` and boolean types. A *boolean* is a variable that can have one of two values: `true` or `false`. C# defines a special type, `bool` for boolean variables. The `if` statement checks the value of a `bool`. When the value is `true`, the statement following the `if` executes. Otherwise, it's skipped. +> As you explore C# (or any programming language), you'll make mistakes when you write code. The compiler will find and report the errors. Look closely at the error output and the code that generated the error. The compiler error can usually help you find the problem. -This process of checking conditions and executing statements based on those conditions is powerful. Let's explore more. +This first sample shows the power of `if` and Boolean types. A *Boolean* is a variable that can have one of two values: `true` or `false`. C# defines a special type, `bool` for Boolean variables. The `if` statement checks the value of a `bool`. When the value is `true`, the statement following the `if` executes. Otherwise, it's skipped. This process of checking conditions and executing statements based on those conditions is powerful. Let's explore more. ## Make if and else work together -To execute different code in both the true and false branches, you create an `else` branch that executes when the condition is false. Try the following code: +To execute different code in both the true and false branches, you create an `else` branch that executes when the condition is false. Try an `else` branch. Add the last two lines in the following code snippet (you should already have the first four): -:::code language="csharp" interactive="try-dotnet-method" source="./snippets/BranchesAndLoops/Program.cs" id="IfAndElse"::: +:::code language="csharp" source="./snippets/BranchesAndLoops/Program.cs" id="IfAndElse"::: -The statement following the `else` keyword executes only when the condition being tested is `false`. Combining `if` and `else` with boolean conditions provides all the power you need. +The statement following the `else` keyword executes only when the condition being tested is `false`. Combining `if` and `else` with Boolean conditions provides all the power you need to handle both a `true` and a `false` condition. > [!IMPORTANT] -> > The indentation under the `if` and `else` statements is for human readers. The C# language doesn't treat indentation or white space as significant. The statement following the `if` or `else` keyword executes based on the condition. All the samples in this tutorial follow a common practice to indent lines based on the control flow of statements. -Because indentation isn't significant, you need to use `{` and `}` to indicate when you want more than one statement to be part of the block that executes conditionally. C# programmers typically use those braces on all `if` and `else` clauses. The following example is the same as what you created. Try it. +Because indentation isn't significant, you need to use `{` and `}` to indicate when you want more than one statement to be part of the block that executes conditionally. C# programmers typically use those braces on all `if` and `else` clauses. The following example is the same as what you created. Modify your code above to match the following code: :::code language="csharp" source="./snippets/BranchesAndLoops/Program.cs" id="IncludeBraces"::: > [!TIP] -> > Through the rest of this tutorial, the code samples all include the braces, following accepted practices. -You can test more complicated conditions: +You can test more complicated conditions. Add the following code after the code you've written so far: :::code language="csharp" source="./snippets/BranchesAndLoops/Program.cs" id="ComplexConditions"::: @@ -59,45 +52,55 @@ The `==` symbol tests for *equality*. Using `==` distinguishes the test for equa The `&&` represents "and". It means both conditions must be true to execute the statement in the true branch. These examples also show that you can have multiple statements in each conditional branch, provided you enclose them in `{` and `}`. -You can also use `||` to represent "or": +You can also use `||` to represent "or". Add the following code after what you've written so far: :::code language="csharp" source="./snippets/BranchesAndLoops/Program.cs" id="UseOr"::: Modify the values of `a`, `b`, and `c` and switch between `&&` and `||` to explore. You gain more understanding of how the `&&` and `||` operators work. +You finished the first step. Before you start the next section, let's move the current code into a separate method. That makes it easier to start working with a new example. Put the existing code in a method called `ExploreIf()`. Call it from the top of your program. When you finished those changes, your code should look like the following: + +:::code language="csharp" source="./snippets/BranchesAndLoops/Program.cs" id="Refactor"::: + +Comment out the call to `ExploreIf()`. It will make the output less cluttered as you work in this section: + +```csharp +//ExploreIf(); +``` + +The `//` starts a **comment** in C#. Comments are any text you want to keep in your source code but not execute as code. The compiler doesn't generate any executable code from comments. + ## Use loops to repeat operations -Another important concept to create larger programs is **loops**. You use loops to repeat statements that you want executed more than once. Try this code in the interactive window: +Another important concept to create larger programs is **loops**. You use loops to repeat statements that you want executed more than once. Add this code after the call to `ExploreIf`: -:::code language="csharp" interactive="try-dotnet-method" source="./snippets/BranchesAndLoops/Program.cs" id="WhileLoop"::: +:::code language="csharp" source="./snippets/BranchesAndLoops/Program.cs" id="WhileLoop"::: The `while` statement checks a condition and executes the statement following the `while`. It repeats checking the condition and executing those statements until the condition is false. -There's one other new operator in this example. The `++` after the `counter` variable is the **increment** operator. It adds 1 to the value of counter, and stores that value in the counter variable. +There's one other new operator in this example. The `++` after the `counter` variable is the **increment** operator. It adds 1 to the value of `counter` and stores that value in the `counter` variable. > [!IMPORTANT] -> -> Make sure that the `while` loop condition does switch to false as you execute the code. Otherwise, you create an **infinite loop** where your program never ends. Let's -> not demonstrate that, because the engine that runs your code times out and you see no output from your program. +> Make sure that the `while` loop condition changes to false as you execute the code. Otherwise, you create an **infinite loop** where your program never ends. That is not demonstrated in this sample, because you have to force your program to quit using **CTRL-C** or other means. -The `while` loop tests the condition before executing the code following the `while`. The `do` ... `while` loop executes the code first, and then checks the condition. It looks like this: +The `while` loop tests the condition before executing the code following the `while`. The `do` ... `while` loop executes the code first, and then checks the condition. The *do while* loop is shown in the following code: :::code language="csharp" source="./snippets/BranchesAndLoops/Program.cs" id="DoLoop"::: -This `do` loop and the earlier `while` loop work the same. +This `do` loop and the earlier `while` loop produce the same output. Let's move on to one last loop statement. ## Work with the for loop -Another common loop statement that you see in C# code is the `for` loop. Try this code in the interactive window: +Another common loop statement that you see in C# code is the `for` loop. Try this code: -:::code language="csharp" interactive="try-dotnet-method" source="./snippets/BranchesAndLoops/Program.cs" id="ForLoop"::: +:::code language="csharp" source="./snippets/BranchesAndLoops/Program.cs" id="ForLoop"::: The preceding `for` loop does the same work as the `while` loop and the `do` loop you already used. The `for` statement has three parts that control how it works: - The first part is the **for initializer**: `int counter = 0;` declares that `counter` is the loop variable, and sets its initial value to `0`. -- The middle part is the **for condition**: `counter < 10` declares that this `for` loop continues to execute as long as the value of counter is less than 10. +- The middle part is the **for condition**: `counter < 10` declares that this `for` loop continues to execute as long as the value of `counter` is less than 10. - The final part is the **for iterator**: `counter++` specifies how to modify the loop variable after executing the block following the `for` statement. Here, it specifies that `counter` increments by 1 each time the block executes. Experiment with these conditions yourself. Try each of the following changes: @@ -115,7 +118,7 @@ A `while`, `do`, or `for` loop can be nested inside another loop to create a mat One `for` loop can generate the rows: -:::code language="csharp" interactive="try-dotnet-method" source="./snippets/BranchesAndLoops/Program.cs" id="Rows"::: +:::code language="csharp" source="./snippets/BranchesAndLoops/Program.cs" id="Rows"::: Another loop can generate the columns: @@ -125,11 +128,11 @@ You can nest one loop inside the other to form pairs: :::code language="csharp" source="./snippets/BranchesAndLoops/Program.cs" id="Nested"::: -You can see that the outer loop increments once for each full run of the inner loop. Reverse the row and column nesting, and see the changes for yourself. +You can see that the outer loop increments once for each full run of the inner loop. Reverse the row and column nesting, and see the changes for yourself. When you're done, place the code from this section in a method called `ExploreLoops()`. ## Combine branches and loops -Now that you saw the `if` statement and the looping constructs in the C# language, see if you can write C# code to find the sum of all integers 1 through 20 that are divisible by 3. Here are a few hints: +Now that you used the `if` statement and the looping constructs in the C# language, see if you can write C# code to find the sum of all integers 1 through 20 that are divisible by 3. Here are a few hints: - The `%` operator gives you the remainder of a division operation. - The `if` statement gives you the condition to see if a number should be part of the sum. @@ -142,11 +145,13 @@ Did you come up with something like this?
-:::code language="csharp" interactive="try-dotnet-method" source="./snippets/BranchesAndLoops/Program.cs" id="Challenge"::: +:::code language="csharp" source="./snippets/BranchesAndLoops/Program.cs" id="Challenge":::
-You completed the "branches and loops" interactive tutorial. You can select the **list collection** link to start the next interactive tutorial, or you can visit the [.NET site](https://dotnet.microsoft.com/learn/dotnet/hello-world-tutorial/intro) to download the .NET SDK, create a project on your machine, and keep coding. The "Next steps" section brings you back to these tutorials. +You've completed the "branches and loops" tutorial. + +You completed the "branches and loops" tutorial. You can select the **list collection** link to start the next tutorial. You can learn more about these concepts in these articles: diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/BranchesAndLoops/BranchesAndLoops.csproj b/docs/csharp/tour-of-csharp/tutorials/snippets/BranchesAndLoops/BranchesAndLoops.csproj index fd4bd08da2987..ed9781c223ab9 100644 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/BranchesAndLoops/BranchesAndLoops.csproj +++ b/docs/csharp/tour-of-csharp/tutorials/snippets/BranchesAndLoops/BranchesAndLoops.csproj @@ -2,7 +2,7 @@ Exe - net9.0 + net10.0 enable enable diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/BranchesAndLoops/Program.cs b/docs/csharp/tour-of-csharp/tutorials/snippets/BranchesAndLoops/Program.cs index dae1c19e90003..0f23a13985413 100644 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/BranchesAndLoops/Program.cs +++ b/docs/csharp/tour-of-csharp/tutorials/snippets/BranchesAndLoops/Program.cs @@ -9,6 +9,47 @@ PageFive(); Challenge(); +// +ExploreIf(); + +void ExploreIf() +{ + int a = 5; + int b = 3; + if (a + b > 10) + { + Console.WriteLine("The answer is greater than 10"); + } + else + { + Console.WriteLine("The answer is not greater than 10"); + } + + int c = 4; + if ((a + b + c > 10) && (a > b)) + { + Console.WriteLine("The answer is greater than 10"); + Console.WriteLine("And the first number is greater than the second"); + } + else + { + Console.WriteLine("The answer is not greater than 10"); + Console.WriteLine("Or the first number is not greater than the second"); + } + + if ((a + b + c > 10) || (a > b)) + { + Console.WriteLine("The answer is greater than 10"); + Console.WriteLine("Or the first number is greater than the second"); + } + else + { + Console.WriteLine("The answer is not greater than 10"); + Console.WriteLine("And the first number is not greater than the second"); + } +} +// + void PageOne() { // From ed6824eb954e087de69a3cd73e06c0794bfb283d Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Wed, 3 Dec 2025 16:38:47 -0500 Subject: [PATCH 05/13] First edit pass on list collection tutorial --- .../tutorials/list-collection.md | 26 ++-- .../ListCollection/ListCollection.csproj | 2 +- .../snippets/ListCollection/Program.cs | 133 ++++++++---------- 3 files changed, 75 insertions(+), 86 deletions(-) diff --git a/docs/csharp/tour-of-csharp/tutorials/list-collection.md b/docs/csharp/tour-of-csharp/tutorials/list-collection.md index 74a6388cccb25..663ca9bea8a03 100644 --- a/docs/csharp/tour-of-csharp/tutorials/list-collection.md +++ b/docs/csharp/tour-of-csharp/tutorials/list-collection.md @@ -1,5 +1,5 @@ --- -title: Data collections - Introductory interactive tutorial +title: Data collections - Introductory tutorial description: In this tutorial, you use your browser to learn about C# collections. You write C# code and see the results of compiling and running your code directly in the browser. ms.date: 03/07/2025 --- @@ -7,17 +7,15 @@ ms.date: 03/07/2025 This introductory tutorial provides an introduction to the C# language and the basics of the class. -This tutorial teaches you C# interactively, using your browser to write C# code and see the results of compiling and running your code. It contains a series of lessons that create, modify, and explore collections and arrays. You work primarily with the class. +This tutorial teaches you C#. You write C# code and see the results of compiling and running that code. It contains a series of lessons that create, modify, and explore collections and arrays. You work primarily with the class. -## A basic list example +<< TODO Create the app>> -> [!TIP] -> -> When a code snippet block includes the "Run" button, that button opens the interactive window, or replaces the existing code in the interactive window. When the snippet doesn't include a "Run" button, you can copy the code and add it to the current interactive window. +## A basic list example -Run the following code in the interactive window. Replace `` with your name and select **Run**: +Add the following code to your source file. Replace `` with your name. Then, type `dotnet run` to run the code: -:::code language="csharp" interactive="try-dotnet-method" source="./snippets/ListCollection/Program.cs" id="BasicList"::: +:::code language="csharp" source="./snippets/ListCollection/Program.cs" id="BasicList"::: You created a list of strings, added three names to that list, and printed the names in all CAPS. You're using concepts that you learned in earlier tutorials to loop through the list. @@ -43,7 +41,7 @@ You're not allowed to access past the end of the list. You can check how long th :::code language="csharp" source="./snippets/ListCollection/Program.cs" id="Property"::: -Select **Run** again to see the results. In C#, indices start at 0, so the largest valid index is one less than the number of items in the list. +Type `dotnet run` again to see the results. In C#, indices start at 0, so the largest valid index is one less than the number of items in the list. For more information about indices, see the [Explore indexes and ranges](../../tutorials/ranges-indexes.md) article. @@ -61,15 +59,15 @@ The items in your list can be sorted as well. The using a different type. Let's build a set of numbers. Delete the code you wrote so far, and replace it with the following code: +You've been using the `string` type in lists so far. Let's make a using a different type. Let's build a set of numbers. Add the following code at the end of your source file: -:::code language="csharp" interactive="try-dotnet-method" source="./snippets/ListCollection/Program.cs" id="CreateList"::: +:::code language="csharp" source="./snippets/ListCollection/Program.cs" id="CreateList"::: That creates a list of integers, and sets the first two integers to the value 1. The *Fibonacci Sequence*, a sequence of numbers, starts with two 1's. Each next Fibonacci number is found by taking the sum of the previous two numbers. Add this code: :::code language="csharp" source="./snippets/ListCollection/Program.cs" id="Fibonacci"::: -Press **Run** to see the results. +Type `dotnet run` to see the results. ## Challenge @@ -80,13 +78,13 @@ Did you come up with something like this?
-:::code language="csharp" interactive="try-dotnet-method" source="./snippets/ListCollection/Program.cs" id="Answer"::: +:::code language="csharp" source="./snippets/ListCollection/Program.cs" id="Answer"::: With each iteration of the loop, you're taking the last two integers in the list, summing them, and adding that value to the list. The loop repeats until you added 20 items to the list.
-You completed the list interactive tutorial, the final introduction to C# interactive tutorial. You can visit the [.NET site](https://dotnet.microsoft.com/learn/dotnet/hello-world-tutorial/intro) to download the .NET SDK, create a project on your machine, and keep coding. The "Next steps" section brings you back to these tutorials. Or, you can continue with the [Explore object oriented programming with classes and objects](../../fundamentals/tutorials/classes.md) tutorial. +You completed the list tutorial. You can continue with the [Pattern matching](./pattern-matching.md) tutorial. You can learn more about [.NET collections](../../../standard/collections/index.md) in the following articles: diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/ListCollection/ListCollection.csproj b/docs/csharp/tour-of-csharp/tutorials/snippets/ListCollection/ListCollection.csproj index fd4bd08da2987..ed9781c223ab9 100644 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/ListCollection/ListCollection.csproj +++ b/docs/csharp/tour-of-csharp/tutorials/snippets/ListCollection/ListCollection.csproj @@ -2,7 +2,7 @@ Exe - net9.0 + net10.0 enable enable diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/ListCollection/Program.cs b/docs/csharp/tour-of-csharp/tutorials/snippets/ListCollection/Program.cs index 3df770ea7cb45..c898bbf5fa803 100644 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/ListCollection/Program.cs +++ b/docs/csharp/tour-of-csharp/tutorials/snippets/ListCollection/Program.cs @@ -1,87 +1,78 @@ - -ListOfStrings(); -ListOfNumbers(); -ChallengeAnswer(); - -void ListOfStrings() +// +List names = ["", "Ana", "Felipe"]; +foreach (var name in names) { - // - List names = ["", "Ana", "Felipe"]; - foreach (var name in names) - { - Console.WriteLine($"Hello {name.ToUpper()}!"); - } - // + Console.WriteLine($"Hello {name.ToUpper()}!"); +} +// - // - Console.WriteLine(); - names.Add("Maria"); - names.Add("Bill"); - names.Remove("Ana"); - foreach (var name in names) - { - Console.WriteLine($"Hello {name.ToUpper()}!"); - } - // +// +Console.WriteLine(); +names.Add("Maria"); +names.Add("Bill"); +names.Remove("Ana"); +foreach (var name in names) +{ + Console.WriteLine($"Hello {name.ToUpper()}!"); +} +// - // - Console.WriteLine($"My name is {names[0]}."); - Console.WriteLine($"I've added {names[2]} and {names[3]} to the list."); - // +// +Console.WriteLine($"My name is {names[0]}."); +Console.WriteLine($"I've added {names[2]} and {names[3]} to the list."); +// - // - Console.WriteLine($"The list has {names.Count} people in it"); - // +// +Console.WriteLine($"The list has {names.Count} people in it"); +// - // - var index = names.IndexOf("Felipe"); - if (index == -1) - { - Console.WriteLine($"When an item is not found, IndexOf returns {index}"); - } - else - { - Console.WriteLine($"The name {names[index]} is at index {index}"); - } - - index = names.IndexOf("Not Found"); - if (index == -1) - { - Console.WriteLine($"When an item is not found, IndexOf returns {index}"); - } - else - { - Console.WriteLine($"The name {names[index]} is at index {index}"); - } - // +// +var index = names.IndexOf("Felipe"); +if (index == -1) +{ + Console.WriteLine($"When an item is not found, IndexOf returns {index}"); +} +else +{ + Console.WriteLine($"The name {names[index]} is at index {index}"); +} - // - names.Sort(); - foreach (var name in names) - { - Console.WriteLine($"Hello {name.ToUpper()}!"); - } - // +index = names.IndexOf("Not Found"); +if (index == -1) +{ + Console.WriteLine($"When an item is not found, IndexOf returns {index}"); +} +else +{ + Console.WriteLine($"The name {names[index]} is at index {index}"); } +// -void ListOfNumbers() +// +names.Sort(); +foreach (var name in names) { - // - List fibonacciNumbers = [1, 1]; - // + Console.WriteLine($"Hello {name.ToUpper()}!"); +} +// - // - var previous = fibonacciNumbers[fibonacciNumbers.Count - 1]; - var previous2 = fibonacciNumbers[fibonacciNumbers.Count - 2]; +// +List fibonacciNumbers = [1, 1]; +// - fibonacciNumbers.Add(previous + previous2); +// +var previous = fibonacciNumbers[fibonacciNumbers.Count - 1]; +var previous2 = fibonacciNumbers[fibonacciNumbers.Count - 2]; - foreach (var item in fibonacciNumbers) - { - Console.WriteLine(item); - } - // +fibonacciNumbers.Add(previous + previous2); + +foreach (var item in fibonacciNumbers) +{ + Console.WriteLine(item); } +// + +ChallengeAnswer(); void ChallengeAnswer() { From 9a63f44e34041f8d620a868be81aa6ca670aee2a Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Thu, 4 Dec 2025 10:42:34 -0500 Subject: [PATCH 06/13] First pass edit on patterns --- .../tutorials/pattern-matching.md | 61 ++++++---- .../PatternMatching/EnumSwitchExample.cs | 76 ------------ .../PatternMatching/FinalExampleProgram.cs | 79 ------------- .../PatternMatching/FirstEnumExample.cs | 74 ------------ .../PatternMatching/PatternMatching.csproj | 2 +- .../snippets/PatternMatching/Program.cs | 111 ++++++++++++++++-- 6 files changed, 144 insertions(+), 259 deletions(-) delete mode 100644 docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/EnumSwitchExample.cs delete mode 100644 docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/FinalExampleProgram.cs delete mode 100644 docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/FirstEnumExample.cs diff --git a/docs/csharp/tour-of-csharp/tutorials/pattern-matching.md b/docs/csharp/tour-of-csharp/tutorials/pattern-matching.md index 34253cdc2afa0..fd1e2d2b71b33 100644 --- a/docs/csharp/tour-of-csharp/tutorials/pattern-matching.md +++ b/docs/csharp/tour-of-csharp/tutorials/pattern-matching.md @@ -1,41 +1,58 @@ --- title: Pattern matching -description: In this tutorial about pattern matching, you use your browser to learn C# interactively. You're going to write C# code and see the results of compiling and running your code directly in the browser. -ms.date: 05/02/2025 +description: In this tutorial about pattern matching, you learn C#. You're going to write C# code and see the results of compiling and running your code. +ms.date: 12/04/2025 --- # Match data against patterns -This tutorial teaches you how to use pattern matching to inspect data in C#. You write small amounts of code, then you compile and run that code. The tutorial contains a series of lessons that explore different kinds of types in C#. These lessons teach you the fundamentals of the C# language. - -> [!TIP] -> When a code snippet block includes the "Run" button, that button opens the interactive window, or replaces the existing code in the interactive window. When the snippet doesn't include a "Run" button, you can copy the code and add it to the current interactive window. +This tutorial teaches you how to use pattern matching to inspect data in C#. You write small amounts of code, then you compile and run that code. The tutorial contains a series of lessons that explore different kinds of patterns supported by C#. These lessons teach you the fundamentals of the C# language. The preceding tutorials demonstrated built-in types and types you define as tuples or records. Instances of these types can be checked against a *pattern*. Whether an instance matches a pattern determines the actions your program takes. In the examples below, you'll notice `?` after type names. This symbol allows the value of this type to be null (for example, `bool?` can be `true`, `false` or `null`). For more information, see [Nullable value types](../../language-reference/builtin-types/nullable-value-types.md). Let's start to explore how you can use patterns. +<< TO DO: Make your app >> + ## Match a value -All the examples in this tutorial use text input that represents a series of bank transactions as comma separated values (CSV) input. In each of the samples you can match the record against a pattern using either an `is` or `switch` expression. This first example splits each line on the `,` character and then *matches* the first string field against the value "DEPOSIT" or "WITHDRAWAL" using an `is` expression. When it matches, the transaction amount is added or deducted from the current account balance. To see it work, press the "Run" button: +All the examples in this tutorial use text input that represents a series of bank transactions as comma separated values (CSV) input. In each of the samples you can match the record against a pattern using either an `is` or `switch` expression. This first example splits each line on the `,` character and then *matches* the first string field against the value "DEPOSIT" or "WITHDRAWAL" using an `is` expression. When it matches, the transaction amount is added or deducted from the current account balance. To see it work, add the following code to your source file. Then, type `dotnet run` in the console window. -:::code language="csharp" interactive="try-dotnet-method" source="./snippets/PatternMatching/Program.cs" id="FirstExample"::: +:::code language="csharp" source="./snippets/PatternMatching/Program.cs" id="FirstExample"::: Examine the output. You can see that each line is processed by comparing the value of the text in the first field. The preceding sample could be similarly constructed using the `==` operator to test that two `string` values are equal. Comparing a variable to a constant is a basic building block for pattern matching. Let's explore more of the building blocks that are part of pattern matching. ## Enum matches -Another common use for pattern matching is to match on the values of an `enum` type. This next sample processes the input records to create a *tuple* where the first value is an `enum` value that notes a deposit or a withdrawal. The second value is the value of the transaction. To see it work, press the "Run" button: +Another common use for pattern matching is to match on the values of an `enum` type. This next sample processes the input records to create a *tuple* where the first value is an `enum` value that notes a deposit or a withdrawal. The second value is the value of the transaction. Add the following code to the end of your source file. It defines the `TransactionType` enumeration: + +:::code language="csharp" source="./snippets/PatternMatching/Program.cs" id="TransactionTypeEnum"::: + +Next, add a function to parse a bank transaction into a tuple that holds the transaction type and the value of the transaction. Add the following code before your declaration of the `TransactionType` enum: + +:::code language="csharp" source="./snippets/PatternMatching/Program.cs" id="ParseTransaction"::: -> [!WARNING] -> Don't copy and paste. The interactive window must be reset to run the following samples. If you make a mistake, the window hangs, and you need to refresh the page to continue. +Next, add a new loop to process the transaction data using the `TransactionType` enumeration you declared: -:::code language="csharp" interactive="try-dotnet" source="./snippets/PatternMatching/FirstEnumExample.cs" id="IsEnumValue"::: +:::code language="csharp" source="./snippets/PatternMatching/Program.cs" id="EnumPatternMatch"::: The preceding example also uses an `if` statement to check the value of an `enum` expression. Another form of pattern matching uses a `switch` expression. Let's explore that syntax and how you can use it. ## Exhaustive matches with `switch` -A series of `if` statements can test a series of conditions. But, the compiler can't tell if a series of `if` statements are *exhaustive* or if later `if` conditions are *subsumed* by earlier conditions. The `switch` expression ensures both of those characteristics are met, which results in fewer bugs in your apps. Let's try it and experiment. Copy the following code. Replace the two `if` statements in the interactive window with the `switch` expression you copied. After you've modified the code, press the "Run" button at the top of the interactive window to run the new sample. +A series of `if` statements can test a series of conditions. But, the compiler can't tell if a series of `if` statements are *exhaustive* or if later `if` conditions are *subsumed* by earlier conditions. *Exhaustive* means that all possible inputs are handled by one of the `if` or `else` clauses in the series of tests. If a series of `if` statements are exhaustive, every possible input satisfies at least one `if` or `else` clause. *Subsumption* means that a later `if` or `else` clause can't be reached because earlier `if` or `else` clauses match all possible inputs. For example, in the following example code, one clause never matches: + +```csharp +int n = GetNumber(); + +if (n < 20) + Console.WriteLine("n is less than 20"); +else if (n < 10) + Console.WriteLine("n is less than 10"); // unreachable +else + Console.WriteLine("n is greater than 20"); +``` + +The `else if` clause never matches because every number less than 10 is also less than 20. The `switch` expression ensures both of those characteristics are met, which results in fewer bugs in your apps. Let's try it and experiment. Copy the following code. Replace the two `if` statements in your `foreach` loop with the `switch` expression you copied. After you've modified the code, type `dotnet run` to run the new sample. -:::code language="csharp" interactive="try-dotnet" source="./snippets/PatternMatching/EnumSwitchExample.cs" id="SwitchEnumValue"::: +:::code language="csharp" source="./snippets/PatternMatching/EnumSwitchExample.cs" id="SwitchEnumValue"::: When you run the code, you see that it works the same. To demonstrate *subsumption*, reorder the switch arms as shown in the following snippet: @@ -48,25 +65,25 @@ currentBalance += transaction switch }; ``` -After you reorder the switch arms, press the "Run" button. The compiler issues an error because the arm with `_` matches every value. As a result, that final arm with `TransactionType.Withdrawal` never runs. The compiler tells you that something's wrong in your code. +After you reorder the switch arms, type `dotnet run`. The compiler issues an error because the arm with `_` matches every value. As a result, that final arm with `TransactionType.Withdrawal` never runs. The compiler tells you that something's wrong in your code. The compiler issues a warning if the expression tested in a `switch` expression could contain values that don't match any switch arm. If some values could fail to match any condition, the `switch` expression isn't *exhaustive*. The compiler also issues a warning if some values of the input don't match any of the switch arms. For example, if you remove the line with `_ => 0.0,`, any invalid values don't match. At run time, that would fail. Once you install the .NET SDK and build programs in your environment, you can test this behavior. The online experience doesn't display warnings in the output window. ## Type patterns -To finish this tutorial, let's explore one more building block to pattern matching: the *type pattern*. A *type pattern* tests an expression at run time to see if it's the specified type. You can use a type test with either an `is` expression or a `switch` expression. Let's modify the current sample in two ways. First, instead of a tuple, let's build `Deposit` and `Withdrawal` record types that represent the transactions. Add the following declarations at the bottom of the interactive window: +To finish this tutorial, let's explore one more building block to pattern matching: the *type pattern*. A *type pattern* tests an expression at run time to see if it's the specified type. You can use a type test with either an `is` expression or a `switch` expression. Let's modify the current sample in two ways. First, instead of a tuple, let's build `Deposit` and `Withdrawal` record types that represent the transactions. Add the following declarations just at the end of the your code file: -:::code language="csharp" interactive="try-dotnet" source="./snippets/PatternMatching/FinalExampleProgram.cs" id="RecordDeclarations"::: +:::code language="csharp" source="./snippets/PatternMatching/FinalExampleProgram.cs" id="RecordDeclarations"::: -Next, add this method after the `Main` method to parse the text and return a series of records: +Next, add this method just before the declaration of the `TransactionType` enumeration. It parses the text and return a series of records: -:::code language="csharp" interactive="try-dotnet" source="./snippets/PatternMatching/FinalExampleProgram.cs" id="ParseToRecord"::: +:::code language="csharp" source="./snippets/PatternMatching/FinalExampleProgram.cs" id="ParseToRecord"::: -Finally, replace the `foreach` loop in the `Main` method with the following code: +Finally, add the following code after the last `foreach` loop: -:::code language="csharp" interactive="try-dotnet" source="./snippets/PatternMatching/FinalExampleProgram.cs" id="TypePattern"::: +:::code language="csharp" source="./snippets/PatternMatching/FinalExampleProgram.cs" id="TypePattern"::: -Then, press the "Run" button to see the results. This final version tests the input against a *type*. +Then, type `dotnet run` to see the results. This final version tests the input against a *type*. Pattern matching provides a vocabulary to compare an expression against characteristics. Patterns can include the expression's type, values of types, property values, and combinations of them. Comparing expressions against a pattern can be more clear than multiple `if` comparisons. You explored some of the patterns you can use to match expressions. There are many more ways to use pattern matching in your applications. First, visit the [.NET site](https://dotnet.microsoft.com/learn/dotnet/hello-world-tutorial/intro) to download the .NET SDK, create a project on your machine, and keep coding. As you explore, you can learn more about pattern matching in C# in the following articles: diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/EnumSwitchExample.cs b/docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/EnumSwitchExample.cs deleted file mode 100644 index 2e0d59867a1ab..0000000000000 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/EnumSwitchExample.cs +++ /dev/null @@ -1,76 +0,0 @@ -namespace EnumSwitchExample; - -// -public static class ExampleProgram -{ - const string bankRecords = """ - DEPOSIT, 10000, Initial balance - DEPOSIT, 500, regular deposit - WITHDRAWAL, 1000, rent - DEPOSIT, 2000, freelance payment - WITHDRAWAL, 300, groceries - DEPOSIT, 700, gift from friend - WITHDRAWAL, 150, utility bill - DEPOSIT, 1200, tax refund - WITHDRAWAL, 500, car maintenance - DEPOSIT, 400, cashback reward - WITHDRAWAL, 250, dining out - DEPOSIT, 3000, bonus payment - WITHDRAWAL, 800, loan repayment - DEPOSIT, 600, stock dividends - WITHDRAWAL, 100, subscription fee - DEPOSIT, 1500, side hustle income - WITHDRAWAL, 200, fuel expenses - DEPOSIT, 900, refund from store - WITHDRAWAL, 350, shopping - DEPOSIT, 2500, project milestone payment - WITHDRAWAL, 400, entertainment - """; - - public static void Main() - { - double currentBalance = 0.0; - - foreach (var transaction in TransactionRecords(bankRecords)) - { - // - currentBalance += transaction switch - { - (TransactionType.Deposit, var amount) => amount, - (TransactionType.Withdrawal, var amount) => -amount, - _ => 0.0, - }; - // - Console.WriteLine($"{transaction.type} => Parsed Amount: {transaction.amount}, New Balance: {currentBalance}"); - } - } - - static IEnumerable<(TransactionType type, double amount)> TransactionRecords(string inputText) - { - var reader = new StringReader(inputText); - string? line; - while ((line = reader.ReadLine()) is not null) - { - string[] parts = line.Split(','); - - string? transactionType = parts[0]?.Trim(); - if (double.TryParse(parts[1].Trim(), out double amount)) - { - // Update the balance based on transaction type - if (transactionType?.ToUpper() is "DEPOSIT") - yield return (TransactionType.Deposit, amount); - else if (transactionType?.ToUpper() is "WITHDRAWAL") - yield return (TransactionType.Withdrawal, amount); - } - yield return (TransactionType.Invalid, 0.0); - } - } -} - -public enum TransactionType -{ - Deposit, - Withdrawal, - Invalid -} -// diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/FinalExampleProgram.cs b/docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/FinalExampleProgram.cs deleted file mode 100644 index da4b22834ae74..0000000000000 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/FinalExampleProgram.cs +++ /dev/null @@ -1,79 +0,0 @@ -public static class ExampleProgram -{ - const string bankRecords = """ - DEPOSIT, 10000, Initial balance - DEPOSIT, 500, regular deposit - WITHDRAWAL, 1000, rent - DEPOSIT, 2000, freelance payment - WITHDRAWAL, 300, groceries - DEPOSIT, 700, gift from friend - WITHDRAWAL, 150, utility bill - DEPOSIT, 1200, tax refund - WITHDRAWAL, 500, car maintenance - DEPOSIT, 400, cashback reward - WITHDRAWAL, 250, dining out - DEPOSIT, 3000, bonus payment - WITHDRAWAL, 800, loan repayment - DEPOSIT, 600, stock dividends - WITHDRAWAL, 100, subscription fee - DEPOSIT, 1500, side hustle income - WITHDRAWAL, 200, fuel expenses - DEPOSIT, 900, refund from store - WITHDRAWAL, 350, shopping - DEPOSIT, 2500, project milestone payment - WITHDRAWAL, 400, entertainment - """; - - public static void Main() - { - double currentBalance = 0.0; - - // - foreach (var transaction in TransactionRecordType(bankRecords)) - { - currentBalance += transaction switch - { - Deposit d => d.Amount, - Withdrawal w => -w.Amount, - _ => 0.0, - }; - Console.WriteLine($" {transaction} => New Balance: {currentBalance}"); - } - // - } - - // - public static IEnumerable TransactionRecordType(string inputText) - { - var reader = new StringReader(inputText); - string? line; - while ((line = reader.ReadLine()) is not null) - { - string[] parts = line.Split(','); - - string? transactionType = parts[0]?.Trim(); - if (double.TryParse(parts[1].Trim(), out double amount)) - { - // Update the balance based on transaction type - if (transactionType?.ToUpper() is "DEPOSIT") - yield return new Deposit(amount, parts[2]); - else if (transactionType?.ToUpper() is "WITHDRAWAL") - yield return new Withdrawal(amount, parts[2]); - } - yield return default; - } - } - // -} - -public enum TransactionType -{ - Deposit, - Withdrawal, - Invalid -} - -// -public record Deposit(double Amount, string description); -public record Withdrawal(double Amount, string description); -// diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/FirstEnumExample.cs b/docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/FirstEnumExample.cs deleted file mode 100644 index a64a45d2ac3ab..0000000000000 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/FirstEnumExample.cs +++ /dev/null @@ -1,74 +0,0 @@ -namespace FirstEnumExample; - -// -public static class ExampleProgram -{ - const string bankRecords = """ - DEPOSIT, 10000, Initial balance - DEPOSIT, 500, regular deposit - WITHDRAWAL, 1000, rent - DEPOSIT, 2000, freelance payment - WITHDRAWAL, 300, groceries - DEPOSIT, 700, gift from friend - WITHDRAWAL, 150, utility bill - DEPOSIT, 1200, tax refund - WITHDRAWAL, 500, car maintenance - DEPOSIT, 400, cashback reward - WITHDRAWAL, 250, dining out - DEPOSIT, 3000, bonus payment - WITHDRAWAL, 800, loan repayment - DEPOSIT, 600, stock dividends - WITHDRAWAL, 100, subscription fee - DEPOSIT, 1500, side hustle income - WITHDRAWAL, 200, fuel expenses - DEPOSIT, 900, refund from store - WITHDRAWAL, 350, shopping - DEPOSIT, 2500, project milestone payment - WITHDRAWAL, 400, entertainment - """; - - public static void Main() - { - double currentBalance = 0.0; - - foreach (var transaction in TransactionRecords(bankRecords)) - { - if (transaction.type == TransactionType.Deposit) - currentBalance += transaction.amount; - else if (transaction.type == TransactionType.Withdrawal) - currentBalance -= transaction.amount; - Console.WriteLine($"{transaction.type} => Parsed Amount: {transaction.amount}, New Balance: {currentBalance}"); - } - } - - static IEnumerable<(TransactionType type, double amount)> TransactionRecords(string inputText) - { - var reader = new StringReader(inputText); - string? line; - while ((line = reader.ReadLine()) is not null) - { - string[] parts = line.Split(','); - - string? transactionType = parts[0]?.Trim(); - if (double.TryParse(parts[1].Trim(), out double amount)) - { - // Update the balance based on transaction type - if (transactionType?.ToUpper() is "DEPOSIT") - yield return (TransactionType.Deposit, amount); - else if (transactionType?.ToUpper() is "WITHDRAWAL") - yield return (TransactionType.Withdrawal, amount); - } - else { - yield return (TransactionType.Invalid, 0.0); - } - } - } -} - -public enum TransactionType -{ - Deposit, - Withdrawal, - Invalid -} -// diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/PatternMatching.csproj b/docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/PatternMatching.csproj index fd4bd08da2987..ed9781c223ab9 100644 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/PatternMatching.csproj +++ b/docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/PatternMatching.csproj @@ -2,7 +2,7 @@ Exe - net9.0 + net10.0 enable enable diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/Program.cs b/docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/Program.cs index abb2305b43bce..90036aed48ffe 100644 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/Program.cs +++ b/docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/Program.cs @@ -47,11 +47,108 @@ } // -Console.WriteLine(); -FirstEnumExample.ExampleProgram.Main(); -Console.WriteLine(); -EnumSwitchExample.ExampleProgram.Main(); -Console.WriteLine(); -ExampleProgram.Main(); -Console.WriteLine(); +// +currentBalance = 0.0; + +foreach (var transaction in TransactionRecords(bankRecords)) +{ + if (transaction.type == TransactionType.Deposit) + currentBalance += transaction.amount; + else if (transaction.type == TransactionType.Withdrawal) + currentBalance -= transaction.amount; + Console.WriteLine($"{transaction.type} => Parsed Amount: {transaction.amount}, New Balance: {currentBalance}"); +} +// + +currentBalance = 0.0; + +foreach (var transaction in TransactionRecords(bankRecords)) +{ + // + currentBalance += transaction switch + { + (TransactionType.Deposit, var amount) => amount, + (TransactionType.Withdrawal, var amount) => -amount, + _ => 0.0, + }; + // + Console.WriteLine($"{transaction.type} => Parsed Amount: {transaction.amount}, New Balance: {currentBalance}"); +} + +// +currentBalance = 0.0; + +foreach (var transaction in TransactionRecordType(bankRecords)) +{ + currentBalance += transaction switch + { + Deposit d => d.Amount, + Withdrawal w => -w.Amount, + _ => 0.0, + }; + Console.WriteLine($" {transaction} => New Balance: {currentBalance}"); +} +// + +// +static IEnumerable<(TransactionType type, double amount)> TransactionRecords(string inputText) +{ + var reader = new StringReader(inputText); + string? line; + while ((line = reader.ReadLine()) is not null) + { + string[] parts = line.Split(','); + + string? transactionType = parts[0]?.Trim(); + if (double.TryParse(parts[1].Trim(), out double amount)) + { + // Update the balance based on transaction type + if (transactionType?.ToUpper() is "DEPOSIT") + yield return (TransactionType.Deposit, amount); + else if (transactionType?.ToUpper() is "WITHDRAWAL") + yield return (TransactionType.Withdrawal, amount); + } + else { + yield return (TransactionType.Invalid, 0.0); + } + } +} +// + +// +static IEnumerable TransactionRecordType(string inputText) +{ + var reader = new StringReader(inputText); + string? line; + while ((line = reader.ReadLine()) is not null) + { + string[] parts = line.Split(','); + + string? transactionType = parts[0]?.Trim(); + if (double.TryParse(parts[1].Trim(), out double amount)) + { + // Update the balance based on transaction type + if (transactionType?.ToUpper() is "DEPOSIT") + yield return new Deposit(amount, parts[2]); + else if (transactionType?.ToUpper() is "WITHDRAWAL") + yield return new Withdrawal(amount, parts[2]); + } + yield return default; + } +} +// + +// +public enum TransactionType +{ + Deposit, + Withdrawal, + Invalid +} +// + +// +public record Deposit(double Amount, string description); +public record Withdrawal(double Amount, string description); +// From 66127c8131718ae2525037fb54fbe9bf38b8c59c Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Thu, 4 Dec 2025 10:54:32 -0500 Subject: [PATCH 07/13] fix warnings --- .../tour-of-csharp/tutorials/numbers-in-csharp.md | 2 -- .../tour-of-csharp/tutorials/pattern-matching.md | 8 ++++---- .../tour-of-csharp/tutorials/tuples-and-types.md | 10 +++++----- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/docs/csharp/tour-of-csharp/tutorials/numbers-in-csharp.md b/docs/csharp/tour-of-csharp/tutorials/numbers-in-csharp.md index fa17a36ec25df..e2ffb854b9f05 100644 --- a/docs/csharp/tour-of-csharp/tutorials/numbers-in-csharp.md +++ b/docs/csharp/tour-of-csharp/tutorials/numbers-in-csharp.md @@ -9,8 +9,6 @@ This tutorial teaches you about the numeric types in C#. You write small amounts ## Explore integer math -## Explore integer math - Create a directory named *numbers-quickstart*. Make it the current directory and run the following command: ```dotnetcli diff --git a/docs/csharp/tour-of-csharp/tutorials/pattern-matching.md b/docs/csharp/tour-of-csharp/tutorials/pattern-matching.md index fd1e2d2b71b33..6a67dc9a584dc 100644 --- a/docs/csharp/tour-of-csharp/tutorials/pattern-matching.md +++ b/docs/csharp/tour-of-csharp/tutorials/pattern-matching.md @@ -52,7 +52,7 @@ else The `else if` clause never matches because every number less than 10 is also less than 20. The `switch` expression ensures both of those characteristics are met, which results in fewer bugs in your apps. Let's try it and experiment. Copy the following code. Replace the two `if` statements in your `foreach` loop with the `switch` expression you copied. After you've modified the code, type `dotnet run` to run the new sample. -:::code language="csharp" source="./snippets/PatternMatching/EnumSwitchExample.cs" id="SwitchEnumValue"::: +:::code language="csharp" source="./snippets/PatternMatching/Program.cs" id="SwitchEnumValue"::: When you run the code, you see that it works the same. To demonstrate *subsumption*, reorder the switch arms as shown in the following snippet: @@ -73,15 +73,15 @@ The compiler issues a warning if the expression tested in a `switch` expression To finish this tutorial, let's explore one more building block to pattern matching: the *type pattern*. A *type pattern* tests an expression at run time to see if it's the specified type. You can use a type test with either an `is` expression or a `switch` expression. Let's modify the current sample in two ways. First, instead of a tuple, let's build `Deposit` and `Withdrawal` record types that represent the transactions. Add the following declarations just at the end of the your code file: -:::code language="csharp" source="./snippets/PatternMatching/FinalExampleProgram.cs" id="RecordDeclarations"::: +:::code language="csharp" source="./snippets/PatternMatching/Program.cs" id="RecordDeclarations"::: Next, add this method just before the declaration of the `TransactionType` enumeration. It parses the text and return a series of records: -:::code language="csharp" source="./snippets/PatternMatching/FinalExampleProgram.cs" id="ParseToRecord"::: +:::code language="csharp" source="./snippets/PatternMatching/Program.cs" id="ParseToRecord"::: Finally, add the following code after the last `foreach` loop: -:::code language="csharp" source="./snippets/PatternMatching/FinalExampleProgram.cs" id="TypePattern"::: +:::code language="csharp" source="./snippets/PatternMatching/Program.cs" id="TypePattern"::: Then, type `dotnet run` to see the results. This final version tests the input against a *type*. diff --git a/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md b/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md index 541522bc86f3d..05c0e2a4a783c 100644 --- a/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md +++ b/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md @@ -48,27 +48,27 @@ Tuples are great for those times when you want multiple values in the same struc The following code declares and uses a `record` type to represent a `Point`: -:::code language="csharp" source="./snippets/TuplesAndTypes/PointEvolution.cs" id="PointRecord"::: +:::code language="csharp" source="./snippets/TuplesAndTypes/Program.cs" id="PointRecord"::: The preceding code must be at the bottom of your source file. Type declarations like `record` declarations must follow executable statements in a file-based app. Add the following code preceding the `record` declaration: -:::code language="csharp" source="./snippets/TuplesAndTypes/PointEvolution.cs" id="UsePointRecord"::: +:::code language="csharp" source="./snippets/TuplesAndTypes/Program.cs" id="UsePointRecord"::: The `record` declaration is a single line of code for the `Point` type that stores the values `X` and `Y` in readonly properties. You use the name `Point` wherever you use that type. Properly named types, like `Point`, provide information about how the type is used. The additional code shows how to use a `with` expression to create a new point that's a modified copy of the existing point. The line `pt4 = pt3 with { Y = 10 }` says "`pt4` has the same values as `pt3` except that `Y` is assigned to 10." You can add any number of properties to change in a single `with` expression. The preceding `record` declaration is a single line of code that ends in `;`. You can add behavior to a `record` type by declaring *members*. A record member can be a function, or more data elements. The members of a type are in the type declaration, between `{` and `}` characters. Delete the `;` and add the following lines of code after the `record` declaration: -:::code language="csharp" source="./snippets/TuplesAndTypes/PointStruct.cs" id="AddSlopeMethod"::: +:::code language="csharp" source="./snippets/TuplesAndTypes/Program.cs" id="AddSlopeMethod"::: Then, add the following code before the `record` declaration, after the line containing the `with` expression: -:::code language="csharp" source="./snippets/TuplesAndTypes/PointStruct.cs" id="UseSlope"::: +:::code language="csharp" source="./snippets/TuplesAndTypes/Program.cs" id="UseSlope"::: You added formality to the *tuple* representing an `X` and `Y` value. You made it a `record` that defined a named type, and included a member to calculate the slope. A `record` type is a shorthand for a `record class`: A `class` type that includes extra behavior. You can modify the `Point` type to make it a `record struct` as well: -:::code language="csharp" source="./snippets/TuplesAndTypes/PointStruct.cs" id="RecordStructPoint"::: +:::code language="csharp" source="./snippets/TuplesAndTypes/Program.cs" id="RecordStructPoint"::: A `record struct` is a `struct` type that includes the extra behavior added to all `record` types. From 19a16602f01d83a18ccdc9fbb9b7a6d4b7ad321b Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Thu, 4 Dec 2025 10:58:44 -0500 Subject: [PATCH 08/13] One more warning pass --- .../tutorials/snippets/PatternMatching/Program.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/Program.cs b/docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/Program.cs index 90036aed48ffe..516a8bb2e8359 100644 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/Program.cs +++ b/docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/Program.cs @@ -75,7 +75,7 @@ Console.WriteLine($"{transaction.type} => Parsed Amount: {transaction.amount}, New Balance: {currentBalance}"); } -// +// currentBalance = 0.0; foreach (var transaction in TransactionRecordType(bankRecords)) @@ -88,7 +88,7 @@ }; Console.WriteLine($" {transaction} => New Balance: {currentBalance}"); } -// +// // static IEnumerable<(TransactionType type, double amount)> TransactionRecords(string inputText) From 947157cffee31547d7f8a14f87c8a08add5d31cd Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Thu, 4 Dec 2025 11:14:54 -0500 Subject: [PATCH 09/13] Convert to file-based-apps Convert all code from this sample to file-based apps. --- .../tutorials/branches-and-loops.md | 28 +++++++-------- .../tour-of-csharp/tutorials/hello-world.md | 24 ++++++------- .../tutorials/list-collection.md | 18 +++++----- .../tutorials/numbers-in-csharp.md | 34 +++++++++---------- .../tutorials/pattern-matching.md | 16 ++++----- .../BranchesAndLoops/BranchesAndLoops.csproj | 10 ------ .../{Program.cs => branches-loops.cs} | 0 .../snippets/HelloWorld/HelloWorld.csproj | 10 ------ .../HelloWorld/{Program.cs => hello-world.cs} | 0 .../ListCollection/ListCollection.csproj | 10 ------ .../ListCollection/{Program.cs => list.cs} | 0 .../{Program.cs => Numbers.cs} | 0 .../NumbersInCsharp/NumbersInCsharp.csproj | 10 ------ .../PatternMatching/PatternMatching.csproj | 10 ------ .../{Program.cs => patterns.cs} | 0 .../TuplesAndTypes/TuplesAndTypes.csproj | 10 ------ .../{Program.cs => tuples-types.cs} | 0 .../tutorials/tuples-and-types.md | 20 +++++------ 18 files changed, 70 insertions(+), 130 deletions(-) delete mode 100644 docs/csharp/tour-of-csharp/tutorials/snippets/BranchesAndLoops/BranchesAndLoops.csproj rename docs/csharp/tour-of-csharp/tutorials/snippets/BranchesAndLoops/{Program.cs => branches-loops.cs} (100%) delete mode 100644 docs/csharp/tour-of-csharp/tutorials/snippets/HelloWorld/HelloWorld.csproj rename docs/csharp/tour-of-csharp/tutorials/snippets/HelloWorld/{Program.cs => hello-world.cs} (100%) delete mode 100644 docs/csharp/tour-of-csharp/tutorials/snippets/ListCollection/ListCollection.csproj rename docs/csharp/tour-of-csharp/tutorials/snippets/ListCollection/{Program.cs => list.cs} (100%) rename docs/csharp/tour-of-csharp/tutorials/snippets/NumbersInCsharp/{Program.cs => Numbers.cs} (100%) delete mode 100644 docs/csharp/tour-of-csharp/tutorials/snippets/NumbersInCsharp/NumbersInCsharp.csproj delete mode 100644 docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/PatternMatching.csproj rename docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/{Program.cs => patterns.cs} (100%) delete mode 100644 docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/TuplesAndTypes.csproj rename docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/{Program.cs => tuples-types.cs} (100%) diff --git a/docs/csharp/tour-of-csharp/tutorials/branches-and-loops.md b/docs/csharp/tour-of-csharp/tutorials/branches-and-loops.md index f70e19595b619..85163228a3ab0 100644 --- a/docs/csharp/tour-of-csharp/tutorials/branches-and-loops.md +++ b/docs/csharp/tour-of-csharp/tutorials/branches-and-loops.md @@ -9,9 +9,9 @@ This tutorial teaches you how to write C# code that examines variables and chang TODO: Build an app, create a file. -Open *Program.cs* in your favorite editor, and replace the contents with the following code: +Open *branches-loops.cs* in your favorite editor, and replace the contents with the following code: -:::code language="csharp" source="./snippets/BranchesAndLoops/Program.cs" id="FirstIf"::: +:::code language="csharp" source="./snippets/BranchesAndLoops/branches-loops.cs" id="FirstIf"::: Try this code by typing `dotnet run` in your console window. You should see the message "The answer is greater than 10." printed to your console. Modify the declaration of `b` so that the sum is less than 10: @@ -30,7 +30,7 @@ This first sample shows the power of `if` and Boolean types. A *Boolean* is a va To execute different code in both the true and false branches, you create an `else` branch that executes when the condition is false. Try an `else` branch. Add the last two lines in the following code snippet (you should already have the first four): -:::code language="csharp" source="./snippets/BranchesAndLoops/Program.cs" id="IfAndElse"::: +:::code language="csharp" source="./snippets/BranchesAndLoops/branches-loops.cs" id="IfAndElse"::: The statement following the `else` keyword executes only when the condition being tested is `false`. Combining `if` and `else` with Boolean conditions provides all the power you need to handle both a `true` and a `false` condition. @@ -39,14 +39,14 @@ The statement following the `else` keyword executes only when the condition bein Because indentation isn't significant, you need to use `{` and `}` to indicate when you want more than one statement to be part of the block that executes conditionally. C# programmers typically use those braces on all `if` and `else` clauses. The following example is the same as what you created. Modify your code above to match the following code: -:::code language="csharp" source="./snippets/BranchesAndLoops/Program.cs" id="IncludeBraces"::: +:::code language="csharp" source="./snippets/BranchesAndLoops/branches-loops.cs" id="IncludeBraces"::: > [!TIP] > Through the rest of this tutorial, the code samples all include the braces, following accepted practices. You can test more complicated conditions. Add the following code after the code you've written so far: -:::code language="csharp" source="./snippets/BranchesAndLoops/Program.cs" id="ComplexConditions"::: +:::code language="csharp" source="./snippets/BranchesAndLoops/branches-loops.cs" id="ComplexConditions"::: The `==` symbol tests for *equality*. Using `==` distinguishes the test for equality from assignment, which you saw in `a = 5`. @@ -54,13 +54,13 @@ The `&&` represents "and". It means both conditions must be true to execute the You can also use `||` to represent "or". Add the following code after what you've written so far: -:::code language="csharp" source="./snippets/BranchesAndLoops/Program.cs" id="UseOr"::: +:::code language="csharp" source="./snippets/BranchesAndLoops/branches-loops.cs" id="UseOr"::: Modify the values of `a`, `b`, and `c` and switch between `&&` and `||` to explore. You gain more understanding of how the `&&` and `||` operators work. You finished the first step. Before you start the next section, let's move the current code into a separate method. That makes it easier to start working with a new example. Put the existing code in a method called `ExploreIf()`. Call it from the top of your program. When you finished those changes, your code should look like the following: -:::code language="csharp" source="./snippets/BranchesAndLoops/Program.cs" id="Refactor"::: +:::code language="csharp" source="./snippets/BranchesAndLoops/branches-loops.cs" id="Refactor"::: Comment out the call to `ExploreIf()`. It will make the output less cluttered as you work in this section: @@ -74,7 +74,7 @@ The `//` starts a **comment** in C#. Comments are any text you want to keep in y Another important concept to create larger programs is **loops**. You use loops to repeat statements that you want executed more than once. Add this code after the call to `ExploreIf`: -:::code language="csharp" source="./snippets/BranchesAndLoops/Program.cs" id="WhileLoop"::: +:::code language="csharp" source="./snippets/BranchesAndLoops/branches-loops.cs" id="WhileLoop"::: The `while` statement checks a condition and executes the statement following the `while`. It repeats checking the condition and executing those statements until the condition is false. @@ -85,7 +85,7 @@ There's one other new operator in this example. The `++` after the `counter` var The `while` loop tests the condition before executing the code following the `while`. The `do` ... `while` loop executes the code first, and then checks the condition. The *do while* loop is shown in the following code: -:::code language="csharp" source="./snippets/BranchesAndLoops/Program.cs" id="DoLoop"::: +:::code language="csharp" source="./snippets/BranchesAndLoops/branches-loops.cs" id="DoLoop"::: This `do` loop and the earlier `while` loop produce the same output. @@ -95,7 +95,7 @@ Let's move on to one last loop statement. Another common loop statement that you see in C# code is the `for` loop. Try this code: -:::code language="csharp" source="./snippets/BranchesAndLoops/Program.cs" id="ForLoop"::: +:::code language="csharp" source="./snippets/BranchesAndLoops/branches-loops.cs" id="ForLoop"::: The preceding `for` loop does the same work as the `while` loop and the `do` loop you already used. The `for` statement has three parts that control how it works: @@ -118,15 +118,15 @@ A `while`, `do`, or `for` loop can be nested inside another loop to create a mat One `for` loop can generate the rows: -:::code language="csharp" source="./snippets/BranchesAndLoops/Program.cs" id="Rows"::: +:::code language="csharp" source="./snippets/BranchesAndLoops/branches-loops.cs" id="Rows"::: Another loop can generate the columns: -:::code language="csharp" source="./snippets/BranchesAndLoops/Program.cs" id="Columns"::: +:::code language="csharp" source="./snippets/BranchesAndLoops/branches-loops.cs" id="Columns"::: You can nest one loop inside the other to form pairs: -:::code language="csharp" source="./snippets/BranchesAndLoops/Program.cs" id="Nested"::: +:::code language="csharp" source="./snippets/BranchesAndLoops/branches-loops.cs" id="Nested"::: You can see that the outer loop increments once for each full run of the inner loop. Reverse the row and column nesting, and see the changes for yourself. When you're done, place the code from this section in a method called `ExploreLoops()`. @@ -145,7 +145,7 @@ Did you come up with something like this?
-:::code language="csharp" source="./snippets/BranchesAndLoops/Program.cs" id="Challenge"::: +:::code language="csharp" source="./snippets/BranchesAndLoops/branches-loops.cs" id="Challenge":::
diff --git a/docs/csharp/tour-of-csharp/tutorials/hello-world.md b/docs/csharp/tour-of-csharp/tutorials/hello-world.md index 34e6530b76024..8f4bd18e5f7df 100644 --- a/docs/csharp/tour-of-csharp/tutorials/hello-world.md +++ b/docs/csharp/tour-of-csharp/tutorials/hello-world.md @@ -13,7 +13,7 @@ TODO: `dotnet new` or create a file. Type the following code in your new `cs` file: -:::code language="csharp" source="./snippets/HelloWorld/Program.cs" id="HelloWorld"::: +:::code language="csharp" source="./snippets/HelloWorld/hello-world.cs" id="HelloWorld"::: TODO: To run the program, type `dotnet run` (or) `dotnet file.cs` at the command prompt. Congratulations! You ran your first C# program. It's a simple program that prints the message "Hello World!" It used the method to print that message. `Console` is a type that represents the console window. `WriteLine` is a method of the `Console` type that prints a line of text to that text console. @@ -29,7 +29,7 @@ Your first program printed the `string` "Hello World!" on the screen. Your first program is limited to printing one message. You can write more useful programs by using *variables*. A *variable* is a symbol you can use to run the same code with different values. Let's try it! Start with the following code: -:::code language="csharp" source="./snippets/HelloWorld/Program.cs" id="Variables"::: +:::code language="csharp" source="./snippets/HelloWorld/hello-world.cs" id="Variables"::: The first line declares a variable, `aFriend`, and assigns it a value, "Bill". The second line prints the name. @@ -38,13 +38,13 @@ You can assign different values to any variable you declare. You can change the > [!IMPORTANT] > Don't delete the declaration of `aFriend`. Add the following code at the end of the preceding code: -:::code language="csharp" source="./snippets/HelloWorld/Program.cs" id="Assignment"::: +:::code language="csharp" source="./snippets/HelloWorld/hello-world.cs" id="Assignment"::: Notice that the same line of code prints two different messages, based on the value stored in the `aFriend` variable. You might notice that the word "Hello" was missing in the last two messages. Let's fix that now. Modify the lines that print the message to the following code: -:::code language="csharp" source="./snippets/HelloWorld/Program.cs" id="ConcatMessage"::: +:::code language="csharp" source="./snippets/HelloWorld/hello-world.cs" id="ConcatMessage"::: TODO: Run the app again using `dotnet run` (or) `dotnet file.cs` to see the results. @@ -54,7 +54,7 @@ This process is called [String interpolation](../../language-reference/tokens/in If you add a `$` before the opening quote of the string, you can then include variables, like `aFriend`, inside the string between curly braces. Give it a try: -:::code language="csharp" source="./snippets/HelloWorld/Program.cs" id="Interpolation"::: +:::code language="csharp" source="./snippets/HelloWorld/hello-world.cs" id="Interpolation"::: TODO: Run the app again using `dotnet run` (or) `dotnet file.cs` to see the results. Instead of "Hello {aFriend}", the message should be "Hello Maira". @@ -64,11 +64,11 @@ Your last edit was our first look at what you can do with strings. Let's explore You're not limited to a single variable between the curly braces. Try the following code at the bottom of your app: -:::code language="csharp" source="./snippets/HelloWorld/Program.cs" id="WorkWithStrings"::: +:::code language="csharp" source="./snippets/HelloWorld/hello-world.cs" id="WorkWithStrings"::: Strings are more than a collection of letters. You can find the length of a string using `Length`. `Length` is a **property** of a string and it returns the number of characters in that string. Add the following code at the bottom of your app: -:::code language="csharp" source="./snippets/HelloWorld/Program.cs" id="Properties"::: +:::code language="csharp" source="./snippets/HelloWorld/hello-world.cs" id="Properties"::: > [!TIP] > @@ -81,7 +81,7 @@ You've been using a *method*, method and related methods and do that work. You can just use those methods to remove leading and trailing spaces. Try the following code: -:::code language="csharp" source="./snippets/HelloWorld/Program.cs" id="Trim"::: +:::code language="csharp" source="./snippets/HelloWorld/hello-world.cs" id="Trim"::: The square brackets `[` and `]` help visualize what the `Trim`, `TrimStart,` and, `TrimEnd` methods do. The brackets show where whitespace starts and ends. @@ -91,17 +91,17 @@ This sample reinforces a couple of important concepts for working with strings. There are other methods available to work with a string. For example, you probably used a search and replace command in an editor or word processor before. The method does something similar in a string. It searches for a substring and replaces it with different text. The method takes two **parameters**. These parameters are the strings between the parentheses. The first string is the text to search for. The second string is the text to replace it with. Try it for yourself. Add this code. Type it in to see the hints as you start typing `.Re` after the `sayHello` variable: -:::code language="csharp" source="./snippets/HelloWorld/Program.cs" id="Replace"::: +:::code language="csharp" source="./snippets/HelloWorld/hello-world.cs" id="Replace"::: Two other useful methods make a string ALL CAPS or all lower case. Try the following code. Type it in to see how **IntelliSense** provides hints as you start to type `To`: -:::code language="csharp" source="./snippets/HelloWorld/Program.cs" id="UpperLower"::: +:::code language="csharp" source="./snippets/HelloWorld/hello-world.cs" id="UpperLower"::: ## Search strings The other part of a *search and replace* operation is to find text in a string. You can use the method for searching. It tells you if a string contains a substring inside it. Try the following code to explore : -:::code language="csharp" source="./snippets/HelloWorld/Program.cs" id="SearchStrings"::: +:::code language="csharp" source="./snippets/HelloWorld/hello-world.cs" id="SearchStrings"::: The method returns a *boolean* value which tells you if the string you were searching for was found. A *boolean* stores either a `true` or a `false` value. When displayed as text output, they're capitalized: `True` and `False`, respectively. You learn more about *boolean* values in a later lesson. @@ -120,7 +120,7 @@ Did you come up with something like the following (expand to see the answer):
-:::code language="csharp" source="./snippets/HelloWorld/Program.cs" id="Challenge"::: +:::code language="csharp" source="./snippets/HelloWorld/hello-world.cs" id="Challenge":::
diff --git a/docs/csharp/tour-of-csharp/tutorials/list-collection.md b/docs/csharp/tour-of-csharp/tutorials/list-collection.md index 663ca9bea8a03..8bc9ec52735d3 100644 --- a/docs/csharp/tour-of-csharp/tutorials/list-collection.md +++ b/docs/csharp/tour-of-csharp/tutorials/list-collection.md @@ -15,7 +15,7 @@ This tutorial teaches you C#. You write C# code and see the results of compiling Add the following code to your source file. Replace `` with your name. Then, type `dotnet run` to run the code: -:::code language="csharp" source="./snippets/ListCollection/Program.cs" id="BasicList"::: +:::code language="csharp" source="./snippets/ListCollection/list.cs" id="BasicList"::: You created a list of strings, added three names to that list, and printed the names in all CAPS. You're using concepts that you learned in earlier tutorials to loop through the list. @@ -29,17 +29,17 @@ The collection you created uses the t One important aspect of this type is that it can grow or shrink, enabling you to add or remove elements. You can see the results by modifying the contents after you displayed its contents. Add the following code after the code you already wrote (the loop that prints the contents): -:::code language="csharp" source="./snippets/ListCollection/Program.cs" id="ModifyList"::: +:::code language="csharp" source="./snippets/ListCollection/list.cs" id="ModifyList"::: You added two more names to the end of the list. You also removed one as well. The output from this block of code shows the initial contents, then prints a blank line and the new contents. The enables you to reference individual items by **index** as well. You access items using the `[` and `]` tokens. Add the following code after what you already wrote and try it: -:::code language="csharp" source="./snippets/ListCollection/Program.cs" id="Indexers"::: +:::code language="csharp" source="./snippets/ListCollection/list.cs" id="Indexers"::: You're not allowed to access past the end of the list. You can check how long the list is using the property. Add the following code: -:::code language="csharp" source="./snippets/ListCollection/Program.cs" id="Property"::: +:::code language="csharp" source="./snippets/ListCollection/list.cs" id="Property"::: Type `dotnet run` again to see the results. In C#, indices start at 0, so the largest valid index is one less than the number of items in the list. @@ -49,23 +49,23 @@ For more information about indices, see the [Explore indexes and ranges](../../t Our samples use relatively small lists, but your applications might often create lists with many more elements, sometimes numbering in the thousands. To find elements in these larger collections, you need to search the list for different items. The method searches for an item and returns the index of the item. If the item isn't in the list, `IndexOf` returns `-1`. Try it to see how it works. Add the following code after what you wrote so far: -:::code language="csharp" source="./snippets/ListCollection/Program.cs" id="Search"::: +:::code language="csharp" source="./snippets/ListCollection/list.cs" id="Search"::: You might not know if an item is in the list, so you should always check the index returned by . If it's `-1`, the item wasn't found. The items in your list can be sorted as well. The method sorts all the items in the list in their normal order (alphabetically for strings). Add this code and run again: -:::code language="csharp" source="./snippets/ListCollection/Program.cs" id="Sort"::: +:::code language="csharp" source="./snippets/ListCollection/list.cs" id="Sort"::: ## Lists of other types You've been using the `string` type in lists so far. Let's make a using a different type. Let's build a set of numbers. Add the following code at the end of your source file: -:::code language="csharp" source="./snippets/ListCollection/Program.cs" id="CreateList"::: +:::code language="csharp" source="./snippets/ListCollection/list.cs" id="CreateList"::: That creates a list of integers, and sets the first two integers to the value 1. The *Fibonacci Sequence*, a sequence of numbers, starts with two 1's. Each next Fibonacci number is found by taking the sum of the previous two numbers. Add this code: -:::code language="csharp" source="./snippets/ListCollection/Program.cs" id="Fibonacci"::: +:::code language="csharp" source="./snippets/ListCollection/list.cs" id="Fibonacci"::: Type `dotnet run` to see the results. @@ -78,7 +78,7 @@ Did you come up with something like this?
-:::code language="csharp" source="./snippets/ListCollection/Program.cs" id="Answer"::: +:::code language="csharp" source="./snippets/ListCollection/list.cs" id="Answer"::: With each iteration of the loop, you're taking the last two integers in the list, summing them, and adding that value to the list. The loop repeats until you added 20 items to the list.
diff --git a/docs/csharp/tour-of-csharp/tutorials/numbers-in-csharp.md b/docs/csharp/tour-of-csharp/tutorials/numbers-in-csharp.md index e2ffb854b9f05..1fc2f46cbe3c4 100644 --- a/docs/csharp/tour-of-csharp/tutorials/numbers-in-csharp.md +++ b/docs/csharp/tour-of-csharp/tutorials/numbers-in-csharp.md @@ -15,9 +15,9 @@ Create a directory named *numbers-quickstart*. Make it the current directory and dotnet new console -n NumbersInCSharp -o . ``` -Open *Program.cs* in your favorite editor, and replace the contents of the file with the following code: +Open *numbers.cs* in your favorite editor, and replace the contents of the file with the following code: -:::code language="csharp" source="./snippets/NumbersInCsharp/Program.cs" id="Addition"::: +:::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="Addition"::: Addition Run this code by typing `dotnet run` in your command window. @@ -30,7 +30,7 @@ You've seen one of the fundamental math operations with integers. The `int` type Start by exploring those different operations. Add these lines after the line that writes the value of `c`: -:::code language="csharp" source="./snippets/NumbersInCsharp/Program.cs" id="OtherOperations"::: +:::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="OtherOperations"::: Run this code by typing `dotnet run` in your command window. @@ -78,23 +78,23 @@ The `//` starts a **comment** in C#. Comments are any text you want to keep in y The C# language defines the precedence of different mathematics operations with rules consistent with the rules you learned in mathematics. Multiplication and division take precedence over addition and subtraction. Explore that by adding the following code after the call to `WorkWithIntegers()`, and executing `dotnet run`: -:::code language="csharp" source="./snippets/NumbersInCsharp/Program.cs" id="Precedence"::: +:::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="Precedence"::: The output demonstrates that the multiplication is performed before the addition. You can force a different order of operation by adding parentheses around the operation or operations you want performed first. Add the following lines and run again: -:::code language="csharp" source="./snippets/NumbersInCsharp/Program.cs" id="Parentheses"::: +:::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="Parentheses"::: Explore more by combining many different operations. Add something like the following lines. Try `dotnet run` again. -:::code language="csharp" source="./snippets/NumbersInCsharp/Program.cs" id="CompoundExpression"::: +:::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="CompoundExpression"::: You may have noticed an interesting behavior for integers. Integer division always produces an integer result, even when you'd expect the result to include a decimal or fractional portion. If you haven't seen this behavior, try the following code: -:::code language="csharp" source="./snippets/NumbersInCsharp/Program.cs" id="Truncation"::: +:::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="Truncation"::: Type `dotnet run` again to see the results. @@ -151,15 +151,15 @@ void OrderPrecedence() That last sample showed you that integer division truncates the result. You can get the **remainder** by using the **remaimnder** operator, the `%` character. Try the following code after the method call to `OrderPrecedence()`: -:::code language="csharp" source="./snippets/NumbersInCsharp/Program.cs" id="QuotientAndRemainder"::: +:::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="QuotientAndRemainder"::: The C# integer type differs from mathematical integers in one other way: the `int` type has minimum and maximum limits. Try the following code to see those limits: -:::code language="csharp" source="./snippets/NumbersInCsharp/Program.cs" id="MinAndMax"::: +:::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="MinAndMax"::: If a calculation produces a value that exceeds those limits, you have an **underflow** or **overflow** condition. The answer appears to wrap from one limit to the other. To see an example, add these two lines to your code: -:::code language="csharp" source="./snippets/NumbersInCsharp/Program.cs" id="Overflow"::: +:::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="Overflow"::: Notice that the answer is very close to the minimum (negative) integer. It's the same as `min + 2`. The addition operation **overflowed** the allowed values for integers. The answer is a large negative number because an overflow "wraps around" from the largest possible integer value to the smallest. @@ -169,19 +169,19 @@ There are other numeric types with different limits and precision that you would The `double` numeric type represents a double-precision floating point number. Those terms may be new to you. A **floating point** number is useful to represent non-integral numbers that may be very large or small in magnitude. **Double-precision** is a relative term that describes the number of binary digits used to store the value. **Double precision** numbers have twice the number of binary digits as **single-precision**. On modern computers, it's more common to use double precision than single precision numbers. **Single precision** numbers are declared using the `float` keyword. Let's explore. Add the following code and see the result: -:::code language="csharp" source="./snippets/NumbersInCsharp/Program.cs" id="FloatingPoint"::: +:::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="FloatingPoint"::: Notice that the answer includes the decimal portion of the quotient. Try a slightly more complicated expression with doubles. You can use the following values, or substitute other numbers: -:::code language="csharp" source="./snippets/NumbersInCsharp/Program.cs" id="ChangeDoubleValues"::: +:::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="ChangeDoubleValues"::: The range of a double value is much greater than integer values. Try the following code below what you've written so far: -:::code language="csharp" source="./snippets/NumbersInCsharp/Program.cs" id="MinMax"::: +:::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="MinMax"::: These values are printed in scientific notation. The number to the left of the `E` is the significand. The number to the right is the exponent, as a power of 10. Just like decimal numbers in math, doubles in C# can have rounding errors. Try this code: -:::code language="csharp" source="./snippets/NumbersInCsharp/Program.cs" id="RoundingError"::: +:::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="RoundingError"::: You know that `0.3` is `3/10` and not exactly the same as `1/3`. Similarly, `0.33` is `33/100`. That value is closer to `1/3`, but still not exact. No matter how many decimal places you add, a rounding error remains. @@ -193,13 +193,13 @@ Try other calculations with large numbers, small numbers, multiplication, and di You've seen the basic numeric types in C#: integers and doubles. There's one other type to learn: the `decimal` type. The `decimal` type has a smaller range but greater precision than `double`. Let's take a look: -:::code language="csharp" source="./snippets/NumbersInCsharp/Program.cs" id="Decimal"::: +:::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="Decimal"::: There's one other type to learn: the `decimal` type. The `decimal` type has a smaller range but greater precision than `double`. Let's take a look: Notice that the range is smaller than the `double` type. You can see the greater precision with the decimal type by trying the following code: -:::code language="csharp" source="./snippets/NumbersInCsharp/Program.cs" id="Precision"::: +:::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="Precision"::: Notice that the math using the decimal type has more digits to the right of the decimal point. @@ -220,7 +220,7 @@ Once you try it, open the details pane to see how you did:
-:::code language="csharp" interactive="try-dotnet-method" source="./snippets/NumbersInCsharp/Program.cs" id="Challenge"::: +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/NumbersInCsharp/numbers.cs" id="Challenge":::
diff --git a/docs/csharp/tour-of-csharp/tutorials/pattern-matching.md b/docs/csharp/tour-of-csharp/tutorials/pattern-matching.md index 6a67dc9a584dc..6e8dc1ec882e2 100644 --- a/docs/csharp/tour-of-csharp/tutorials/pattern-matching.md +++ b/docs/csharp/tour-of-csharp/tutorials/pattern-matching.md @@ -15,7 +15,7 @@ The preceding tutorials demonstrated built-in types and types you define as tupl All the examples in this tutorial use text input that represents a series of bank transactions as comma separated values (CSV) input. In each of the samples you can match the record against a pattern using either an `is` or `switch` expression. This first example splits each line on the `,` character and then *matches* the first string field against the value "DEPOSIT" or "WITHDRAWAL" using an `is` expression. When it matches, the transaction amount is added or deducted from the current account balance. To see it work, add the following code to your source file. Then, type `dotnet run` in the console window. -:::code language="csharp" source="./snippets/PatternMatching/Program.cs" id="FirstExample"::: +:::code language="csharp" source="./snippets/PatternMatching/patterns.cs" id="FirstExample"::: Examine the output. You can see that each line is processed by comparing the value of the text in the first field. The preceding sample could be similarly constructed using the `==` operator to test that two `string` values are equal. Comparing a variable to a constant is a basic building block for pattern matching. Let's explore more of the building blocks that are part of pattern matching. @@ -23,15 +23,15 @@ Examine the output. You can see that each line is processed by comparing the val Another common use for pattern matching is to match on the values of an `enum` type. This next sample processes the input records to create a *tuple* where the first value is an `enum` value that notes a deposit or a withdrawal. The second value is the value of the transaction. Add the following code to the end of your source file. It defines the `TransactionType` enumeration: -:::code language="csharp" source="./snippets/PatternMatching/Program.cs" id="TransactionTypeEnum"::: +:::code language="csharp" source="./snippets/PatternMatching/patterns.cs" id="TransactionTypeEnum"::: Next, add a function to parse a bank transaction into a tuple that holds the transaction type and the value of the transaction. Add the following code before your declaration of the `TransactionType` enum: -:::code language="csharp" source="./snippets/PatternMatching/Program.cs" id="ParseTransaction"::: +:::code language="csharp" source="./snippets/PatternMatching/patterns.cs" id="ParseTransaction"::: Next, add a new loop to process the transaction data using the `TransactionType` enumeration you declared: -:::code language="csharp" source="./snippets/PatternMatching/Program.cs" id="EnumPatternMatch"::: +:::code language="csharp" source="./snippets/PatternMatching/patterns.cs" id="EnumPatternMatch"::: The preceding example also uses an `if` statement to check the value of an `enum` expression. Another form of pattern matching uses a `switch` expression. Let's explore that syntax and how you can use it. @@ -52,7 +52,7 @@ else The `else if` clause never matches because every number less than 10 is also less than 20. The `switch` expression ensures both of those characteristics are met, which results in fewer bugs in your apps. Let's try it and experiment. Copy the following code. Replace the two `if` statements in your `foreach` loop with the `switch` expression you copied. After you've modified the code, type `dotnet run` to run the new sample. -:::code language="csharp" source="./snippets/PatternMatching/Program.cs" id="SwitchEnumValue"::: +:::code language="csharp" source="./snippets/PatternMatching/patterns.cs" id="SwitchEnumValue"::: When you run the code, you see that it works the same. To demonstrate *subsumption*, reorder the switch arms as shown in the following snippet: @@ -73,15 +73,15 @@ The compiler issues a warning if the expression tested in a `switch` expression To finish this tutorial, let's explore one more building block to pattern matching: the *type pattern*. A *type pattern* tests an expression at run time to see if it's the specified type. You can use a type test with either an `is` expression or a `switch` expression. Let's modify the current sample in two ways. First, instead of a tuple, let's build `Deposit` and `Withdrawal` record types that represent the transactions. Add the following declarations just at the end of the your code file: -:::code language="csharp" source="./snippets/PatternMatching/Program.cs" id="RecordDeclarations"::: +:::code language="csharp" source="./snippets/PatternMatching/patterns.cs" id="RecordDeclarations"::: Next, add this method just before the declaration of the `TransactionType` enumeration. It parses the text and return a series of records: -:::code language="csharp" source="./snippets/PatternMatching/Program.cs" id="ParseToRecord"::: +:::code language="csharp" source="./snippets/PatternMatching/patterns.cs" id="ParseToRecord"::: Finally, add the following code after the last `foreach` loop: -:::code language="csharp" source="./snippets/PatternMatching/Program.cs" id="TypePattern"::: +:::code language="csharp" source="./snippets/PatternMatching/patterns.cs" id="TypePattern"::: Then, type `dotnet run` to see the results. This final version tests the input against a *type*. diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/BranchesAndLoops/BranchesAndLoops.csproj b/docs/csharp/tour-of-csharp/tutorials/snippets/BranchesAndLoops/BranchesAndLoops.csproj deleted file mode 100644 index ed9781c223ab9..0000000000000 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/BranchesAndLoops/BranchesAndLoops.csproj +++ /dev/null @@ -1,10 +0,0 @@ - - - - Exe - net10.0 - enable - enable - - - diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/BranchesAndLoops/Program.cs b/docs/csharp/tour-of-csharp/tutorials/snippets/BranchesAndLoops/branches-loops.cs similarity index 100% rename from docs/csharp/tour-of-csharp/tutorials/snippets/BranchesAndLoops/Program.cs rename to docs/csharp/tour-of-csharp/tutorials/snippets/BranchesAndLoops/branches-loops.cs diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/HelloWorld/HelloWorld.csproj b/docs/csharp/tour-of-csharp/tutorials/snippets/HelloWorld/HelloWorld.csproj deleted file mode 100644 index ed9781c223ab9..0000000000000 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/HelloWorld/HelloWorld.csproj +++ /dev/null @@ -1,10 +0,0 @@ - - - - Exe - net10.0 - enable - enable - - - diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/HelloWorld/Program.cs b/docs/csharp/tour-of-csharp/tutorials/snippets/HelloWorld/hello-world.cs similarity index 100% rename from docs/csharp/tour-of-csharp/tutorials/snippets/HelloWorld/Program.cs rename to docs/csharp/tour-of-csharp/tutorials/snippets/HelloWorld/hello-world.cs diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/ListCollection/ListCollection.csproj b/docs/csharp/tour-of-csharp/tutorials/snippets/ListCollection/ListCollection.csproj deleted file mode 100644 index ed9781c223ab9..0000000000000 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/ListCollection/ListCollection.csproj +++ /dev/null @@ -1,10 +0,0 @@ - - - - Exe - net10.0 - enable - enable - - - diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/ListCollection/Program.cs b/docs/csharp/tour-of-csharp/tutorials/snippets/ListCollection/list.cs similarity index 100% rename from docs/csharp/tour-of-csharp/tutorials/snippets/ListCollection/Program.cs rename to docs/csharp/tour-of-csharp/tutorials/snippets/ListCollection/list.cs diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/NumbersInCsharp/Program.cs b/docs/csharp/tour-of-csharp/tutorials/snippets/NumbersInCsharp/Numbers.cs similarity index 100% rename from docs/csharp/tour-of-csharp/tutorials/snippets/NumbersInCsharp/Program.cs rename to docs/csharp/tour-of-csharp/tutorials/snippets/NumbersInCsharp/Numbers.cs diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/NumbersInCsharp/NumbersInCsharp.csproj b/docs/csharp/tour-of-csharp/tutorials/snippets/NumbersInCsharp/NumbersInCsharp.csproj deleted file mode 100644 index ed9781c223ab9..0000000000000 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/NumbersInCsharp/NumbersInCsharp.csproj +++ /dev/null @@ -1,10 +0,0 @@ - - - - Exe - net10.0 - enable - enable - - - diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/PatternMatching.csproj b/docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/PatternMatching.csproj deleted file mode 100644 index ed9781c223ab9..0000000000000 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/PatternMatching.csproj +++ /dev/null @@ -1,10 +0,0 @@ - - - - Exe - net10.0 - enable - enable - - - diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/Program.cs b/docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/patterns.cs similarity index 100% rename from docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/Program.cs rename to docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/patterns.cs diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/TuplesAndTypes.csproj b/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/TuplesAndTypes.csproj deleted file mode 100644 index ed9781c223ab9..0000000000000 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/TuplesAndTypes.csproj +++ /dev/null @@ -1,10 +0,0 @@ - - - - Exe - net10.0 - enable - enable - - - diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/Program.cs b/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/tuples-types.cs similarity index 100% rename from docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/Program.cs rename to docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/tuples-types.cs diff --git a/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md b/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md index 05c0e2a4a783c..8f0f8c59f8bbd 100644 --- a/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md +++ b/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md @@ -15,30 +15,30 @@ TODO: Create sample. *Tuples* are an ordered sequence of values with a fixed length. Each element of a tuple has a type and an optional name. The following code declares a tuple that represents a 2D point. Copy the following code to your file and type `dotnet run`. -:::code language="csharp" source="./snippets/TuplesAndTypes/Program.cs" id="CreateTuple"::: +:::code language="csharp" source="./snippets/TuplesAndTypes/tuples-types.cs" id="CreateTuple"::: > [!TIP] > As you explore C# (or any programming language), you make mistakes when you write code. The **compiler** finds those errors and reports them to you. When the output contains error messages, look closely at the example code and your code to see what to fix. That exercise helps you learn the structure of C# code. You can also ask Copilot to find differences or spot any mistakes. You can reassign any member of a tuple. Add the following code after the existing code. Type `dotnet run` again to see the results. -:::code language="csharp" source="./snippets/TuplesAndTypes/Program.cs" id="Modify"::: +:::code language="csharp" source="./snippets/TuplesAndTypes/tuples-types.cs" id="Modify"::: You can also create a new tuple that's a modified copy of the original using a `with` expression. Add the following code after the existing code and type `dotnet run` to see the results: -:::code language="csharp" source="./snippets/TuplesAndTypes/Program.cs" id="Wither"::: +:::code language="csharp" source="./snippets/TuplesAndTypes/tuples-types.cs" id="Wither"::: The tuple `pt2` contains the `X` value of `pt` (6), and `pt2.Y` is 10. Tuples are structural types. In other words, tuple types don't have names like `string` or `int`. A tuple type is defined by the number of members, referred to as *arity*, and the types of those members. The member names are for convenience. You can assign a tuple to a tuple with the same arity and types even if the members have different names. You can add the following code after the code you already wrote and try it: -:::code language="csharp" source="./snippets/TuplesAndTypes/Program.cs" id="NamedAssignment"::: +:::code language="csharp" source="./snippets/TuplesAndTypes/tuples-types.cs" id="NamedAssignment"::: The variable `subscript` has two members, both of which are integers. Both `subscript` and `pt` represent instances of the same tuple type: a tuple containing 2 `int` members. Tuples are easy to create: You declare multiple members enclosed in parentheses. All the following declare different tuples of different arities and member types. Add the following code to create new tuple types: -:::code language="csharp" source="./snippets/TuplesAndTypes/Program.cs" id="TupleTypes"::: +:::code language="csharp" source="./snippets/TuplesAndTypes/tuples-types.cs" id="TupleTypes"::: While tuples are easy to create, they're limited in their capabilities. Tuple types don't have names, so you can't convey meaning to the set of values. Tuple types can't add behavior. C# has other kinds of types you can create when your type defines behavior. @@ -48,27 +48,27 @@ Tuples are great for those times when you want multiple values in the same struc The following code declares and uses a `record` type to represent a `Point`: -:::code language="csharp" source="./snippets/TuplesAndTypes/Program.cs" id="PointRecord"::: +:::code language="csharp" source="./snippets/TuplesAndTypes/tuples-types.cs" id="PointRecord"::: The preceding code must be at the bottom of your source file. Type declarations like `record` declarations must follow executable statements in a file-based app. Add the following code preceding the `record` declaration: -:::code language="csharp" source="./snippets/TuplesAndTypes/Program.cs" id="UsePointRecord"::: +:::code language="csharp" source="./snippets/TuplesAndTypes/tuples-types.cs" id="UsePointRecord"::: The `record` declaration is a single line of code for the `Point` type that stores the values `X` and `Y` in readonly properties. You use the name `Point` wherever you use that type. Properly named types, like `Point`, provide information about how the type is used. The additional code shows how to use a `with` expression to create a new point that's a modified copy of the existing point. The line `pt4 = pt3 with { Y = 10 }` says "`pt4` has the same values as `pt3` except that `Y` is assigned to 10." You can add any number of properties to change in a single `with` expression. The preceding `record` declaration is a single line of code that ends in `;`. You can add behavior to a `record` type by declaring *members*. A record member can be a function, or more data elements. The members of a type are in the type declaration, between `{` and `}` characters. Delete the `;` and add the following lines of code after the `record` declaration: -:::code language="csharp" source="./snippets/TuplesAndTypes/Program.cs" id="AddSlopeMethod"::: +:::code language="csharp" source="./snippets/TuplesAndTypes/tuples-types.cs" id="AddSlopeMethod"::: Then, add the following code before the `record` declaration, after the line containing the `with` expression: -:::code language="csharp" source="./snippets/TuplesAndTypes/Program.cs" id="UseSlope"::: +:::code language="csharp" source="./snippets/TuplesAndTypes/tuples-types.cs" id="UseSlope"::: You added formality to the *tuple* representing an `X` and `Y` value. You made it a `record` that defined a named type, and included a member to calculate the slope. A `record` type is a shorthand for a `record class`: A `class` type that includes extra behavior. You can modify the `Point` type to make it a `record struct` as well: -:::code language="csharp" source="./snippets/TuplesAndTypes/Program.cs" id="RecordStructPoint"::: +:::code language="csharp" source="./snippets/TuplesAndTypes/tuples-types.cs" id="RecordStructPoint"::: A `record struct` is a `struct` type that includes the extra behavior added to all `record` types. From b9fe3ada37c09a18aceec662ba6d9c92c65a17db Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Fri, 5 Dec 2025 17:05:46 -0500 Subject: [PATCH 10/13] Edit for using codespaces --- .../tutorials/branches-and-loops.md | 17 +++++++---- .../tour-of-csharp/tutorials/hello-world.md | 23 +++++++++------ docs/csharp/tour-of-csharp/tutorials/index.md | 11 +++----- .../tutorials/list-collection.md | 17 +++++++---- .../tutorials/numbers-in-csharp.md | 28 +++++++++---------- .../tutorials/pattern-matching.md | 19 +++++++++---- .../tutorials/tuples-and-types.md | 27 ++++++++++++------ 7 files changed, 90 insertions(+), 52 deletions(-) diff --git a/docs/csharp/tour-of-csharp/tutorials/branches-and-loops.md b/docs/csharp/tour-of-csharp/tutorials/branches-and-loops.md index 85163228a3ab0..f7445db4f6f1d 100644 --- a/docs/csharp/tour-of-csharp/tutorials/branches-and-loops.md +++ b/docs/csharp/tour-of-csharp/tutorials/branches-and-loops.md @@ -7,22 +7,29 @@ ms.date: 12/03/2025 This tutorial teaches you how to write C# code that examines variables and changes the execution path based on those variables. You write C# code and see the results of compiling and running it. The tutorial contains a series of lessons that explore branching and looping constructs in C#. These lessons teach you the fundamentals of the C# language. -TODO: Build an app, create a file. +To use codespaces, you need a GitHub account. If you don't already have one, you can create a free account at [GitHub.com](https://github.com). -Open *branches-loops.cs* in your favorite editor, and replace the contents with the following code: +Open a browser window to [GitHub codespaces](https://github.com/codespaces). Create a new codespace from the *.NET Template*. If you've done other tutorials in this series, you can open that codespace. Once your codespace loads, create a new file in the *tutorials* folder named *branches-loops.cs*. Open your new file. Type or copy the following code into *branches-loops.cs*: :::code language="csharp" source="./snippets/BranchesAndLoops/branches-loops.cs" id="FirstIf"::: -Try this code by typing `dotnet run` in your console window. You should see the message "The answer is greater than 10." printed to your console. Modify the declaration of `b` so that the sum is less than 10: +Try this code by typing the following in the integrated terminal: + +```dotnetcli +cd tutorials +dotnet branches-loops.cs +``` + +You should see the message "The answer is greater than 10." printed to your console. Modify the declaration of `b` so that the sum is less than 10: ```csharp int b = 3; ``` -Type `dotnet run` again. Because the answer is less than 10, nothing is printed. The **condition** you're testing is false. You don't have any code to execute because you've only written one of the possible branches for an `if` statement: the true branch. +Type `dotnet branches-loops.cs` again in the terminal window. Because the answer is less than 10, nothing is printed. The **condition** you're testing is false. You don't have any code to execute because you've only written one of the possible branches for an `if` statement: the true branch. > [!TIP] -> As you explore C# (or any programming language), you'll make mistakes when you write code. The compiler will find and report the errors. Look closely at the error output and the code that generated the error. The compiler error can usually help you find the problem. +> As you explore C# (or any programming language), you'll make mistakes when you write code. The compiler will find and report the errors. Look closely at the error output and the code that generated the error. You can also ask Copilot to find differences or spot any mistakes. The compiler error can usually help you find the problem. This first sample shows the power of `if` and Boolean types. A *Boolean* is a variable that can have one of two values: `true` or `false`. C# defines a special type, `bool` for Boolean variables. The `if` statement checks the value of a `bool`. When the value is `true`, the statement following the `if` executes. Otherwise, it's skipped. This process of checking conditions and executing statements based on those conditions is powerful. Let's explore more. diff --git a/docs/csharp/tour-of-csharp/tutorials/hello-world.md b/docs/csharp/tour-of-csharp/tutorials/hello-world.md index 8f4bd18e5f7df..61be528f0ab55 100644 --- a/docs/csharp/tour-of-csharp/tutorials/hello-world.md +++ b/docs/csharp/tour-of-csharp/tutorials/hello-world.md @@ -7,15 +7,22 @@ ms.date: 12/02/2025 This tutorial teaches you C#. You write your first C# and see the results of compiling and running your code. It contains a series of lessons that begin with a "Hello World" program. These lessons teach you the fundamentals of the C# language. -## Run your first program +To use codespaces, you need a GitHub account. If you don't already have one, you can create a free account at [GitHub.com](https://github.com). -TODO: `dotnet new` or create a file. +## Run your first program -Type the following code in your new `cs` file: +Open a browser window to [GitHub codespaces](https://github.com/codespaces). Create a new codespace from the *.NET Template*. Once your codespace loads, create a new file in the *tutorials* folder named *hello-world.cs*. Open your new file. Type or copy the following code into *hello-world.cs*: :::code language="csharp" source="./snippets/HelloWorld/hello-world.cs" id="HelloWorld"::: -TODO: To run the program, type `dotnet run` (or) `dotnet file.cs` at the command prompt. Congratulations! You ran your first C# program. It's a simple program that prints the message "Hello World!" It used the method to print that message. `Console` is a type that represents the console window. `WriteLine` is a method of the `Console` type that prints a line of text to that text console. +In the integrated terminal window, make the *tutorials* folder the current folder, and run your program: + +```dotnetcli +cd tutorials +dotnet hello-world.cs +``` + +Congratulations! You ran your first C# program. It's a simple program that prints the message "Hello World!" It used the method to print that message. `Console` is a type that represents the console window. `WriteLine` is a method of the `Console` type that prints a line of text to that text console. Let's move on and explore more. The rest of this lesson explores working with the `string` type, which represents text in C#. Like the `Console` type, the `string` type has methods. The `string` methods work with text. @@ -25,7 +32,7 @@ Your first program printed the `string` "Hello World!" on the screen. > [!TIP] > -> As you explore C# (or any programming language), you make mistakes when you write code. The **compiler** finds those errors and report them to you. When the output contains error messages, look closely at the example code, and the code in your `.cs` file to see what to fix. That exercise helps you learn the structure of C# code. +> As you explore C# (or any programming language), you make mistakes when you write code. The **compiler** finds those errors and report them to you. When the output contains error messages, look closely at the example code, and the code in your `.cs` file to see what to fix. That exercise helps you learn the structure of C# code. You can also ask Copilot to find differences or spot mistakes. Your first program is limited to printing one message. You can write more useful programs by using *variables*. A *variable* is a symbol you can use to run the same code with different values. Let's try it! Start with the following code: @@ -46,7 +53,7 @@ You might notice that the word "Hello" was missing in the last two messages. Let :::code language="csharp" source="./snippets/HelloWorld/hello-world.cs" id="ConcatMessage"::: -TODO: Run the app again using `dotnet run` (or) `dotnet file.cs` to see the results. +Run the app again using `dotnet hello-world.cs` to see the results. You've been using `+` to build strings from **variables** and **constant** strings. There's a better way. You can place a variable between `{` and `}` characters to tell C# to replace that text with the value of the variable. @@ -56,7 +63,7 @@ If you add a `$` before the opening quote of the string, you can then include va :::code language="csharp" source="./snippets/HelloWorld/hello-world.cs" id="Interpolation"::: -TODO: Run the app again using `dotnet run` (or) `dotnet file.cs` to see the results. Instead of "Hello {aFriend}", the message should be "Hello Maira". +Run the app again using `dotnet hello-world.cs` to see the results. Instead of "Hello {aFriend}", the message should be "Hello Maira". ## Work with strings @@ -124,7 +131,7 @@ Did you come up with something like the following (expand to see the answer): -You completed the "Hello C#" introduction to C# tutorial. You can select the **Numbers in C#** tutorial to start the next tutorial, or you can visit the [.NET site](https://dotnet.microsoft.com/learn/dotnet/hello-world-tutorial/intro) to download the .NET SDK, create a project on your machine, and keep coding. The "Next steps" section brings you back to these tutorials. +You completed the "Hello C#" introduction to C# tutorial. You can select the [Numbers in C#](./numbers-in-csharp.md) tutorial to start the next tutorial, or you can visit the [.NET site](https://dotnet.microsoft.com/learn/dotnet/hello-world-tutorial/intro) to download the .NET SDK, create a project on your machine, and keep coding. For further reading on the `string` type: diff --git a/docs/csharp/tour-of-csharp/tutorials/index.md b/docs/csharp/tour-of-csharp/tutorials/index.md index 67c0ade444c0f..16f89327b7ab0 100644 --- a/docs/csharp/tour-of-csharp/tutorials/index.md +++ b/docs/csharp/tour-of-csharp/tutorials/index.md @@ -1,25 +1,22 @@ --- title: Interactive tutorials description: Learn C# in your browser, and get started with your own development environment -ms.date: 04/23/2025 +ms.date: 12/05/2025 --- # Introduction to C\# -Welcome to the introduction to C# tutorials. These lessons start with interactive code that you can run in your browser. You can learn the basics of C# from the [C# for Beginners video series](https://aka.ms/dotnet/beginnervideos/youtube/csharp) before starting these interactive lessons. +Welcome to the introduction to C# tutorials. These lessons start with interactive code that you can run in GitHub codespaces. You can learn the basics of C# from the [C# for Beginners video series](https://aka.ms/dotnet/beginnervideos/youtube/csharp) before starting these interactive lessons. > [!VIDEO https://www.youtube.com/embed/9THmGiSPjBQ?si=3kUKFtOMLpEzeq7J] The first lessons explain C# concepts using small snippets of code. You'll learn the basics of C# syntax and how to work with data types like strings, numbers, and booleans. It's all interactive, and you'll be writing and running code within minutes. These first lessons assume no prior knowledge of programming or the C# language. Each lesson builds on the prior lessons. You should do them in order. However, if you have some programming experience, you can skip or skim the first lessons and start with any new concepts. -You can try these tutorials in different environments. The concepts you'll learn are the same. The difference is which experience you prefer: - -- [In your browser, on the docs platform](hello-world.md): This experience embeds a runnable C# code window in docs pages. You write and execute C# code in the browser. -- [In the Microsoft Learn training experience](/training/paths/csharp-first-steps/). This learning path contains several modules that teach the basics of C#. +To use GitHub codespaces, you need to create a free [GitHub](https://github.com) account. ## Hello world -In the [Hello world](hello-world.md) tutorial, you'll create the most basic C# program. You'll explore the `string` type and how to work with text. You can also use the path on [Microsoft Learn training](/training/paths/csharp-first-steps/). +In the [Hello world](hello-world.md) tutorial, you'll create the most basic C# program. You'll explore the `string` type and how to work with text. ## Numbers in C\# diff --git a/docs/csharp/tour-of-csharp/tutorials/list-collection.md b/docs/csharp/tour-of-csharp/tutorials/list-collection.md index 8bc9ec52735d3..b361864b3a453 100644 --- a/docs/csharp/tour-of-csharp/tutorials/list-collection.md +++ b/docs/csharp/tour-of-csharp/tutorials/list-collection.md @@ -5,18 +5,25 @@ ms.date: 03/07/2025 --- # Learn to manage data collections using List\ in C\# -This introductory tutorial provides an introduction to the C# language and the basics of the class. +This introductory tutorial provides an introduction to the C# language and the basics of the class. This tutorial teaches you C#. You write C# code and see the results of compiling and running that code. It contains a series of lessons that create, modify, and explore collections and arrays. You work primarily with the class. -<< TODO Create the app>> +To use codespaces, you need a GitHub account. If you don't already have one, you can create a free account at [GitHub.com](https://github.com). ## A basic list example -Add the following code to your source file. Replace `` with your name. Then, type `dotnet run` to run the code: +Open a browser window to [GitHub codespaces](https://github.com/codespaces). Create a new codespace from the *.NET Template*. If you've done other tutorials in this series, you can open that codespace. Once your codespace loads, create a new file in the *tutorials* folder named *lists.cs*. Open your new file. Type or copy the following code into *lists.cs*: :::code language="csharp" source="./snippets/ListCollection/list.cs" id="BasicList"::: +Run the code by typing the following in the terminal window: + +```dotnetcli +cd tutorials +dotnet lists.cs +``` + You created a list of strings, added three names to that list, and printed the names in all CAPS. You're using concepts that you learned in earlier tutorials to loop through the list. The code to display names makes use of the [string interpolation](../../language-reference/tokens/interpolated.md) feature. When you precede a `string` with the `$` character, you can embed C# code in the string declaration. The actual string replaces that C# code with the value it generates. In this example, it replaces the `{name.ToUpper()}` with each name, converted to capital letters, because you called the method. @@ -41,7 +48,7 @@ You're not allowed to access past the end of the list. You can check how long th :::code language="csharp" source="./snippets/ListCollection/list.cs" id="Property"::: -Type `dotnet run` again to see the results. In C#, indices start at 0, so the largest valid index is one less than the number of items in the list. +Type `dotnet lists.cs` again in the terminal window to see the results. In C#, indices start at 0, so the largest valid index is one less than the number of items in the list. For more information about indices, see the [Explore indexes and ranges](../../tutorials/ranges-indexes.md) article. @@ -67,7 +74,7 @@ That creates a list of integers, and sets the first two integers to the value 1. :::code language="csharp" source="./snippets/ListCollection/list.cs" id="Fibonacci"::: -Type `dotnet run` to see the results. +Type `dotnet lists` in the terminal window to see the results. ## Challenge diff --git a/docs/csharp/tour-of-csharp/tutorials/numbers-in-csharp.md b/docs/csharp/tour-of-csharp/tutorials/numbers-in-csharp.md index 1fc2f46cbe3c4..415c9df8eaaf2 100644 --- a/docs/csharp/tour-of-csharp/tutorials/numbers-in-csharp.md +++ b/docs/csharp/tour-of-csharp/tutorials/numbers-in-csharp.md @@ -7,20 +7,20 @@ ms.date: 12/02/2025 This tutorial teaches you about the numeric types in C#. You write small amounts of code, then you compile and run that code. The tutorial contains a series of lessons that explore numbers and math operations in C#. These lessons teach you the fundamentals of the C# language. -## Explore integer math - -Create a directory named *numbers-quickstart*. Make it the current directory and run the following command: +To use codespaces, you need a GitHub account. If you don't already have one, you can create a free account at [GitHub.com](https://github.com). -```dotnetcli -dotnet new console -n NumbersInCSharp -o . -``` +## Explore integer math -Open *numbers.cs* in your favorite editor, and replace the contents of the file with the following code: +Open a browser window to [GitHub codespaces](https://github.com/codespaces). Create a new codespace from the *.NET Template*. If you've done the [hello world](./hello-world.md) tutorial, you can open that codespace. Once your codespace loads, create a new file in the *tutorials* folder named *numbers.cs*. Open your new file. Type or copy the following code into *numbers.cs*: :::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="Addition"::: -Addition -Run this code by typing `dotnet run` in your command window. +Run this code by typing the following commands in the integrated terminal: + +```dotnetcli +cd ./tutorials +dotnet numbers.cs +``` You've seen one of the fundamental math operations with integers. The `int` type represents an **integer**, a zero, positive, or negative whole number. You use the `+` symbol for addition. Other common mathematical operations for integers include: @@ -32,12 +32,12 @@ Start by exploring those different operations. Add these lines after the line th :::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="OtherOperations"::: -Run this code by typing `dotnet run` in your command window. +Run this code by typing `dotnet numers.cs` in the terminal window. You can also experiment by writing multiple mathematics operations in the same line, if you'd like. Try `c = a + b - 12 * 17;` for example. Mixing variables and constant numbers is allowed. > [!TIP] -> As you explore C# (or any programming language), you'll make mistakes when you write code. The **compiler** will find those errors and report them to you. When the output contains error messages, look closely at the example code and the code in your window to see what to fix. That exercise will help you learn the structure of C# code. +> As you explore C# (or any programming language), you'll make mistakes when you write code. The **compiler** will find those errors and report them to you. When the output contains error messages, look closely at the example code and the code in your window to see what to fix. You can also ask Copilot to find differences or spot mistakes. That exercise will help you learn the structure of C# code. You've finished the first step. Before you start the next section, let's move the current code into a separate *method*. A method is a series of statements grouped together and given a name. You call a method by writing the method's name followed by `()`. Organizing your code into methods makes it easier to start working with a new example. When you finish, your code should look like this: @@ -76,7 +76,7 @@ Comment out the call to `WorkingWithIntegers()`. It will make the output less cl The `//` starts a **comment** in C#. Comments are any text you want to keep in your source code but not execute as code. The compiler doesn't generate any executable code from comments. Because `WorkWithIntegers()` is a method, you need to only comment out one line. -The C# language defines the precedence of different mathematics operations with rules consistent with the rules you learned in mathematics. Multiplication and division take precedence over addition and subtraction. Explore that by adding the following code after the call to `WorkWithIntegers()`, and executing `dotnet run`: +The C# language defines the precedence of different mathematics operations with rules consistent with the rules you learned in mathematics. Multiplication and division take precedence over addition and subtraction. Explore that by adding the following code after the call to `WorkWithIntegers()`, and typing `dotnet numbers.cs` in the terminal window: :::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="Precedence"::: @@ -86,7 +86,7 @@ You can force a different order of operation by adding parentheses around the op :::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="Parentheses"::: -Explore more by combining many different operations. Add something like the following lines. Try `dotnet run` again. +Explore more by combining many different operations. Add something like the following lines. Try `dotnet numbers` again in the terminal window. :::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="CompoundExpression"::: @@ -96,7 +96,7 @@ If you haven't seen this behavior, try the following code: :::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="Truncation"::: -Type `dotnet run` again to see the results. +Type `dotnet numbers` again in the terminal window to see the results. Before moving on, let's take all the code you've written in this section and put it in a new method. Call that new method `OrderPrecedence`. Your code should look something like this: diff --git a/docs/csharp/tour-of-csharp/tutorials/pattern-matching.md b/docs/csharp/tour-of-csharp/tutorials/pattern-matching.md index 6e8dc1ec882e2..80062cf7df3c2 100644 --- a/docs/csharp/tour-of-csharp/tutorials/pattern-matching.md +++ b/docs/csharp/tour-of-csharp/tutorials/pattern-matching.md @@ -7,16 +7,25 @@ ms.date: 12/04/2025 This tutorial teaches you how to use pattern matching to inspect data in C#. You write small amounts of code, then you compile and run that code. The tutorial contains a series of lessons that explore different kinds of patterns supported by C#. These lessons teach you the fundamentals of the C# language. +To use codespaces, you need a GitHub account. If you don't already have one, you can create a free account at [GitHub.com](https://github.com). + The preceding tutorials demonstrated built-in types and types you define as tuples or records. Instances of these types can be checked against a *pattern*. Whether an instance matches a pattern determines the actions your program takes. In the examples below, you'll notice `?` after type names. This symbol allows the value of this type to be null (for example, `bool?` can be `true`, `false` or `null`). For more information, see [Nullable value types](../../language-reference/builtin-types/nullable-value-types.md). Let's start to explore how you can use patterns. -<< TO DO: Make your app >> +Open a browser window to [GitHub codespaces](https://github.com/codespaces). Create a new codespace from the *.NET Template*. If you've done other tutorials in this series, you can open that codespace. Once your codespace loads, create a new file in the *tutorials* folder named *patterns.cs*. Open your new file. ## Match a value -All the examples in this tutorial use text input that represents a series of bank transactions as comma separated values (CSV) input. In each of the samples you can match the record against a pattern using either an `is` or `switch` expression. This first example splits each line on the `,` character and then *matches* the first string field against the value "DEPOSIT" or "WITHDRAWAL" using an `is` expression. When it matches, the transaction amount is added or deducted from the current account balance. To see it work, add the following code to your source file. Then, type `dotnet run` in the console window. +All the examples in this tutorial use text input that represents a series of bank transactions as comma separated values (CSV) input. In each of the samples you can match the record against a pattern using either an `is` or `switch` expression. This first example splits each line on the `,` character and then *matches* the first string field against the value "DEPOSIT" or "WITHDRAWAL" using an `is` expression. When it matches, the transaction amount is added or deducted from the current account balance. To see it work, add the following code to *patterns.cs*: :::code language="csharp" source="./snippets/PatternMatching/patterns.cs" id="FirstExample"::: +Then, type the following in the terminal window: + +```dotnetcli +cd tutorials +dotnet patterns.cs +``` + Examine the output. You can see that each line is processed by comparing the value of the text in the first field. The preceding sample could be similarly constructed using the `==` operator to test that two `string` values are equal. Comparing a variable to a constant is a basic building block for pattern matching. Let's explore more of the building blocks that are part of pattern matching. ## Enum matches @@ -50,7 +59,7 @@ else Console.WriteLine("n is greater than 20"); ``` -The `else if` clause never matches because every number less than 10 is also less than 20. The `switch` expression ensures both of those characteristics are met, which results in fewer bugs in your apps. Let's try it and experiment. Copy the following code. Replace the two `if` statements in your `foreach` loop with the `switch` expression you copied. After you've modified the code, type `dotnet run` to run the new sample. +The `else if` clause never matches because every number less than 10 is also less than 20. The `switch` expression ensures both of those characteristics are met, which results in fewer bugs in your apps. Let's try it and experiment. Copy the following code. Replace the two `if` statements in your `foreach` loop with the `switch` expression you copied. After you've modified the code, type `dotnet patterns.cs` in the terminal window to run the new sample. :::code language="csharp" source="./snippets/PatternMatching/patterns.cs" id="SwitchEnumValue"::: @@ -65,7 +74,7 @@ currentBalance += transaction switch }; ``` -After you reorder the switch arms, type `dotnet run`. The compiler issues an error because the arm with `_` matches every value. As a result, that final arm with `TransactionType.Withdrawal` never runs. The compiler tells you that something's wrong in your code. +After you reorder the switch arms, type `dotnet patterns.cs` in the terminal window. The compiler issues an error because the arm with `_` matches every value. As a result, that final arm with `TransactionType.Withdrawal` never runs. The compiler tells you that something's wrong in your code. The compiler issues a warning if the expression tested in a `switch` expression could contain values that don't match any switch arm. If some values could fail to match any condition, the `switch` expression isn't *exhaustive*. The compiler also issues a warning if some values of the input don't match any of the switch arms. For example, if you remove the line with `_ => 0.0,`, any invalid values don't match. At run time, that would fail. Once you install the .NET SDK and build programs in your environment, you can test this behavior. The online experience doesn't display warnings in the output window. @@ -83,7 +92,7 @@ Finally, add the following code after the last `foreach` loop: :::code language="csharp" source="./snippets/PatternMatching/patterns.cs" id="TypePattern"::: -Then, type `dotnet run` to see the results. This final version tests the input against a *type*. +Then, type `dotnet patterns.cs` in the terminal window to see the results. This final version tests the input against a *type*. Pattern matching provides a vocabulary to compare an expression against characteristics. Patterns can include the expression's type, values of types, property values, and combinations of them. Comparing expressions against a pattern can be more clear than multiple `if` comparisons. You explored some of the patterns you can use to match expressions. There are many more ways to use pattern matching in your applications. First, visit the [.NET site](https://dotnet.microsoft.com/learn/dotnet/hello-world-tutorial/intro) to download the .NET SDK, create a project on your machine, and keep coding. As you explore, you can learn more about pattern matching in C# in the following articles: diff --git a/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md b/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md index 8f0f8c59f8bbd..36f09956890ed 100644 --- a/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md +++ b/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md @@ -9,28 +9,35 @@ This tutorial teaches you about creating types in C#. You write small amounts of The preceding tutorials worked with text and numbers. Strings and Numbers are *simple types*: They each store one single value. As your programs grow larger, you need to work with more sophisticated data structures. C# provides different kinds of types you can define when you need data structures with more fields, properties, or behavior. Let's start to explore those types. -TODO: Create sample. +To use codespaces, you need a GitHub account. If you don't already have one, you can create a free account at [GitHub.com](https://github.com). ## Tuples -*Tuples* are an ordered sequence of values with a fixed length. Each element of a tuple has a type and an optional name. The following code declares a tuple that represents a 2D point. Copy the following code to your file and type `dotnet run`. +Open a browser window to [GitHub codespaces](https://github.com/codespaces). Create a new codespace from the *.NET Template*. If you've done other tutorials in this series, you can open that codespace. Once your codespace loads, create a new file in the *tutorials* folder named *tuples.cs*. Open your new file. Type or copy the following code into *tuples.cs*: :::code language="csharp" source="./snippets/TuplesAndTypes/tuples-types.cs" id="CreateTuple"::: -> [!TIP] -> As you explore C# (or any programming language), you make mistakes when you write code. The **compiler** finds those errors and reports them to you. When the output contains error messages, look closely at the example code and your code to see what to fix. That exercise helps you learn the structure of C# code. You can also ask Copilot to find differences or spot any mistakes. +Run your program by typing the following commands in the integrated terminal window: + +```dotnetcli +cd tutorials +dotnet tuples.cs +``` + +*Tuples* are an ordered sequence of values with a fixed length. Each element of a tuple has a type and an optional name. -You can reassign any member of a tuple. Add the following code after the existing code. Type `dotnet run` again to see the results. +> [!TIP] +> As you explore C# (or any programming language), you make mistakes when you write code. The **compiler** finds those errors and reports them to you. When the output contains error messages, look closely at the example code and your code to see what to fix. You can also ask Copilot to find differences or spot any mistakes. That exercise helps you learn the structure of C# code. :::code language="csharp" source="./snippets/TuplesAndTypes/tuples-types.cs" id="Modify"::: -You can also create a new tuple that's a modified copy of the original using a `with` expression. Add the following code after the existing code and type `dotnet run` to see the results: +You can also create a new tuple that's a modified copy of the original using a `with` expression. Add the following code after the existing code and type `dotnet tuples.cs` in the terminal window to see the results: :::code language="csharp" source="./snippets/TuplesAndTypes/tuples-types.cs" id="Wither"::: The tuple `pt2` contains the `X` value of `pt` (6), and `pt2.Y` is 10. -Tuples are structural types. In other words, tuple types don't have names like `string` or `int`. A tuple type is defined by the number of members, referred to as *arity*, and the types of those members. The member names are for convenience. You can assign a tuple to a tuple with the same arity and types even if the members have different names. You can add the following code after the code you already wrote and try it: +Tuples are structural types. In other words, tuple types don't have names like `string` or `int`. A tuple type is defined by the number of members, referred to as *arity*, and the types of those members. The member names are for convenience. You can assign a tuple to a tuple with the same arity and types even if the members have different names. You can add the following code after the code you already wrote and try it by typing `dotnet tuples.cs` in the terminal window: :::code language="csharp" source="./snippets/TuplesAndTypes/tuples-types.cs" id="NamedAssignment"::: @@ -40,6 +47,8 @@ Tuples are easy to create: You declare multiple members enclosed in parentheses. :::code language="csharp" source="./snippets/TuplesAndTypes/tuples-types.cs" id="TupleTypes"::: +Try this change by typing `dotnet tuples.cs` again in the terminal window. + While tuples are easy to create, they're limited in their capabilities. Tuple types don't have names, so you can't convey meaning to the set of values. Tuple types can't add behavior. C# has other kinds of types you can create when your type defines behavior. ## Create record types @@ -66,11 +75,13 @@ Then, add the following code before the `record` declaration, after the line con :::code language="csharp" source="./snippets/TuplesAndTypes/tuples-types.cs" id="UseSlope"::: +Type `dotnet tuples.cs` in the terminal window to run this version. + You added formality to the *tuple* representing an `X` and `Y` value. You made it a `record` that defined a named type, and included a member to calculate the slope. A `record` type is a shorthand for a `record class`: A `class` type that includes extra behavior. You can modify the `Point` type to make it a `record struct` as well: :::code language="csharp" source="./snippets/TuplesAndTypes/tuples-types.cs" id="RecordStructPoint"::: -A `record struct` is a `struct` type that includes the extra behavior added to all `record` types. +A `record struct` is a `struct` type that includes the extra behavior added to all `record` types. Try this version by typing `dotnet tuples.cs` in the terminal window. ## Struct, class, and interface types From 563e904519cfd2000afea2526814ea92aeee5d6b Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Mon, 8 Dec 2025 17:03:48 -0500 Subject: [PATCH 11/13] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- docs/csharp/tour-of-csharp/tutorials/branches-and-loops.md | 3 +-- docs/csharp/tour-of-csharp/tutorials/hello-world.md | 4 ++-- docs/csharp/tour-of-csharp/tutorials/list-collection.md | 4 ++-- docs/csharp/tour-of-csharp/tutorials/numbers-in-csharp.md | 7 ++----- docs/csharp/tour-of-csharp/tutorials/pattern-matching.md | 2 +- .../tutorials/snippets/TuplesAndTypes/tuples-types.cs | 2 +- docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md | 1 + 7 files changed, 10 insertions(+), 13 deletions(-) diff --git a/docs/csharp/tour-of-csharp/tutorials/branches-and-loops.md b/docs/csharp/tour-of-csharp/tutorials/branches-and-loops.md index f7445db4f6f1d..06df3656c1351 100644 --- a/docs/csharp/tour-of-csharp/tutorials/branches-and-loops.md +++ b/docs/csharp/tour-of-csharp/tutorials/branches-and-loops.md @@ -39,7 +39,7 @@ To execute different code in both the true and false branches, you create an `el :::code language="csharp" source="./snippets/BranchesAndLoops/branches-loops.cs" id="IfAndElse"::: -The statement following the `else` keyword executes only when the condition being tested is `false`. Combining `if` and `else` with Boolean conditions provides all the power you need to handle both a `true` and a `false` condition. +The statement following the `else` keyword executes only when the condition being tested is `false`. Combining `if` and `else` with boolean conditions provides all the power you need to handle both a `true` and a `false` condition. > [!IMPORTANT] > The indentation under the `if` and `else` statements is for human readers. The C# language doesn't treat indentation or white space as significant. The statement following the `if` or `else` keyword executes based on the condition. All the samples in this tutorial follow a common practice to indent lines based on the control flow of statements. @@ -156,7 +156,6 @@ Did you come up with something like this? -You've completed the "branches and loops" tutorial. You completed the "branches and loops" tutorial. You can select the **list collection** link to start the next tutorial. diff --git a/docs/csharp/tour-of-csharp/tutorials/hello-world.md b/docs/csharp/tour-of-csharp/tutorials/hello-world.md index 61be528f0ab55..03fe92dcd390a 100644 --- a/docs/csharp/tour-of-csharp/tutorials/hello-world.md +++ b/docs/csharp/tour-of-csharp/tutorials/hello-world.md @@ -5,7 +5,7 @@ ms.date: 12/02/2025 --- # Introduction to C# - tutorial -This tutorial teaches you C#. You write your first C# and see the results of compiling and running your code. It contains a series of lessons that begin with a "Hello World" program. These lessons teach you the fundamentals of the C# language. +This tutorial teaches you C#. You write your first C# program and see the results of compiling and running your code. It contains a series of lessons that begin with a "Hello World" program. These lessons teach you the fundamentals of the C# language. To use codespaces, you need a GitHub account. If you don't already have one, you can create a free account at [GitHub.com](https://github.com). @@ -32,7 +32,7 @@ Your first program printed the `string` "Hello World!" on the screen. > [!TIP] > -> As you explore C# (or any programming language), you make mistakes when you write code. The **compiler** finds those errors and report them to you. When the output contains error messages, look closely at the example code, and the code in your `.cs` file to see what to fix. That exercise helps you learn the structure of C# code. You can also ask Copilot to find differences or spot mistakes. +> As you explore C# (or any programming language), you make mistakes when you write code. The **compiler** finds those errors and reports them to you. When the output contains error messages, look closely at the example code, and the code in your `.cs` file to see what to fix. That exercise helps you learn the structure of C# code. You can also ask Copilot to find differences or spot mistakes. Your first program is limited to printing one message. You can write more useful programs by using *variables*. A *variable* is a symbol you can use to run the same code with different values. Let's try it! Start with the following code: diff --git a/docs/csharp/tour-of-csharp/tutorials/list-collection.md b/docs/csharp/tour-of-csharp/tutorials/list-collection.md index b361864b3a453..5b78c1c30a721 100644 --- a/docs/csharp/tour-of-csharp/tutorials/list-collection.md +++ b/docs/csharp/tour-of-csharp/tutorials/list-collection.md @@ -1,6 +1,6 @@ --- title: Data collections - Introductory tutorial -description: In this tutorial, you use your browser to learn about C# collections. You write C# code and see the results of compiling and running your code directly in the browser. +description: In this tutorial, you use GitHub Codespaces to learn about C# collections. You write C# code and see the results of compiling and running your code in the Codespaces environment. ms.date: 03/07/2025 --- # Learn to manage data collections using List\ in C\# @@ -74,7 +74,7 @@ That creates a list of integers, and sets the first two integers to the value 1. :::code language="csharp" source="./snippets/ListCollection/list.cs" id="Fibonacci"::: -Type `dotnet lists` in the terminal window to see the results. +Type `dotnet lists.cs` in the terminal window to see the results. ## Challenge diff --git a/docs/csharp/tour-of-csharp/tutorials/numbers-in-csharp.md b/docs/csharp/tour-of-csharp/tutorials/numbers-in-csharp.md index 415c9df8eaaf2..97587882808ab 100644 --- a/docs/csharp/tour-of-csharp/tutorials/numbers-in-csharp.md +++ b/docs/csharp/tour-of-csharp/tutorials/numbers-in-csharp.md @@ -32,7 +32,7 @@ Start by exploring those different operations. Add these lines after the line th :::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="OtherOperations"::: -Run this code by typing `dotnet numers.cs` in the terminal window. +Run this code by typing `dotnet numbers.cs` in the terminal window. You can also experiment by writing multiple mathematics operations in the same line, if you'd like. Try `c = a + b - 12 * 17;` for example. Mixing variables and constant numbers is allowed. @@ -149,7 +149,7 @@ void OrderPrecedence() ## Explore integer precision and limits -That last sample showed you that integer division truncates the result. You can get the **remainder** by using the **remaimnder** operator, the `%` character. Try the following code after the method call to `OrderPrecedence()`: +That last sample showed you that integer division truncates the result. You can get the **remainder** by using the **remainder** operator, the `%` character. Try the following code after the method call to `OrderPrecedence()`: :::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="QuotientAndRemainder"::: @@ -195,8 +195,6 @@ You've seen the basic numeric types in C#: integers and doubles. There's one oth :::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="Decimal"::: -There's one other type to learn: the `decimal` type. The `decimal` type has a smaller range but greater precision than `double`. Let's take a look: - Notice that the range is smaller than the `double` type. You can see the greater precision with the decimal type by trying the following code: :::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="Precision"::: @@ -207,7 +205,6 @@ The `M` suffix on the numbers is how you indicate that a constant should use the > [!NOTE] > The letter `M` was chosen as the most visually distinct letter between the `double` and `decimal` keywords. -Notice that the math using the decimal type has more digits to the right of the decimal point. ***Challenge*** diff --git a/docs/csharp/tour-of-csharp/tutorials/pattern-matching.md b/docs/csharp/tour-of-csharp/tutorials/pattern-matching.md index 80062cf7df3c2..63fe13fc932a0 100644 --- a/docs/csharp/tour-of-csharp/tutorials/pattern-matching.md +++ b/docs/csharp/tour-of-csharp/tutorials/pattern-matching.md @@ -84,7 +84,7 @@ To finish this tutorial, let's explore one more building block to pattern matchi :::code language="csharp" source="./snippets/PatternMatching/patterns.cs" id="RecordDeclarations"::: -Next, add this method just before the declaration of the `TransactionType` enumeration. It parses the text and return a series of records: +Next, add this method just before the declaration of the `TransactionType` enumeration. It parses the text and returns a series of records: :::code language="csharp" source="./snippets/PatternMatching/patterns.cs" id="ParseToRecord"::: diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/tuples-types.cs b/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/tuples-types.cs index b88b1f1cebec8..e7d267b7a5f39 100644 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/tuples-types.cs +++ b/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/tuples-types.cs @@ -30,7 +30,7 @@ // Point pt3 = new Point(1, 1); var pt4 = pt3 with { Y = 10 }; -Console.WriteLine($"The two points are {pt} and {pt2}"); +Console.WriteLine($"The two points are {pt3} and {pt4}"); // // diff --git a/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md b/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md index 36f09956890ed..d48bd908c23fb 100644 --- a/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md +++ b/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md @@ -29,6 +29,7 @@ dotnet tuples.cs > [!TIP] > As you explore C# (or any programming language), you make mistakes when you write code. The **compiler** finds those errors and reports them to you. When the output contains error messages, look closely at the example code and your code to see what to fix. You can also ask Copilot to find differences or spot any mistakes. That exercise helps you learn the structure of C# code. +Add the following code after the previous code to modify a tuple member: :::code language="csharp" source="./snippets/TuplesAndTypes/tuples-types.cs" id="Modify"::: You can also create a new tuple that's a modified copy of the original using a `with` expression. Add the following code after the existing code and type `dotnet tuples.cs` in the terminal window to see the results: From e6b4ff994a2c98db0d8861a2b8c1a60beaee2b92 Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Mon, 8 Dec 2025 17:19:18 -0500 Subject: [PATCH 12/13] Fix grammar. --- docs/csharp/tour-of-csharp/tutorials/numbers-in-csharp.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/csharp/tour-of-csharp/tutorials/numbers-in-csharp.md b/docs/csharp/tour-of-csharp/tutorials/numbers-in-csharp.md index 97587882808ab..91da2380a5944 100644 --- a/docs/csharp/tour-of-csharp/tutorials/numbers-in-csharp.md +++ b/docs/csharp/tour-of-csharp/tutorials/numbers-in-csharp.md @@ -167,7 +167,7 @@ There are other numeric types with different limits and precision that you would ## Work with the double type -The `double` numeric type represents a double-precision floating point number. Those terms may be new to you. A **floating point** number is useful to represent non-integral numbers that may be very large or small in magnitude. **Double-precision** is a relative term that describes the number of binary digits used to store the value. **Double precision** numbers have twice the number of binary digits as **single-precision**. On modern computers, it's more common to use double precision than single precision numbers. **Single precision** numbers are declared using the `float` keyword. Let's explore. Add the following code and see the result: +The `double` numeric type represents a double-precision floating point number. Those terms may be new to you. A **floating point** number is useful to represent non-integral numbers that can be very large or small in magnitude. **Double-precision** is a relative term that describes the number of binary digits used to store the value. **Double precision** numbers have twice the number of binary digits as **single-precision**. On modern computers, it's more common to use double precision than single precision numbers. **Single precision** numbers are declared using the `float` keyword. Let's explore. Add the following code and see the result: :::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="FloatingPoint"::: From 4695033764d84a69b19a53fc756f98cbc1a4ebba Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Mon, 8 Dec 2025 17:39:45 -0500 Subject: [PATCH 13/13] Final grammar check --- .../tutorials/branches-and-loops.md | 30 +++++++-------- .../tour-of-csharp/tutorials/hello-world.md | 20 +++++----- docs/csharp/tour-of-csharp/tutorials/index.md | 14 +++---- .../tutorials/list-collection.md | 16 ++++---- .../tutorials/numbers-in-csharp.md | 38 +++++++++---------- .../tutorials/pattern-matching.md | 22 +++++------ .../tutorials/tuples-and-types.md | 16 ++++---- 7 files changed, 78 insertions(+), 78 deletions(-) diff --git a/docs/csharp/tour-of-csharp/tutorials/branches-and-loops.md b/docs/csharp/tour-of-csharp/tutorials/branches-and-loops.md index 06df3656c1351..d1d6f97cc2bac 100644 --- a/docs/csharp/tour-of-csharp/tutorials/branches-and-loops.md +++ b/docs/csharp/tour-of-csharp/tutorials/branches-and-loops.md @@ -9,11 +9,11 @@ This tutorial teaches you how to write C# code that examines variables and chang To use codespaces, you need a GitHub account. If you don't already have one, you can create a free account at [GitHub.com](https://github.com). -Open a browser window to [GitHub codespaces](https://github.com/codespaces). Create a new codespace from the *.NET Template*. If you've done other tutorials in this series, you can open that codespace. Once your codespace loads, create a new file in the *tutorials* folder named *branches-loops.cs*. Open your new file. Type or copy the following code into *branches-loops.cs*: +Open a browser window to [GitHub codespaces](https://github.com/codespaces). Create a new codespace from the *.NET Template*. If you completed other tutorials in this series, you can open that codespace. Once your codespace loads, create a new file in the *tutorials* folder named *branches-loops.cs*. Open your new file. Type or copy the following code into *branches-loops.cs*: :::code language="csharp" source="./snippets/BranchesAndLoops/branches-loops.cs" id="FirstIf"::: -Try this code by typing the following in the integrated terminal: +Try this code by typing the following command in the integrated terminal: ```dotnetcli cd tutorials @@ -26,10 +26,10 @@ You should see the message "The answer is greater than 10." printed to your cons int b = 3; ``` -Type `dotnet branches-loops.cs` again in the terminal window. Because the answer is less than 10, nothing is printed. The **condition** you're testing is false. You don't have any code to execute because you've only written one of the possible branches for an `if` statement: the true branch. +Type `dotnet branches-loops.cs` again in the terminal window. Because the answer is less than 10, nothing is printed. The **condition** you're testing is false. You don't have any code to execute because you only wrote one of the possible branches for an `if` statement: the true branch. > [!TIP] -> As you explore C# (or any programming language), you'll make mistakes when you write code. The compiler will find and report the errors. Look closely at the error output and the code that generated the error. You can also ask Copilot to find differences or spot any mistakes. The compiler error can usually help you find the problem. +> As you explore C# (or any programming language), you might make mistakes when you write code. The compiler finds and reports the errors. Look closely at the error output and the code that generated the error. You can also ask Copilot to find differences or spot any mistakes. The compiler error can usually help you find the problem. This first sample shows the power of `if` and Boolean types. A *Boolean* is a variable that can have one of two values: `true` or `false`. C# defines a special type, `bool` for Boolean variables. The `if` statement checks the value of a `bool`. When the value is `true`, the statement following the `if` executes. Otherwise, it's skipped. This process of checking conditions and executing statements based on those conditions is powerful. Let's explore more. @@ -51,7 +51,7 @@ Because indentation isn't significant, you need to use `{` and `}` to indicate w > [!TIP] > Through the rest of this tutorial, the code samples all include the braces, following accepted practices. -You can test more complicated conditions. Add the following code after the code you've written so far: +You can test more complicated conditions. Add the following code after the code you wrote so far: :::code language="csharp" source="./snippets/BranchesAndLoops/branches-loops.cs" id="ComplexConditions"::: @@ -59,17 +59,17 @@ The `==` symbol tests for *equality*. Using `==` distinguishes the test for equa The `&&` represents "and". It means both conditions must be true to execute the statement in the true branch. These examples also show that you can have multiple statements in each conditional branch, provided you enclose them in `{` and `}`. -You can also use `||` to represent "or". Add the following code after what you've written so far: +You can also use `||` to represent "or". Add the following code after what you wrote so far: :::code language="csharp" source="./snippets/BranchesAndLoops/branches-loops.cs" id="UseOr"::: Modify the values of `a`, `b`, and `c` and switch between `&&` and `||` to explore. You gain more understanding of how the `&&` and `||` operators work. -You finished the first step. Before you start the next section, let's move the current code into a separate method. That makes it easier to start working with a new example. Put the existing code in a method called `ExploreIf()`. Call it from the top of your program. When you finished those changes, your code should look like the following: +You finished the first step. Before you start the next section, let's move the current code into a separate method. That makes it easier to start working with a new example. Put the existing code in a method called `ExploreIf()`. Call it from the top of your program. When you finished those changes, your code should look like the following code: :::code language="csharp" source="./snippets/BranchesAndLoops/branches-loops.cs" id="Refactor"::: -Comment out the call to `ExploreIf()`. It will make the output less cluttered as you work in this section: +Comment out the call to `ExploreIf()`. It makes the output less cluttered as you work in this section: ```csharp //ExploreIf(); @@ -79,7 +79,7 @@ The `//` starts a **comment** in C#. Comments are any text you want to keep in y ## Use loops to repeat operations -Another important concept to create larger programs is **loops**. You use loops to repeat statements that you want executed more than once. Add this code after the call to `ExploreIf`: +Another important concept for creating larger programs is **loops**. Use loops to repeat statements that you want to execute more than once. Add this code after the call to `ExploreIf`: :::code language="csharp" source="./snippets/BranchesAndLoops/branches-loops.cs" id="WhileLoop"::: @@ -88,7 +88,7 @@ The `while` statement checks a condition and executes the statement following th There's one other new operator in this example. The `++` after the `counter` variable is the **increment** operator. It adds 1 to the value of `counter` and stores that value in the `counter` variable. > [!IMPORTANT] -> Make sure that the `while` loop condition changes to false as you execute the code. Otherwise, you create an **infinite loop** where your program never ends. That is not demonstrated in this sample, because you have to force your program to quit using **CTRL-C** or other means. +> Make sure that the `while` loop condition changes to false as you execute the code. Otherwise, you create an **infinite loop** where your program never ends. That behavior isn't demonstrated in this sample, because you have to force your program to quit by using **CTRL-C** or other means. The `while` loop tests the condition before executing the code following the `while`. The `do` ... `while` loop executes the code first, and then checks the condition. The *do while* loop is shown in the following code: @@ -117,17 +117,17 @@ Experiment with these conditions yourself. Try each of the following changes: When you're done, let's move on to write some code yourself to use what you learned. -There's one other looping statement that isn't covered in this tutorial: the `foreach` statement. The `foreach` statement repeats its statement for every item in a sequence of items. It's most often used with *collections*. It's covered in the next tutorial. +There's one other looping statement that isn't covered in this tutorial: the `foreach` statement. The `foreach` statement repeats its statement for every item in a sequence of items. You most often use it with *collections*. It's covered in the next tutorial. ## Created nested loops -A `while`, `do`, or `for` loop can be nested inside another loop to create a matrix using the combination of each item in the outer loop with each item in the inner loop. Let's do that to build a set of alphanumeric pairs to represent rows and columns. +You can nest a `while`, `do`, or `for` loop inside another loop to create a matrix by combining each item in the outer loop with each item in the inner loop. Let's build a set of alphanumeric pairs to represent rows and columns. -One `for` loop can generate the rows: +One `for` loop generates the rows: :::code language="csharp" source="./snippets/BranchesAndLoops/branches-loops.cs" id="Rows"::: -Another loop can generate the columns: +Another loop generates the columns: :::code language="csharp" source="./snippets/BranchesAndLoops/branches-loops.cs" id="Columns"::: @@ -135,7 +135,7 @@ You can nest one loop inside the other to form pairs: :::code language="csharp" source="./snippets/BranchesAndLoops/branches-loops.cs" id="Nested"::: -You can see that the outer loop increments once for each full run of the inner loop. Reverse the row and column nesting, and see the changes for yourself. When you're done, place the code from this section in a method called `ExploreLoops()`. +The outer loop increments once for each full run of the inner loop. Reverse the row and column nesting, and see the changes for yourself. When you're done, place the code from this section in a method called `ExploreLoops()`. ## Combine branches and loops diff --git a/docs/csharp/tour-of-csharp/tutorials/hello-world.md b/docs/csharp/tour-of-csharp/tutorials/hello-world.md index 03fe92dcd390a..4c95e6da006f0 100644 --- a/docs/csharp/tour-of-csharp/tutorials/hello-world.md +++ b/docs/csharp/tour-of-csharp/tutorials/hello-world.md @@ -22,17 +22,17 @@ cd tutorials dotnet hello-world.cs ``` -Congratulations! You ran your first C# program. It's a simple program that prints the message "Hello World!" It used the method to print that message. `Console` is a type that represents the console window. `WriteLine` is a method of the `Console` type that prints a line of text to that text console. +You ran your first C# program. It's a simple program that prints the message "Hello World!" It uses the method to print that message. `Console` is a type that represents the console window. `WriteLine` is a method of the `Console` type that prints a line of text to that text console. Let's move on and explore more. The rest of this lesson explores working with the `string` type, which represents text in C#. Like the `Console` type, the `string` type has methods. The `string` methods work with text. ## Declare and use variables -Your first program printed the `string` "Hello World!" on the screen. +Your first program prints the `string` "Hello World!" on the screen. > [!TIP] > -> As you explore C# (or any programming language), you make mistakes when you write code. The **compiler** finds those errors and reports them to you. When the output contains error messages, look closely at the example code, and the code in your `.cs` file to see what to fix. That exercise helps you learn the structure of C# code. You can also ask Copilot to find differences or spot mistakes. +> As you explore C# (or any programming language), you make mistakes when you write code. The **compiler** finds those errors and reports them to you. When the output contains error messages, look closely at the example code and the code in your `.cs` file to see what to fix. That exercise helps you learn the structure of C# code. You can also ask Copilot to find differences or spot mistakes. Your first program is limited to printing one message. You can write more useful programs by using *variables*. A *variable* is a symbol you can use to run the same code with different values. Let's try it! Start with the following code: @@ -49,7 +49,7 @@ You can assign different values to any variable you declare. You can change the Notice that the same line of code prints two different messages, based on the value stored in the `aFriend` variable. -You might notice that the word "Hello" was missing in the last two messages. Let's fix that now. Modify the lines that print the message to the following code: +You might notice that the word "Hello" is missing in the last two messages. Let's fix that now. Modify the lines that print the message to the following code: :::code language="csharp" source="./snippets/HelloWorld/hello-world.cs" id="ConcatMessage"::: @@ -67,13 +67,13 @@ Run the app again using `dotnet hello-world.cs` to see the results. Instead of " ## Work with strings -Your last edit was our first look at what you can do with strings. Let's explore more. +Your last edit was your first look at what you can do with strings. Let's explore more. You're not limited to a single variable between the curly braces. Try the following code at the bottom of your app: :::code language="csharp" source="./snippets/HelloWorld/hello-world.cs" id="WorkWithStrings"::: -Strings are more than a collection of letters. You can find the length of a string using `Length`. `Length` is a **property** of a string and it returns the number of characters in that string. Add the following code at the bottom of your app: +Strings are more than a collection of letters. You can find the length of a string by using `Length`. `Length` is a **property** of a string and it returns the number of characters in that string. Add the following code at the bottom of your app: :::code language="csharp" source="./snippets/HelloWorld/hello-world.cs" id="Properties"::: @@ -96,11 +96,11 @@ This sample reinforces a couple of important concepts for working with strings. ## Replace -There are other methods available to work with a string. For example, you probably used a search and replace command in an editor or word processor before. The method does something similar in a string. It searches for a substring and replaces it with different text. The method takes two **parameters**. These parameters are the strings between the parentheses. The first string is the text to search for. The second string is the text to replace it with. Try it for yourself. Add this code. Type it in to see the hints as you start typing `.Re` after the `sayHello` variable: +You can use other methods to work with a string. For example, you might have used a search and replace command in an editor or word processor. The method does something similar in a string. It searches for a substring and replaces it with different text. The method takes two **parameters**. These parameters are the strings between the parentheses. The first string is the text to search for. The second string is the text to replace it with. Try it for yourself. Add this code. Type it in to see the hints as you start typing `.Re` after the `sayHello` variable: :::code language="csharp" source="./snippets/HelloWorld/hello-world.cs" id="Replace"::: -Two other useful methods make a string ALL CAPS or all lower case. Try the following code. Type it in to see how **IntelliSense** provides hints as you start to type `To`: +Two other useful methods make a string all caps or all lowercase. Try the following code. Type it in to see how **IntelliSense** provides hints as you start to type `To`: :::code language="csharp" source="./snippets/HelloWorld/hello-world.cs" id="UpperLower"::: @@ -114,7 +114,7 @@ The method returns a *boolean* value which tell ## Challenge -There are two similar methods, and that also search for substrings in a string. These methods find a substring at the beginning or the end of the string. Try to modify the previous sample to use and instead of . Search for "You" or "goodbye" at the beginning of a string. Search for "hello" or "goodbye" at the end of a string. +Two similar methods, and , also search for substrings in a string. These methods find a substring at the beginning or the end of the string. Try to modify the previous sample to use and instead of . Search for "You" or "goodbye" at the beginning of a string. Search for "hello" or "goodbye" at the end of a string. > [!NOTE] > @@ -122,7 +122,7 @@ There are two similar methods, and
diff --git a/docs/csharp/tour-of-csharp/tutorials/index.md b/docs/csharp/tour-of-csharp/tutorials/index.md index 16f89327b7ab0..3deb836f616e7 100644 --- a/docs/csharp/tour-of-csharp/tutorials/index.md +++ b/docs/csharp/tour-of-csharp/tutorials/index.md @@ -10,29 +10,29 @@ Welcome to the introduction to C# tutorials. These lessons start with interactiv > [!VIDEO https://www.youtube.com/embed/9THmGiSPjBQ?si=3kUKFtOMLpEzeq7J] -The first lessons explain C# concepts using small snippets of code. You'll learn the basics of C# syntax and how to work with data types like strings, numbers, and booleans. It's all interactive, and you'll be writing and running code within minutes. These first lessons assume no prior knowledge of programming or the C# language. Each lesson builds on the prior lessons. You should do them in order. However, if you have some programming experience, you can skip or skim the first lessons and start with any new concepts. +The first lessons explain C# concepts using small snippets of code. You learn the basics of C# syntax and how to work with data types like strings, numbers, and booleans. It's all interactive, and you'll be writing and running code within minutes. These first lessons assume no prior knowledge of programming or the C# language. Each lesson builds on the prior lessons. You should do them in order. However, if you have some programming experience, you can skip or skim the first lessons and start with any new concepts. To use GitHub codespaces, you need to create a free [GitHub](https://github.com) account. ## Hello world -In the [Hello world](hello-world.md) tutorial, you'll create the most basic C# program. You'll explore the `string` type and how to work with text. +In the [Hello world](hello-world.md) tutorial, you create the most basic C# program. You explore the `string` type and how to work with text. ## Numbers in C\# -In the [Numbers in C#](numbers-in-csharp.md) tutorial, you'll learn how computers store numbers and how to perform calculations with different numeric types. You'll learn the basics of rounding, and how to perform mathematical calculations using C#. +In the [Numbers in C#](numbers-in-csharp.md) tutorial, you learn how computers store numbers and how to perform calculations with different numeric types. You learn the basics of rounding, and how to perform mathematical calculations using C#. ## Tuples and types -In the [Tuples and types](tuples-and-types.md) tutorial, you'll learn to create types in C#. You can create *tuples*, *records*, *struct*, and *class* types. The capabilities of these different kinds of types reflect their different uses. +In the [Tuples and types](tuples-and-types.md) tutorial, you learn to create types in C#. You can create *tuples*, *records*, *struct*, and *class* types. The capabilities of these different kinds of types reflect their different uses. ## Branches and loops -The [Branches and loops](branches-and-loops.md) tutorial teaches the basics of selecting different paths of code execution based on the values stored in variables. You'll learn the basics of control flow, which is the basis of how programs make decisions and choose different actions. +The [Branches and loops](branches-and-loops.md) tutorial teaches the basics of selecting different paths of code execution based on the values stored in variables. You learn the basics of control flow, which is the basis of how programs make decisions and choose different actions. ## List collection -The [List collection](list-collection.md) lesson gives you a tour of the List collection type that stores sequences of data. You'll learn how to add and remove items, search for items, and sort the lists. You'll explore different kinds of lists. +The [List collection](list-collection.md) lesson gives you a tour of the List collection type that stores sequences of data. You learn how to add and remove items, search for items, and sort the lists. You explore different kinds of lists. ## Pattern matching @@ -40,6 +40,6 @@ The [Pattern matching](pattern-matching.md) lesson provides an introduction to * ## Set up your local environment -After you finish these tutorials, set up a development environment. You'll want: +After you finish these tutorials, set up a development environment. You need: [!INCLUDE [Prerequisites](../../../../includes/prerequisites-basic-winget.md)] diff --git a/docs/csharp/tour-of-csharp/tutorials/list-collection.md b/docs/csharp/tour-of-csharp/tutorials/list-collection.md index 5b78c1c30a721..2ac2e70d7141b 100644 --- a/docs/csharp/tour-of-csharp/tutorials/list-collection.md +++ b/docs/csharp/tour-of-csharp/tutorials/list-collection.md @@ -13,18 +13,18 @@ To use codespaces, you need a GitHub account. If you don't already have one, you ## A basic list example -Open a browser window to [GitHub codespaces](https://github.com/codespaces). Create a new codespace from the *.NET Template*. If you've done other tutorials in this series, you can open that codespace. Once your codespace loads, create a new file in the *tutorials* folder named *lists.cs*. Open your new file. Type or copy the following code into *lists.cs*: +Open a browser window to [GitHub codespaces](https://github.com/codespaces). Create a new codespace from the *.NET Template*. If you completed other tutorials in this series, you can open that codespace. Once your codespace loads, create a new file in the *tutorials* folder named *lists.cs*. Open your new file. Type or copy the following code into *lists.cs*: :::code language="csharp" source="./snippets/ListCollection/list.cs" id="BasicList"::: -Run the code by typing the following in the terminal window: +Run the code by typing the following command in the terminal window: ```dotnetcli cd tutorials dotnet lists.cs ``` -You created a list of strings, added three names to that list, and printed the names in all CAPS. You're using concepts that you learned in earlier tutorials to loop through the list. +You created a list of strings, added three names to that list, and printed the names in all caps. You're using concepts that you learned in earlier tutorials to loop through the list. The code to display names makes use of the [string interpolation](../../language-reference/tokens/interpolated.md) feature. When you precede a `string` with the `$` character, you can embed C# code in the string declaration. The actual string replaces that C# code with the value it generates. In this example, it replaces the `{name.ToUpper()}` with each name, converted to capital letters, because you called the method. @@ -44,7 +44,7 @@ The enables you to reference individu :::code language="csharp" source="./snippets/ListCollection/list.cs" id="Indexers"::: -You're not allowed to access past the end of the list. You can check how long the list is using the property. Add the following code: +You're not allowed to access past the end of the list. You can check how long the list is by using the property. Add the following code: :::code language="csharp" source="./snippets/ListCollection/list.cs" id="Property"::: @@ -60,17 +60,17 @@ Our samples use relatively small lists, but your applications might often create You might not know if an item is in the list, so you should always check the index returned by . If it's `-1`, the item wasn't found. -The items in your list can be sorted as well. The method sorts all the items in the list in their normal order (alphabetically for strings). Add this code and run again: +You can also sort the items in your list. The method sorts all the items in the list in their normal order (alphabetically for strings). Add this code and run again: :::code language="csharp" source="./snippets/ListCollection/list.cs" id="Sort"::: ## Lists of other types -You've been using the `string` type in lists so far. Let's make a using a different type. Let's build a set of numbers. Add the following code at the end of your source file: +So far, you've been using the `string` type in lists. Let's make a using a different type. Let's build a set of numbers. Add the following code at the end of your source file: :::code language="csharp" source="./snippets/ListCollection/list.cs" id="CreateList"::: -That creates a list of integers, and sets the first two integers to the value 1. The *Fibonacci Sequence*, a sequence of numbers, starts with two 1's. Each next Fibonacci number is found by taking the sum of the previous two numbers. Add this code: +That code creates a list of integers and sets the first two integers to the value 1. The *Fibonacci Sequence*, a sequence of numbers, starts with two 1's. Each next Fibonacci number is found by taking the sum of the previous two numbers. Add this code: :::code language="csharp" source="./snippets/ListCollection/list.cs" id="Fibonacci"::: @@ -87,7 +87,7 @@ Did you come up with something like this? :::code language="csharp" source="./snippets/ListCollection/list.cs" id="Answer"::: -With each iteration of the loop, you're taking the last two integers in the list, summing them, and adding that value to the list. The loop repeats until you added 20 items to the list. +With each iteration of the loop, you take the last two integers in the list, sum them, and add that value to the list. The loop repeats until you add 20 items to the list.
diff --git a/docs/csharp/tour-of-csharp/tutorials/numbers-in-csharp.md b/docs/csharp/tour-of-csharp/tutorials/numbers-in-csharp.md index 91da2380a5944..2b486a25e0fb4 100644 --- a/docs/csharp/tour-of-csharp/tutorials/numbers-in-csharp.md +++ b/docs/csharp/tour-of-csharp/tutorials/numbers-in-csharp.md @@ -11,7 +11,7 @@ To use codespaces, you need a GitHub account. If you don't already have one, you ## Explore integer math -Open a browser window to [GitHub codespaces](https://github.com/codespaces). Create a new codespace from the *.NET Template*. If you've done the [hello world](./hello-world.md) tutorial, you can open that codespace. Once your codespace loads, create a new file in the *tutorials* folder named *numbers.cs*. Open your new file. Type or copy the following code into *numbers.cs*: +Open a browser window to [GitHub codespaces](https://github.com/codespaces). Create a new codespace from the *.NET Template*. If you complete the [hello world](./hello-world.md) tutorial, you can open that codespace. When your codespace loads, create a new file in the *tutorials* folder named *numbers.cs*. Open your new file. Type or copy the following code into *numbers.cs*: :::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="Addition"::: @@ -22,7 +22,7 @@ cd ./tutorials dotnet numbers.cs ``` -You've seen one of the fundamental math operations with integers. The `int` type represents an **integer**, a zero, positive, or negative whole number. You use the `+` symbol for addition. Other common mathematical operations for integers include: +You saw one of the fundamental math operations with integers. The `int` type represents an **integer**, a zero, positive, or negative whole number. You use the `+` symbol for addition. Other common mathematical operations for integers include: - `-` for subtraction - `*` for multiplication @@ -37,9 +37,9 @@ Run this code by typing `dotnet numbers.cs` in the terminal window. You can also experiment by writing multiple mathematics operations in the same line, if you'd like. Try `c = a + b - 12 * 17;` for example. Mixing variables and constant numbers is allowed. > [!TIP] -> As you explore C# (or any programming language), you'll make mistakes when you write code. The **compiler** will find those errors and report them to you. When the output contains error messages, look closely at the example code and the code in your window to see what to fix. You can also ask Copilot to find differences or spot mistakes. That exercise will help you learn the structure of C# code. +> As you explore C# (or any programming language), you might make mistakes when you write code. The **compiler** finds those errors and reports them to you. When the output contains error messages, look closely at the example code and the code in your window to see what to fix. You can also ask Copilot to find differences or spot mistakes. That exercise helps you learn the structure of C# code. -You've finished the first step. Before you start the next section, let's move the current code into a separate *method*. A method is a series of statements grouped together and given a name. You call a method by writing the method's name followed by `()`. Organizing your code into methods makes it easier to start working with a new example. When you finish, your code should look like this: +You finished the first step. Before you start the next section, let's move the current code into a separate *method*. A method is a series of statements grouped together and given a name. You call a method by writing the method's name followed by `()`. Organizing your code into methods makes it easier to start working with a new example. When you finish, your code should look like this: ```csharp WorkWithIntegers(); @@ -68,7 +68,7 @@ void WorkWithIntegers() ## Explore order of operations -Comment out the call to `WorkingWithIntegers()`. It will make the output less cluttered as you work in this section: +Comment out the call to `WorkingWithIntegers()`. It makes the output less cluttered as you work in this section: ```csharp //WorkWithIntegers(); @@ -90,15 +90,15 @@ Explore more by combining many different operations. Add something like the foll :::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="CompoundExpression"::: -You may have noticed an interesting behavior for integers. Integer division always produces an integer result, even when you'd expect the result to include a decimal or fractional portion. +You might notice an interesting behavior for integers. Integer division always produces an integer result, even when you'd expect the result to include a decimal or fractional portion. -If you haven't seen this behavior, try the following code: +If you didn't see this behavior, try the following code: :::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="Truncation"::: Type `dotnet numbers` again in the terminal window to see the results. -Before moving on, let's take all the code you've written in this section and put it in a new method. Call that new method `OrderPrecedence`. Your code should look something like this: +Before moving on, let's take all the code you wrote in this section and put it in a new method. Call that new method `OrderPrecedence`. Your code should look something like this: ```csharp // WorkWithIntegers(); @@ -149,7 +149,7 @@ void OrderPrecedence() ## Explore integer precision and limits -That last sample showed you that integer division truncates the result. You can get the **remainder** by using the **remainder** operator, the `%` character. Try the following code after the method call to `OrderPrecedence()`: +The previous sample showed that integer division truncates the result. You can get the **remainder** by using the **remainder** operator, the `%` character. Try the following code after the method call to `OrderPrecedence()`: :::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="QuotientAndRemainder"::: @@ -163,11 +163,11 @@ If a calculation produces a value that exceeds those limits, you have an **under Notice that the answer is very close to the minimum (negative) integer. It's the same as `min + 2`. The addition operation **overflowed** the allowed values for integers. The answer is a large negative number because an overflow "wraps around" from the largest possible integer value to the smallest. -There are other numeric types with different limits and precision that you would use when the `int` type doesn't meet your needs. Let's explore those types of numbers next. +There are other numeric types with different limits and precision that you can use when the `int` type doesn't meet your needs. Let's explore those types of numbers next. ## Work with the double type -The `double` numeric type represents a double-precision floating point number. Those terms may be new to you. A **floating point** number is useful to represent non-integral numbers that can be very large or small in magnitude. **Double-precision** is a relative term that describes the number of binary digits used to store the value. **Double precision** numbers have twice the number of binary digits as **single-precision**. On modern computers, it's more common to use double precision than single precision numbers. **Single precision** numbers are declared using the `float` keyword. Let's explore. Add the following code and see the result: +The `double` numeric type represents a double-precision floating point number. Those terms might be new to you. A **floating point** number is useful for representing non-integral numbers that can be very large or small in magnitude. **Double-precision** is a relative term that describes the number of binary digits used to store the value. **Double precision** numbers have twice the number of binary digits as **single-precision**. On modern computers, you more commonly use double precision than single precision numbers. **Single precision** numbers are declared by using the `float` keyword. Let's explore. Add the following code and see the result: :::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="FloatingPoint"::: @@ -175,7 +175,7 @@ Notice that the answer includes the decimal portion of the quotient. Try a sligh :::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="ChangeDoubleValues"::: -The range of a double value is much greater than integer values. Try the following code below what you've written so far: +The range of a double value is much greater than integer values. Try the following code that you add to what you've written so far: :::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="MinMax"::: @@ -187,11 +187,11 @@ You know that `0.3` is `3/10` and not exactly the same as `1/3`. Similarly, `0.3 ***Challenge*** -Try other calculations with large numbers, small numbers, multiplication, and division using the `double` type. Try more complicated calculations. After you've spent some time with the challenge, take the code you've written and place it in a new method. Name that new method `WorkWithDoubles`. +Try other calculations with large numbers, small numbers, multiplication, and division by using the `double` type. Try more complicated calculations. After you spend some time with the challenge, take the code you wrote and place it in a new method. Name that new method `WorkWithDoubles`. ## Work with decimal types -You've seen the basic numeric types in C#: integers and doubles. There's one other type to learn: the `decimal` type. The `decimal` type has a smaller range but greater precision than `double`. Let's take a look: +You saw the basic numeric types in C#: integers and doubles. There's one other type to learn: the `decimal` type. The `decimal` type has a smaller range but greater precision than `double`. Let's take a look: :::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="Decimal"::: @@ -199,20 +199,20 @@ Notice that the range is smaller than the `double` type. You can see the greater :::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="Precision"::: -Notice that the math using the decimal type has more digits to the right of the decimal point. +Notice that the math with the decimal type has more digits to the right of the decimal point. -The `M` suffix on the numbers is how you indicate that a constant should use the `decimal` type. Otherwise, the compiler assumes the `double` type. +The `M` suffix on the numbers indicates that a constant should use the `decimal` type. Otherwise, the compiler assumes the `double` type. > [!NOTE] -> The letter `M` was chosen as the most visually distinct letter between the `double` and `decimal` keywords. +> The letter `M` is the most visually distinct letter between the `double` and `decimal` keywords. ***Challenge*** -Now that you've seen the different numeric types, write code that calculates the area of a circle whose radius is 2.50 centimeters. Remember that the area of a circle is the radius squared multiplied by PI. One hint: .NET contains a constant for PI, that you can use for that value. , like all constants declared in the `System.Math` namespace, is a `double` value. For that reason, you should use `double` instead of `decimal` values for this challenge. +Now that you know the different numeric types, write code that calculates the area of a circle whose radius is 2.50 centimeters. Remember that the area of a circle is the radius squared multiplied by PI. One hint: .NET contains a constant for PI, that you can use for that value. , like all constants declared in the `System.Math` namespace, is a `double` value. For that reason, you should use `double` instead of `decimal` values for this challenge. You should get an answer between 19 and 20. -Once you try it, open the details pane to see how you did: +When you try it, open the details pane to see how you did:
diff --git a/docs/csharp/tour-of-csharp/tutorials/pattern-matching.md b/docs/csharp/tour-of-csharp/tutorials/pattern-matching.md index 63fe13fc932a0..60c3e8a364e8f 100644 --- a/docs/csharp/tour-of-csharp/tutorials/pattern-matching.md +++ b/docs/csharp/tour-of-csharp/tutorials/pattern-matching.md @@ -9,28 +9,28 @@ This tutorial teaches you how to use pattern matching to inspect data in C#. You To use codespaces, you need a GitHub account. If you don't already have one, you can create a free account at [GitHub.com](https://github.com). -The preceding tutorials demonstrated built-in types and types you define as tuples or records. Instances of these types can be checked against a *pattern*. Whether an instance matches a pattern determines the actions your program takes. In the examples below, you'll notice `?` after type names. This symbol allows the value of this type to be null (for example, `bool?` can be `true`, `false` or `null`). For more information, see [Nullable value types](../../language-reference/builtin-types/nullable-value-types.md). Let's start to explore how you can use patterns. +The preceding tutorials demonstrated built-in types and types you define as tuples or records. You can check instances of these types against a *pattern*. Whether an instance matches a pattern determines the actions your program takes. In the examples below, you see `?` after type names. This symbol allows the value of this type to be null (for example, `bool?` can be `true`, `false`, or `null`). For more information, see [Nullable value types](../../language-reference/builtin-types/nullable-value-types.md). Let's start to explore how you can use patterns. -Open a browser window to [GitHub codespaces](https://github.com/codespaces). Create a new codespace from the *.NET Template*. If you've done other tutorials in this series, you can open that codespace. Once your codespace loads, create a new file in the *tutorials* folder named *patterns.cs*. Open your new file. +Open a browser window to [GitHub codespaces](https://github.com/codespaces). Create a new codespace from the *.NET Template*. If you completed other tutorials in this series, you can open that codespace. Once your codespace loads, create a new file in the *tutorials* folder named *patterns.cs*. Open your new file. ## Match a value -All the examples in this tutorial use text input that represents a series of bank transactions as comma separated values (CSV) input. In each of the samples you can match the record against a pattern using either an `is` or `switch` expression. This first example splits each line on the `,` character and then *matches* the first string field against the value "DEPOSIT" or "WITHDRAWAL" using an `is` expression. When it matches, the transaction amount is added or deducted from the current account balance. To see it work, add the following code to *patterns.cs*: +All the examples in this tutorial use text input that represents a series of bank transactions as comma separated values (CSV) input. In each of the samples, you can match the record against a pattern by using either an `is` or `switch` expression. This first example splits each line on the `,` character and then *matches* the first string field against the value "DEPOSIT" or "WITHDRAWAL" by using an `is` expression. When it matches, the transaction amount is added or deducted from the current account balance. To see it work, add the following code to *patterns.cs*: :::code language="csharp" source="./snippets/PatternMatching/patterns.cs" id="FirstExample"::: -Then, type the following in the terminal window: +Then, type the following text in the terminal window: ```dotnetcli cd tutorials dotnet patterns.cs ``` -Examine the output. You can see that each line is processed by comparing the value of the text in the first field. The preceding sample could be similarly constructed using the `==` operator to test that two `string` values are equal. Comparing a variable to a constant is a basic building block for pattern matching. Let's explore more of the building blocks that are part of pattern matching. +Examine the output. You can see that each line is processed by comparing the value of the text in the first field. You could similarly construct the preceding sample by using the `==` operator to test that two `string` values are equal. Comparing a variable to a constant is a basic building block for pattern matching. Let's explore more of the building blocks that are part of pattern matching. ## Enum matches -Another common use for pattern matching is to match on the values of an `enum` type. This next sample processes the input records to create a *tuple* where the first value is an `enum` value that notes a deposit or a withdrawal. The second value is the value of the transaction. Add the following code to the end of your source file. It defines the `TransactionType` enumeration: +Another common use for pattern matching is matching on the values of an `enum` type. The following sample processes the input records to create a *tuple* where the first value is an `enum` value that notes a deposit or a withdrawal. The second value is the value of the transaction. Add the following code to the end of your source file. It defines the `TransactionType` enumeration: :::code language="csharp" source="./snippets/PatternMatching/patterns.cs" id="TransactionTypeEnum"::: @@ -38,7 +38,7 @@ Next, add a function to parse a bank transaction into a tuple that holds the tra :::code language="csharp" source="./snippets/PatternMatching/patterns.cs" id="ParseTransaction"::: -Next, add a new loop to process the transaction data using the `TransactionType` enumeration you declared: +Next, add a new loop to process the transaction data by using the `TransactionType` enumeration you declared: :::code language="csharp" source="./snippets/PatternMatching/patterns.cs" id="EnumPatternMatch"::: @@ -46,7 +46,7 @@ The preceding example also uses an `if` statement to check the value of an `enum ## Exhaustive matches with `switch` -A series of `if` statements can test a series of conditions. But, the compiler can't tell if a series of `if` statements are *exhaustive* or if later `if` conditions are *subsumed* by earlier conditions. *Exhaustive* means that all possible inputs are handled by one of the `if` or `else` clauses in the series of tests. If a series of `if` statements are exhaustive, every possible input satisfies at least one `if` or `else` clause. *Subsumption* means that a later `if` or `else` clause can't be reached because earlier `if` or `else` clauses match all possible inputs. For example, in the following example code, one clause never matches: +A series of `if` statements can test a series of conditions. But, the compiler can't tell if a series of `if` statements are *exhaustive* or if later `if` conditions are *subsumed* by earlier conditions. *Exhaustive* means that one of the `if` or `else` clauses in the series of tests handles all possible inputs. If a series of `if` statements are exhaustive, every possible input satisfies at least one `if` or `else` clause. *Subsumption* means that a later `if` or `else` clause can't be reached because earlier `if` or `else` clauses match all possible inputs. For example, in the following example code, one clause never matches: ```csharp int n = GetNumber(); @@ -59,7 +59,7 @@ else Console.WriteLine("n is greater than 20"); ``` -The `else if` clause never matches because every number less than 10 is also less than 20. The `switch` expression ensures both of those characteristics are met, which results in fewer bugs in your apps. Let's try it and experiment. Copy the following code. Replace the two `if` statements in your `foreach` loop with the `switch` expression you copied. After you've modified the code, type `dotnet patterns.cs` in the terminal window to run the new sample. +The `else if` clause never matches because every number less than 10 is also less than 20. The `switch` expression ensures both of those characteristics are met, which results in fewer bugs in your apps. Let's try it and experiment. Copy the following code. Replace the two `if` statements in your `foreach` loop with the `switch` expression you copied. After you modify the code, type `dotnet patterns.cs` in the terminal window to run the new sample. :::code language="csharp" source="./snippets/PatternMatching/patterns.cs" id="SwitchEnumValue"::: @@ -76,7 +76,7 @@ currentBalance += transaction switch After you reorder the switch arms, type `dotnet patterns.cs` in the terminal window. The compiler issues an error because the arm with `_` matches every value. As a result, that final arm with `TransactionType.Withdrawal` never runs. The compiler tells you that something's wrong in your code. -The compiler issues a warning if the expression tested in a `switch` expression could contain values that don't match any switch arm. If some values could fail to match any condition, the `switch` expression isn't *exhaustive*. The compiler also issues a warning if some values of the input don't match any of the switch arms. For example, if you remove the line with `_ => 0.0,`, any invalid values don't match. At run time, that would fail. Once you install the .NET SDK and build programs in your environment, you can test this behavior. The online experience doesn't display warnings in the output window. +The compiler issues a warning if the expression tested in a `switch` expression could contain values that don't match any switch arm. If some values could fail to match any condition, the `switch` expression isn't *exhaustive*. The compiler also issues a warning if some values of the input don't match any of the switch arms. For example, if you remove the line with `_ => 0.0,`, any invalid values don't match. At run time, that failure would occur. Once you install the .NET SDK and build programs in your environment, you can test this behavior. The online experience doesn't display warnings in the output window. ## Type patterns @@ -94,7 +94,7 @@ Finally, add the following code after the last `foreach` loop: Then, type `dotnet patterns.cs` in the terminal window to see the results. This final version tests the input against a *type*. -Pattern matching provides a vocabulary to compare an expression against characteristics. Patterns can include the expression's type, values of types, property values, and combinations of them. Comparing expressions against a pattern can be more clear than multiple `if` comparisons. You explored some of the patterns you can use to match expressions. There are many more ways to use pattern matching in your applications. First, visit the [.NET site](https://dotnet.microsoft.com/learn/dotnet/hello-world-tutorial/intro) to download the .NET SDK, create a project on your machine, and keep coding. As you explore, you can learn more about pattern matching in C# in the following articles: +Pattern matching provides a vocabulary to compare an expression against characteristics. Patterns can include the expression's type, values of types, property values, and combinations of them. Comparing expressions against a pattern can be clearer than multiple `if` comparisons. You explored some of the patterns you can use to match expressions. There are many more ways to use pattern matching in your applications. First, visit the [.NET site](https://dotnet.microsoft.com/learn/dotnet/hello-world-tutorial/intro) to download the .NET SDK, create a project on your machine, and keep coding. As you explore, you can learn more about pattern matching in C# in the following articles: - [Pattern matching in C#](../../fundamentals/functional/pattern-matching.md) - [Explore pattern matching tutorial](../../tutorials/patterns-objects.md) diff --git a/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md b/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md index d48bd908c23fb..cfbb0b65dcdcc 100644 --- a/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md +++ b/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md @@ -7,13 +7,13 @@ ms.date: 12/03/2025 This tutorial teaches you about creating types in C#. You write small amounts of code, then you compile and run that code. The tutorial contains a series of lessons that explore different kinds of types in C#. These lessons teach you the fundamentals of the C# language. -The preceding tutorials worked with text and numbers. Strings and Numbers are *simple types*: They each store one single value. As your programs grow larger, you need to work with more sophisticated data structures. C# provides different kinds of types you can define when you need data structures with more fields, properties, or behavior. Let's start to explore those types. +The preceding tutorials worked with text and numbers. Strings and numbers are *simple types*: They each store one single value. As your programs grow larger, you need to work with more sophisticated data structures. C# provides different kinds of types you can define when you need data structures with more fields, properties, or behavior. Let's start to explore those types. To use codespaces, you need a GitHub account. If you don't already have one, you can create a free account at [GitHub.com](https://github.com). ## Tuples -Open a browser window to [GitHub codespaces](https://github.com/codespaces). Create a new codespace from the *.NET Template*. If you've done other tutorials in this series, you can open that codespace. Once your codespace loads, create a new file in the *tutorials* folder named *tuples.cs*. Open your new file. Type or copy the following code into *tuples.cs*: +Open a browser window to [GitHub codespaces](https://github.com/codespaces). Create a new codespace from the *.NET Template*. If you completed other tutorials in this series, you can open that codespace. When your codespace loads, create a new file in the *tutorials* folder named *tuples.cs*. Open your new file. Type or copy the following code into *tuples.cs*: :::code language="csharp" source="./snippets/TuplesAndTypes/tuples-types.cs" id="CreateTuple"::: @@ -42,9 +42,9 @@ Tuples are structural types. In other words, tuple types don't have names like ` :::code language="csharp" source="./snippets/TuplesAndTypes/tuples-types.cs" id="NamedAssignment"::: -The variable `subscript` has two members, both of which are integers. Both `subscript` and `pt` represent instances of the same tuple type: a tuple containing 2 `int` members. +The variable `subscript` has two members, both of which are integers. Both `subscript` and `pt` represent instances of the same tuple type: a tuple containing two `int` members. -Tuples are easy to create: You declare multiple members enclosed in parentheses. All the following declare different tuples of different arities and member types. Add the following code to create new tuple types: +Tuples are easy to create: You declare multiple members enclosed in parentheses. All the following declarations define different tuples with different arities and member types. Add the following code to create new tuple types: :::code language="csharp" source="./snippets/TuplesAndTypes/tuples-types.cs" id="TupleTypes"::: @@ -54,7 +54,7 @@ While tuples are easy to create, they're limited in their capabilities. Tuple ty ## Create record types -Tuples are great for those times when you want multiple values in the same structure. They're lightweight, and can be declared as they're used. As your program goes, you might find that you use the same tuple type throughout your code. If your app does work in the 2D graph space, the tuples that represent points might be common. Once you find that, you can declare a `record` type that stores those values and provides more capabilities. The following code sample uses a `Main` method to represent the entry point for the program. That way, you can declare a `record` type preceding the entry point in the code. Press the "Run" button on the following code to replace your existing sample with the following code. +Tuples are great for those times when you want multiple values in the same structure. They're lightweight, and you can declare them as you use them. As your program grows, you might find that you use the same tuple type throughout your code. If your app works in the 2D graph space, the tuples that represent points might be common. When you find this pattern, you can declare a `record` type that stores those values and provides more capabilities. The following code sample uses a `Main` method to represent the entry point for the program. That way, you can declare a `record` type preceding the entry point in the code. Select **Run** on the following code to replace your existing sample with the following code. The following code declares and uses a `record` type to represent a `Point`: @@ -68,7 +68,7 @@ Add the following code preceding the `record` declaration: The `record` declaration is a single line of code for the `Point` type that stores the values `X` and `Y` in readonly properties. You use the name `Point` wherever you use that type. Properly named types, like `Point`, provide information about how the type is used. The additional code shows how to use a `with` expression to create a new point that's a modified copy of the existing point. The line `pt4 = pt3 with { Y = 10 }` says "`pt4` has the same values as `pt3` except that `Y` is assigned to 10." You can add any number of properties to change in a single `with` expression. -The preceding `record` declaration is a single line of code that ends in `;`. You can add behavior to a `record` type by declaring *members*. A record member can be a function, or more data elements. The members of a type are in the type declaration, between `{` and `}` characters. Delete the `;` and add the following lines of code after the `record` declaration: +The preceding `record` declaration is a single line of code that ends in `;`. You can add behavior to a `record` type by declaring *members*. A record member can be a function or more data elements. The members of a type are in the type declaration, between `{` and `}` characters. Delete the `;` and add the following lines of code after the `record` declaration: :::code language="csharp" source="./snippets/TuplesAndTypes/tuples-types.cs" id="AddSlopeMethod"::: @@ -78,7 +78,7 @@ Then, add the following code before the `record` declaration, after the line con Type `dotnet tuples.cs` in the terminal window to run this version. -You added formality to the *tuple* representing an `X` and `Y` value. You made it a `record` that defined a named type, and included a member to calculate the slope. A `record` type is a shorthand for a `record class`: A `class` type that includes extra behavior. You can modify the `Point` type to make it a `record struct` as well: +You added formality to the *tuple* representing an `X` and `Y` value. You made it a `record` that defined a named type and included a member to calculate the slope. A `record` type is a shorthand for a `record class`: A `class` type that includes extra behavior. You can modify the `Point` type to make it a `record struct` as well: :::code language="csharp" source="./snippets/TuplesAndTypes/tuples-types.cs" id="RecordStructPoint"::: @@ -94,7 +94,7 @@ The `record` modifier instructs the compiler to write several members for you. Y When you declare a `record` type, you declare that your type should use a default set of behaviors for equality comparisons, assignment, and copying instances of that type. Records are the best choice when storing related data is the primary responsibility of your type. As you add more behaviors, consider using `struct` or `class` types, without the `record` modifier. -You use `struct` types for value types when more sophisticated behavior is needed, but the primary responsibility is storing values. You use `class` types to use object oriented idioms like encapsulation, inheritance, and polymorphism. +Use `struct` types for value types when you need more sophisticated behavior, but the primary responsibility is storing values. Use `class` types to use object-oriented idioms like encapsulation, inheritance, and polymorphism. You can also define `interface` types to declare behavioral contracts that different types must implement. Both `struct` and `class` types can implement interfaces.