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..d1d6f97cc2bac 100644 --- a/docs/csharp/tour-of-csharp/tutorials/branches-and-loops.md +++ b/docs/csharp/tour-of-csharp/tutorials/branches-and-loops.md @@ -1,103 +1,113 @@ --- 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. +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 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*: -Run the following code in the interactive window. Select **Run**: +:::code language="csharp" source="./snippets/BranchesAndLoops/branches-loops.cs" id="FirstIf"::: -:::code language="csharp" interactive="try-dotnet-method" source="./snippets/BranchesAndLoops/Program.cs" id="FirstIf"::: +Try this code by typing the following command in the integrated terminal: + +```dotnetcli +cd tutorials +dotnet branches-loops.cs +``` -Modify the declaration of `b` so that the sum is less than 10: +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 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 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 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. +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/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. +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"::: +:::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: +You can test more complicated conditions. Add the following code after the code you wrote 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`. 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 wrote 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: + +:::code language="csharp" source="./snippets/BranchesAndLoops/branches-loops.cs" id="Refactor"::: + +Comment out the call to `ExploreIf()`. It makes 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 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" interactive="try-dotnet-method" 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. -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 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. 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"::: +:::code language="csharp" source="./snippets/BranchesAndLoops/branches-loops.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/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: - 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: @@ -107,29 +117,29 @@ 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" interactive="try-dotnet-method" source="./snippets/BranchesAndLoops/Program.cs" id="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/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. +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 +152,12 @@ 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/branches-loops.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 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/hello-world.md b/docs/csharp/tour-of-csharp/tutorials/hello-world.md index 16b21ad0ebcab..4c95e6da006f0 100644 --- a/docs/csharp/tour-of-csharp/tutorials/hello-world.md +++ b/docs/csharp/tour-of-csharp/tutorials/hello-world.md @@ -1,54 +1,59 @@ --- -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. +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. -> [!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. +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). ## Run your first program -Run the following code in the interactive window. +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"::: + +In the integrated terminal window, make the *tutorials* folder the current folder, and run your program: -:::code language="csharp" interactive="try-dotnet-method" source="./snippets/HelloWorld/Program.cs" id="HelloWorld"::: +```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. +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 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 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: -:::code language="csharp" interactive="try-dotnet-method" 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. -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"::: +:::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: +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/Program.cs" id="ConcatMessage"::: +:::code language="csharp" source="./snippets/HelloWorld/hello-world.cs" id="ConcatMessage"::: -Select **Run** again 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,25 +61,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/hello-world.cs" id="Interpolation"::: -:::code language="csharp" source="./snippets/HelloWorld/Program.cs" id="Interpolation"::: +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 -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: +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/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 the interactive window: +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/Program.cs" id="Properties"::: +:::code language="csharp" source="./snippets/HelloWorld/hello-world.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 +88,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/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,25 +96,25 @@ 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" interactive="try-dotnet-method" 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`: +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/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" interactive="try-dotnet-method" 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. ## 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] > @@ -117,16 +122,16 @@ There are two similar methods, and
-:::code language="csharp" interactive="try-dotnet-method" source="./snippets/HelloWorld/Program.cs" id="Challenge"::: +:::code language="csharp" source="./snippets/HelloWorld/hello-world.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#](./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..3deb836f616e7 100644 --- a/docs/csharp/tour-of-csharp/tutorials/index.md +++ b/docs/csharp/tour-of-csharp/tutorials/index.md @@ -1,41 +1,38 @@ --- 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. +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. -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 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 @@ -43,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 74a6388cccb25..2ac2e70d7141b 100644 --- a/docs/csharp/tour-of-csharp/tutorials/list-collection.md +++ b/docs/csharp/tour-of-csharp/tutorials/list-collection.md @@ -1,25 +1,30 @@ --- -title: Data collections - Introductory interactive 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. +title: Data collections - Introductory tutorial +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\# -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# 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. + +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 -> [!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. +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 following code in the interactive window. Replace `` with your name and select **Run**: +Run the code by typing the following command in the terminal window: -:::code language="csharp" interactive="try-dotnet-method" source="./snippets/ListCollection/Program.cs" id="BasicList"::: +```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. @@ -31,19 +36,19 @@ 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: +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/Program.cs" id="Property"::: +:::code language="csharp" source="./snippets/ListCollection/list.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 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. @@ -51,25 +56,25 @@ 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: +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/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. Delete the code you wrote so far, and replace it with the following code: +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" interactive="try-dotnet-method" 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: +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/Program.cs" id="Fibonacci"::: +:::code language="csharp" source="./snippets/ListCollection/list.cs" id="Fibonacci"::: -Press **Run** to see the results. +Type `dotnet lists.cs` in the terminal window to see the results. ## Challenge @@ -80,13 +85,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/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.
-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/numbers-in-csharp.md b/docs/csharp/tour-of-csharp/tutorials/numbers-in-csharp.md index 40034751c60bb..2b486a25e0fb4 100644 --- a/docs/csharp/tour-of-csharp/tutorials/numbers-in-csharp.md +++ b/docs/csharp/tour-of-csharp/tutorials/numbers-in-csharp.md @@ -1,141 +1,229 @@ --- -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. +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). ## Explore integer math -Run the following code in the interactive window. +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"::: -:::code language="csharp" interactive="try-dotnet-method" source="./snippets/NumbersInCsharp/Program.cs" id="Addition"::: +Run this code by typing the following commands in the integrated terminal: + +```dotnetcli +cd ./tutorials +dotnet numbers.cs +``` -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: +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 - `/` 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/numbers.cs" id="OtherOperations"::: + +Run this code by typing `dotnet numbers.cs` in the terminal 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 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 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 makes 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 typing `dotnet numbers.cs` in the terminal window: -:::code language="csharp" interactive="try-dotnet-method" 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 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"::: +:::code language="csharp" source="./snippets/NumbersInCsharp/numbers.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 numbers` again in the terminal window. -:::code language="csharp" source="./snippets/NumbersInCsharp/Program.cs" id="CompoundExpression"::: +:::code language="csharp" source="./snippets/NumbersInCsharp/numbers.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. -Try the following code: +If you didn't see this behavior, try the following code: -:::code language="csharp" interactive="try-dotnet-method" source="./snippets/NumbersInCsharp/Program.cs" id="Truncation"::: +:::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 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(); +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: +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" interactive="try-dotnet-method" 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 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"::: +:::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. -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 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 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" interactive="try-dotnet-method" 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"::: - -The range of a double value is greater than integer values. Try the following code in the interactive window: +:::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="ChangeDoubleValues"::: -:::code language="csharp" source="./snippets/NumbersInCsharp/Program.cs" id="MinMax"::: +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: -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. +:::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="MinMax"::: -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"::: +:::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. ***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 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 -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" interactive="try-dotnet-method" source="./snippets/NumbersInCsharp/Program.cs" id="Decimal"::: +:::code language="csharp" source="./snippets/NumbersInCsharp/numbers.cs" id="Decimal"::: 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. +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*** -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:
-:::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":::
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/pattern-matching.md b/docs/csharp/tour-of-csharp/tutorials/pattern-matching.md index 34253cdc2afa0..60c3e8a364e8f 100644 --- a/docs/csharp/tour-of-csharp/tutorials/pattern-matching.md +++ b/docs/csharp/tour-of-csharp/tutorials/pattern-matching.md @@ -1,41 +1,67 @@ --- 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. +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. -> [!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. +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 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, 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 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 text in the terminal window: -:::code language="csharp" interactive="try-dotnet-method" source="./snippets/PatternMatching/Program.cs" id="FirstExample"::: +```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. To see it work, press the "Run" button: +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"::: + +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: -> [!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. +:::code language="csharp" source="./snippets/PatternMatching/patterns.cs" id="ParseTransaction"::: -:::code language="csharp" interactive="try-dotnet" source="./snippets/PatternMatching/FirstEnumExample.cs" id="IsEnumValue"::: +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"::: 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 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(); + +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 modify the code, type `dotnet patterns.cs` in the terminal window to run the new sample. -:::code language="csharp" interactive="try-dotnet" source="./snippets/PatternMatching/EnumSwitchExample.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: @@ -48,27 +74,27 @@ 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 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 -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/patterns.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 returns a series of records: -:::code language="csharp" interactive="try-dotnet" source="./snippets/PatternMatching/FinalExampleProgram.cs" id="ParseToRecord"::: +:::code language="csharp" source="./snippets/PatternMatching/patterns.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/patterns.cs" id="TypePattern"::: -Then, press the "Run" button 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: +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/snippets/BranchesAndLoops/BranchesAndLoops.csproj b/docs/csharp/tour-of-csharp/tutorials/snippets/BranchesAndLoops/BranchesAndLoops.csproj deleted file mode 100644 index fd4bd08da2987..0000000000000 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/BranchesAndLoops/BranchesAndLoops.csproj +++ /dev/null @@ -1,10 +0,0 @@ - - - - Exe - net9.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 75% 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 index dae1c19e90003..0f23a13985413 100644 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/BranchesAndLoops/Program.cs +++ b/docs/csharp/tour-of-csharp/tutorials/snippets/BranchesAndLoops/branches-loops.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() { // 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 fd4bd08da2987..0000000000000 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/HelloWorld/HelloWorld.csproj +++ /dev/null @@ -1,10 +0,0 @@ - - - - Exe - net9.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 deleted file mode 100644 index fe73550748b2e..0000000000000 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/HelloWorld/Program.cs +++ /dev/null @@ -1,102 +0,0 @@ -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}]"); - - 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")); - // -} - -void Challenge() -{ - // - string songLyrics = "You say goodbye, and I say hello"; - Console.WriteLine(songLyrics.StartsWith("You")); - Console.WriteLine(songLyrics.StartsWith("goodbye")); - - Console.WriteLine(songLyrics.EndsWith("hello")); - Console.WriteLine(songLyrics.EndsWith("goodbye")); - // -} diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/HelloWorld/hello-world.cs b/docs/csharp/tour-of-csharp/tutorials/snippets/HelloWorld/hello-world.cs new file mode 100644 index 0000000000000..29a26f376bada --- /dev/null +++ b/docs/csharp/tour-of-csharp/tutorials/snippets/HelloWorld/hello-world.cs @@ -0,0 +1,78 @@ +// +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")); +// + +Challenge(); + +void Challenge() +{ + // + string songLyrics = "You say goodbye, and I say hello"; + Console.WriteLine(songLyrics.StartsWith("You")); + Console.WriteLine(songLyrics.StartsWith("goodbye")); + + Console.WriteLine(songLyrics.EndsWith("hello")); + Console.WriteLine(songLyrics.EndsWith("goodbye")); + // +} 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 fd4bd08da2987..0000000000000 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/ListCollection/ListCollection.csproj +++ /dev/null @@ -1,10 +0,0 @@ - - - - Exe - net9.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 deleted file mode 100644 index 3df770ea7cb45..0000000000000 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/ListCollection/Program.cs +++ /dev/null @@ -1,103 +0,0 @@ - -ListOfStrings(); -ListOfNumbers(); -ChallengeAnswer(); - -void ListOfStrings() -{ - // - List names = ["", "Ana", "Felipe"]; - 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($"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}"); - } - // - - // - names.Sort(); - foreach (var name in names) - { - Console.WriteLine($"Hello {name.ToUpper()}!"); - } - // -} - -void ListOfNumbers() -{ - // - List fibonacciNumbers = [1, 1]; - // - - // - var previous = fibonacciNumbers[fibonacciNumbers.Count - 1]; - var previous2 = fibonacciNumbers[fibonacciNumbers.Count - 2]; - - fibonacciNumbers.Add(previous + previous2); - - foreach (var item in fibonacciNumbers) - { - Console.WriteLine(item); - } - // -} - -void ChallengeAnswer() -{ - // - List fibonacciNumbers = [1, 1]; - - while (fibonacciNumbers.Count < 20) - { - var previous = fibonacciNumbers[fibonacciNumbers.Count - 1]; - var previous2 = fibonacciNumbers[fibonacciNumbers.Count - 2]; - - fibonacciNumbers.Add(previous + previous2); - } - foreach (var item in fibonacciNumbers) - { - Console.WriteLine(item); - } - // -} diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/ListCollection/list.cs b/docs/csharp/tour-of-csharp/tutorials/snippets/ListCollection/list.cs new file mode 100644 index 0000000000000..c898bbf5fa803 --- /dev/null +++ b/docs/csharp/tour-of-csharp/tutorials/snippets/ListCollection/list.cs @@ -0,0 +1,94 @@ +// +List names = ["", "Ana", "Felipe"]; +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($"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}"); +} +// + +// +names.Sort(); +foreach (var name in names) +{ + Console.WriteLine($"Hello {name.ToUpper()}!"); +} +// + +// +List fibonacciNumbers = [1, 1]; +// + +// +var previous = fibonacciNumbers[fibonacciNumbers.Count - 1]; +var previous2 = fibonacciNumbers[fibonacciNumbers.Count - 2]; + +fibonacciNumbers.Add(previous + previous2); + +foreach (var item in fibonacciNumbers) +{ + Console.WriteLine(item); +} +// + +ChallengeAnswer(); + +void ChallengeAnswer() +{ + // + List fibonacciNumbers = [1, 1]; + + while (fibonacciNumbers.Count < 20) + { + var previous = fibonacciNumbers[fibonacciNumbers.Count - 1]; + var previous2 = fibonacciNumbers[fibonacciNumbers.Count - 2]; + + fibonacciNumbers.Add(previous + previous2); + } + foreach (var item in fibonacciNumbers) + { + Console.WriteLine(item); + } + // +} 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 74% rename from docs/csharp/tour-of-csharp/tutorials/snippets/NumbersInCsharp/Program.cs rename to docs/csharp/tour-of-csharp/tutorials/snippets/NumbersInCsharp/Numbers.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/Numbers.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); + // +} + 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 fd4bd08da2987..0000000000000 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/NumbersInCsharp/NumbersInCsharp.csproj +++ /dev/null @@ -1,10 +0,0 @@ - - - - Exe - net9.0 - enable - enable - - - 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 deleted file mode 100644 index fd4bd08da2987..0000000000000 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/PatternMatching.csproj +++ /dev/null @@ -1,10 +0,0 @@ - - - - Exe - net9.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 deleted file mode 100644 index abb2305b43bce..0000000000000 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/Program.cs +++ /dev/null @@ -1,57 +0,0 @@ -// -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 - """; - -double currentBalance = 0.0; -var reader = new StringReader(bankRecords); - -string? line; -while ((line = reader.ReadLine()) is not null) -{ - if (string.IsNullOrWhiteSpace(line)) continue; - // Split the line based on comma delimiter and trim each part - 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") - currentBalance += amount; - else if (transactionType?.ToUpper() is "WITHDRAWAL") - currentBalance -= amount; - - Console.WriteLine($"{line.Trim()} => Parsed Amount: {amount}, New Balance: {currentBalance}"); - } -} -// - -Console.WriteLine(); -FirstEnumExample.ExampleProgram.Main(); -Console.WriteLine(); -EnumSwitchExample.ExampleProgram.Main(); -Console.WriteLine(); -ExampleProgram.Main(); -Console.WriteLine(); - diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/patterns.cs b/docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/patterns.cs new file mode 100644 index 0000000000000..516a8bb2e8359 --- /dev/null +++ b/docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/patterns.cs @@ -0,0 +1,154 @@ +// +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 + """; + +double currentBalance = 0.0; +var reader = new StringReader(bankRecords); + +string? line; +while ((line = reader.ReadLine()) is not null) +{ + if (string.IsNullOrWhiteSpace(line)) continue; + // Split the line based on comma delimiter and trim each part + 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") + currentBalance += amount; + else if (transactionType?.ToUpper() is "WITHDRAWAL") + currentBalance -= amount; + + Console.WriteLine($"{line.Trim()} => Parsed Amount: {amount}, New Balance: {currentBalance}"); + } +} +// + +// +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); +// + 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 deleted file mode 100644 index 291fb75394c85..0000000000000 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/Program.cs +++ /dev/null @@ -1,37 +0,0 @@ - -using System.Xml.Linq; - -FirstExample(); - -void 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); - // -} - 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 fd4bd08da2987..0000000000000 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/TuplesAndTypes.csproj +++ /dev/null @@ -1,10 +0,0 @@ - - - - Exe - net9.0 - enable - enable - - - 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 new file mode 100644 index 0000000000000..e7d267b7a5f39 --- /dev/null +++ b/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/tuples-types.cs @@ -0,0 +1,56 @@ +// +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 {pt3} and {pt4}"); +// + +// +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; +} +// + +namespace PrimaryRecord +{ + // + public record Point(int X, int Y); + // +} + 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..cfbb0b65dcdcc 100644 --- a/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md +++ b/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md @@ -1,74 +1,88 @@ --- -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. -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 -*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. +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" interactive="try-dotnet-method" 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 the code in the interactive window to see what to fix. That exercise helps you learn the structure of C# code. +Run your program by typing the following commands in the integrated terminal window: + +```dotnetcli +cd tutorials +dotnet tuples.cs +``` -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. +*Tuples* are an ordered sequence of values with a fixed length. Each element of a tuple has a type and an optional name. + +> [!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/Program.cs" id="Modify"::: +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 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 tuples.cs` in the terminal window 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 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 by typing `dotnet tuples.cs` in the terminal window: -:::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. +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/Program.cs" id="TupleTypes"::: +:::code language="csharp" source="./snippets/TuplesAndTypes/tuples-types.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. +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 -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`: + +:::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. -> [!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. +Add the following code preceding the `record` declaration: -The following code declares and uses a `record` type to represent a `Point`, and then uses that `Point` structure in the `Main` method: +:::code language="csharp" source="./snippets/TuplesAndTypes/tuples-types.cs" id="UsePointRecord"::: -:::code language="csharp" interactive="try-dotnet-class" source="./snippets/TuplesAndTypes/PointEvolution.cs" id="PointVersion2"::: +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 `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 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 `;`, 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: +:::code language="csharp" source="./snippets/TuplesAndTypes/tuples-types.cs" id="AddSlopeMethod"::: -:::code language="csharp" source="./snippets/TuplesAndTypes/PointStruct.cs" id="PointVersion3"::: +Then, add the following code before the `record` declaration, after the line containing the `with` expression: -Then, add the following code to the `Main` method after the line containing the `with` expression: +:::code language="csharp" source="./snippets/TuplesAndTypes/tuples-types.cs" id="UseSlope"::: -:::code language="csharp" source="./snippets/TuplesAndTypes/PointStruct.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: +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/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 @@ -80,13 +94,13 @@ 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. 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: