From 850191cdfe252decc6039bd254efda0019a567a8 Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Fri, 21 Mar 2025 16:42:53 -0400 Subject: [PATCH 1/5] First draft The code is written in snippets, and not using the interactive window yet. --- docs/csharp/toc.yml | 20 +-- docs/csharp/tour-of-csharp/tutorials/index.md | 20 ++- .../tutorials/numbers-in-csharp.md | 2 +- .../snippets/TuplesAndTypes/Program.cs | 10 ++ .../TuplesAndTypes/TuplesAndTypes.csproj | 10 ++ .../tutorials/tuples-and-types.md | 123 ++++++++++++++++++ 6 files changed, 163 insertions(+), 22 deletions(-) create mode 100644 docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/Program.cs create mode 100644 docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/TuplesAndTypes.csproj create mode 100644 docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md diff --git a/docs/csharp/toc.yml b/docs/csharp/toc.yml index 25954329e3961..b6129c1f03afb 100644 --- a/docs/csharp/toc.yml +++ b/docs/csharp/toc.yml @@ -9,16 +9,16 @@ items: items: - name: Choose your first lesson href: tour-of-csharp/tutorials/index.md - - name: Tutorials - items: - - name: Hello world and text - href: tour-of-csharp/tutorials/hello-world.md - - name: Numbers in C# - href: tour-of-csharp/tutorials/numbers-in-csharp.md - - name: Branches and loops - href: tour-of-csharp/tutorials/branches-and-loops.md - - name: List collections - href: tour-of-csharp/tutorials/list-collection.md + - name: Hello world and text + href: tour-of-csharp/tutorials/hello-world.md + - name: Numbers in C# + href: tour-of-csharp/tutorials/numbers-in-csharp.md + - name: Tuples and types + href: tour-of-csharp/tutorials/tuples-and-types.md + - name: Branches and loops + href: tour-of-csharp/tutorials/branches-and-loops.md + - name: List collections + href: tour-of-csharp/tutorials/list-collection.md - name: C# language strategy href: tour-of-csharp/strategy.md - name: Learn C# for Java developers diff --git a/docs/csharp/tour-of-csharp/tutorials/index.md b/docs/csharp/tour-of-csharp/tutorials/index.md index 2dff3021aefe6..18953931983f9 100644 --- a/docs/csharp/tour-of-csharp/tutorials/index.md +++ b/docs/csharp/tour-of-csharp/tutorials/index.md @@ -1,7 +1,7 @@ --- title: Interactive tutorials description: Learn C# in your browser, and get started with your own development environment -ms.date: 03/07/2025 +ms.date: 03/20/2025 --- # Introduction to C\# @@ -10,35 +10,33 @@ Welcome to the introduction to C# tutorials. These lessons start with interactiv > [!VIDEO https://www.youtube.com/embed/9THmGiSPjBQ?si=3kUKFtOMLpEzeq7J] -The first lessons explain C# concepts using small snippets of code. You'll learn the basics of C# syntax and how to work with data types like strings, numbers, and booleans. It's all interactive, and you'll be writing and running code within minutes. These first lessons assume no prior knowledge of programming or the C# language. +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 may 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#. -## [Hello world](hello-world.md) +## 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/). -## [Numbers in C#](numbers-in-csharp.md) +## 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#. -This tutorial assumes that you've finished the [Hello world](hello-world.md) lesson. +## Tuples and types -## [Branches and loops](branches-and-loops.md) +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. -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. +## Branches and loops -This tutorial assumes that you've finished the [Hello world](hello-world.md) and [Numbers in C#](numbers-in-csharp.md) lessons. +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. -## [List collection](list-collection.md) +## 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. -This tutorial assumes that you've finished the lessons listed above. - ## Set up your local environment After you finish these tutorials, set up a development environment. You'll want: 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 8146a44713e8c..70325527bb6c8 100644 --- a/docs/csharp/tour-of-csharp/tutorials/numbers-in-csharp.md +++ b/docs/csharp/tour-of-csharp/tutorials/numbers-in-csharp.md @@ -134,7 +134,7 @@ Once you try it, open the details pane to see how you did: Try some other formulas if you'd like. -You completed the "Numbers in C#" interactive tutorial. You can select the **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 "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 can learn more about numbers in C# in the following articles: diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/Program.cs b/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/Program.cs new file mode 100644 index 0000000000000..a2776c975c413 --- /dev/null +++ b/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/Program.cs @@ -0,0 +1,10 @@ +// See https://aka.ms/new-console-template for more information +Console.WriteLine("Hello, World!"); + +// 1. Use tuples. Consider a point? +// 2. Convert tuple to a record. +// 3. Make it a record, add some method, like distance? +// 4. discuss struct and class. Those add more behavior.2nd project? + // arbitrary distance between two points. + // slope? + diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/TuplesAndTypes.csproj b/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/TuplesAndTypes.csproj new file mode 100644 index 0000000000000..fd4bd08da2987 --- /dev/null +++ b/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/TuplesAndTypes.csproj @@ -0,0 +1,10 @@ + + + + Exe + net9.0 + enable + enable + + + diff --git a/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md b/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md new file mode 100644 index 0000000000000..9562d1809b219 --- /dev/null +++ b/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md @@ -0,0 +1,123 @@ +--- +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 +--- +# 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. + +## 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: + +```csharp +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}"); +``` + +> [!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. + +Tuples are structural types. In other words, different 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 shape even if the members have different names: + +```csharp +var subscript(A, B) = pt; +``` + +The variable `subscript` has two members, but of which are integers. Both `subscript` and `pt` represent instances of the same tuple type: a tuple containing 2 `int` members. You can reassign any member of a tuple: + +```csharp +pt.X = pt.X + 5; +``` + +You can also create a new tuple that's a modified copy of the original using a `with` expression: + +```csharp +var pt2 = pt with { Y = 10 }; +``` + +The tuple `pt2` contains the `X` value of `pt` (6), and `pt2.Y` is 10. + +Tuples are easy to create: You declare multiple members enclosed in parentheses. All the following declare different tuples of different arites and member types: + +```csharp +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); +``` + +Tuples are easy to create, but they are limited in their capabilities. Tuple types don't have names, so you can convey meaning to the set of values. Tuple types can't add behavior. For that, C# has other kinds of types you can create. + +## 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 are 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: + +```csharp +public record Point(int X, int Y); +``` + +The preceding single line of code declares a named *record* type that stores the values `X` and `Y` in readonly properties. You use the name `Point` wherever you use that type. Using a named type makes it clear how the type is used. Unlike tuples, you can't change the value of a property in a record, but you can still make a new copy using a `with` expression: + +```csharp +Point pt = new Point {X = 1, Y = 1}; +var pt2 = pt with { Y = 10 }; +``` + +Record types can include behavior as well as data. In C#, any type declaration starts with `{` and ends with `}`. Replace the record declaration you made with the following: + +```csharp +public record Point(int X, int Y) +{ + public double Slope() => (double) Y / (double) X; +} +``` + +You can call it like the following: + +```csharp +double slope = pt.Slope(); +Console.WriteLine($"The slope of {pt} is {slope}"); +``` + +You've added a bit of 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 where some types are generated by the compiler. You can modify the `Point` type to make it a `record struct` as well: + +```csharp +public record struct Point(int X, int Y) +{ + public double Slope() => (double) Y / (double) X; +} +``` + +All named types in C# are either `class` or `struct` types. A `class` is a *reference type*. A `struct` is a *value type*. Variables of a value type store the contents of the the instance inline in memory. In other words, a `record struct Point` stores two integers: `X` and `Y`. Variables of a reference type store a reference, or pointer, to the storage for the instance. In other words, a `record class Point` stores a reference to a block of memory that holds the values for `X` and `Y`. + +In practice, that means value types are copied when assigned, but a copy of a class instance is a copy of the *reference*. That copied reference refers to the same instance of `X` and `Y`. + +The `record` modifier instructs the compiler to write several members for you. You can learn much more in the article on [record types](../../fundamentals/types/records.md) in the fundamentals section. + +## Struct, class, and interface types + +When you declare a `record` type, you declare that your type should use a default set of behavior 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 behavior, 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. + +You can also define `interface` types to declare behavioral contracts that different types must implement. Both `struct` and `class` types can implement interfaces. + +You'll 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 can learn more about types in C# in the following articles: + +- [Types in C#](../../fundamentals/types/index.md) +- [Records](../../fundamentals/types/records.md) +- [Classes](../../fundamentals/types/classes.md) From 706a3e3d54db5483396da1499c9334d63d522677 Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Thu, 3 Apr 2025 12:07:13 -0400 Subject: [PATCH 2/5] add samples --- .../snippets/TuplesAndTypes/PointEvolution.cs | 20 ++++++ .../snippets/TuplesAndTypes/PointStruct.cs | 8 +++ .../snippets/TuplesAndTypes/Program.cs | 56 ++++++++++++++--- .../tutorials/tuples-and-types.md | 63 +++++-------------- 4 files changed, 91 insertions(+), 56 deletions(-) create mode 100644 docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/PointEvolution.cs create mode 100644 docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/PointStruct.cs diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/PointEvolution.cs b/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/PointEvolution.cs new file mode 100644 index 0000000000000..f452509e01645 --- /dev/null +++ b/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/PointEvolution.cs @@ -0,0 +1,20 @@ +namespace PointEvolution; + +// +public record Point(int X, int Y) +{ + public double Slope() => (double)Y / (double)X; +} +// + +public static class Expected +{ + public static void Example() + { + // + Point pt = new Point(1, 1); + double slope = pt.Slope(); + Console.WriteLine($"The slope of {pt} is {slope}"); + // + } +} diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/PointStruct.cs b/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/PointStruct.cs new file mode 100644 index 0000000000000..ea5d16a059157 --- /dev/null +++ b/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/PointStruct.cs @@ -0,0 +1,8 @@ +namespace MoreStruct; + +// +public record struct Point(int X, int Y) +{ + public double Slope() => (double) Y / (double) X; +} +// diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/Program.cs b/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/Program.cs index a2776c975c413..3fc4daf31da6b 100644 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/Program.cs +++ b/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/Program.cs @@ -1,10 +1,48 @@ -// See https://aka.ms/new-console-template for more information -Console.WriteLine("Hello, World!"); - -// 1. Use tuples. Consider a point? -// 2. Convert tuple to a record. -// 3. Make it a record, add some method, like distance? -// 4. discuss struct and class. Those add more behavior.2nd project? - // arbitrary distance between two points. - // slope? + +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); + // +} + +// +Point pt = new Point(1, 1); +var pt2 = pt with { Y = 10 }; +// + +PointEvolution.Expected.Example(); + +// +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 9562d1809b219..fbfb78d54a4eb 100644 --- a/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md +++ b/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md @@ -17,44 +17,31 @@ The preceding tutorials worked with text and numbers. Strings and Numbers are *s *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: -```csharp -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}"); -``` +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/TuplesAndTypes/Program.cs" id="CreateTuple"::: > [!TIP] > > As you explore C# (or any programming language), you make mistakes when you write code. The **compiler** finds those errors and 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. -Tuples are structural types. In other words, different 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 shape even if the members have different names: - -```csharp -var subscript(A, B) = pt; -``` - -The variable `subscript` has two members, but of which are integers. Both `subscript` and `pt` represent instances of the same tuple type: a tuple containing 2 `int` members. You can reassign any member of a tuple: +You can reassign any member of a tuple: -```csharp -pt.X = pt.X + 5; -``` +:::code language="csharp" source="./snippets/TuplesAndTypes/Program.cs" id="Modify"::: You can also create a new tuple that's a modified copy of the original using a `with` expression: -```csharp -var pt2 = pt with { Y = 10 }; -``` +:::code language="csharp" source="./snippets/TuplesAndTypes/Program.cs" id="Wither"::: The tuple `pt2` contains the `X` value of `pt` (6), and `pt2.Y` is 10. +Tuples are structural types. In other words, tuple types don't have names like `string` or `int`. A tuple type is defined by the number of members, referred to as *arity* and the types of those members. The member names are for convenience. You can assign a tuple to a tuple with the same arity and types even if the members have different names: + +:::code language="csharp" source="./snippets/TuplesAndTypes/Program.cs" id="NamedAssignment"::: + +The variable `subscript` has two members, both of which are integers. Both `subscript` and `pt` represent instances of the same tuple type: a tuple containing 2 `int` members. + Tuples are easy to create: You declare multiple members enclosed in parentheses. All the following declare different tuples of different arites and member types: -```csharp -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); -``` +:::code language="csharp" source="./snippets/TuplesAndTypes/Program.cs" id="TupleTypes"::: Tuples are easy to create, but they are limited in their capabilities. Tuple types don't have names, so you can convey meaning to the set of values. Tuple types can't add behavior. For that, C# has other kinds of types you can create. @@ -62,41 +49,23 @@ Tuples are easy to create, but they are limited in their capabilities. Tuple typ Tuples are great for those times when you want multiple values in the same structure. They're lightweight, and can be declared as they are 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: -```csharp -public record Point(int X, int Y); -``` +:::code language="csharp" interactive="try-dotnet-program" source="./snippets/TuplesAndTypes/Program.cs" id="DeclareRecord"::: The preceding single line of code declares a named *record* type that stores the values `X` and `Y` in readonly properties. You use the name `Point` wherever you use that type. Using a named type makes it clear how the type is used. Unlike tuples, you can't change the value of a property in a record, but you can still make a new copy using a `with` expression: -```csharp -Point pt = new Point {X = 1, Y = 1}; -var pt2 = pt with { Y = 10 }; -``` +:::code language="csharp" source="./snippets/TuplesAndTypes/Program.cs" id="CreateRecord"::: Record types can include behavior as well as data. In C#, any type declaration starts with `{` and ends with `}`. Replace the record declaration you made with the following: -```csharp -public record Point(int X, int Y) -{ - public double Slope() => (double) Y / (double) X; -} -``` +:::code language="csharp" source="./snippets/TuplesAndTypes/PointEvolution.cs" id="PointVersion2"::: You can call it like the following: -```csharp -double slope = pt.Slope(); -Console.WriteLine($"The slope of {pt} is {slope}"); -``` +:::code language="csharp" source="./snippets/TuplesAndTypes/PointEvolution.cs" id="Version2Usage"::: You've added a bit of 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 where some types are generated by the compiler. You can modify the `Point` type to make it a `record struct` as well: -```csharp -public record struct Point(int X, int Y) -{ - public double Slope() => (double) Y / (double) X; -} -``` +:::code language="csharp" source="./snippets/TuplesAndTypes/PointStruct.cs" id="RecordStruct"::: All named types in C# are either `class` or `struct` types. A `class` is a *reference type*. A `struct` is a *value type*. Variables of a value type store the contents of the the instance inline in memory. In other words, a `record struct Point` stores two integers: `X` and `Y`. Variables of a reference type store a reference, or pointer, to the storage for the instance. In other words, a `record class Point` stores a reference to a block of memory that holds the values for `X` and `Y`. From 2f5c3442d17c2e50cb38c9b0d93cbbc9a5c03c0b Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Thu, 3 Apr 2025 13:07:53 -0400 Subject: [PATCH 3/5] correct interactive bits. Use the class type, and declare a `Main` method. --- .../snippets/TuplesAndTypes/PointEvolution.cs | 19 ++++------- .../snippets/TuplesAndTypes/PointStruct.cs | 33 ++++++++++++++++--- .../snippets/TuplesAndTypes/Program.cs | 11 ------- .../tutorials/tuples-and-types.md | 14 +++----- 4 files changed, 40 insertions(+), 37 deletions(-) diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/PointEvolution.cs b/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/PointEvolution.cs index f452509e01645..1edbac77c5f4f 100644 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/PointEvolution.cs +++ b/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/PointEvolution.cs @@ -1,20 +1,15 @@ namespace PointEvolution; -// -public record Point(int X, int Y) +public static class SampleTwo { - public double Slope() => (double)Y / (double)X; -} -// + // + public record Point(int X, int Y); -public static class Expected -{ - public static void Example() + public static void Main() { - // Point pt = new Point(1, 1); - double slope = pt.Slope(); - Console.WriteLine($"The slope of {pt} is {slope}"); - // + 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 index ea5d16a059157..2ee93b8cf47f7 100644 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/PointStruct.cs +++ b/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/PointStruct.cs @@ -1,8 +1,31 @@ -namespace MoreStruct; +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}"); + // + } + } +} -// -public record struct Point(int X, int Y) +namespace MoreStruct { - public double Slope() => (double) Y / (double) X; + // + public record struct Point(int X, int Y) + { + public double Slope() => (double) Y / (double) X; + } + // } -// diff --git a/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/Program.cs b/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/Program.cs index 3fc4daf31da6b..291fb75394c85 100644 --- a/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/Program.cs +++ b/docs/csharp/tour-of-csharp/tutorials/snippets/TuplesAndTypes/Program.cs @@ -35,14 +35,3 @@ void FirstExample() // } -// -Point pt = new Point(1, 1); -var pt2 = pt with { Y = 10 }; -// - -PointEvolution.Expected.Example(); - -// -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 fbfb78d54a4eb..51037409df405 100644 --- a/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md +++ b/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md @@ -49,19 +49,15 @@ Tuples are easy to create, but they are limited in their capabilities. Tuple typ Tuples are great for those times when you want multiple values in the same structure. They're lightweight, and can be declared as they are 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: -:::code language="csharp" interactive="try-dotnet-program" source="./snippets/TuplesAndTypes/Program.cs" id="DeclareRecord"::: +:::code language="csharp" interactive="try-dotnet-class" source="./snippets/TuplesAndTypes/PointEvolution.cs" id="PointVersion2"::: -The preceding single line of code declares a named *record* type that stores the values `X` and `Y` in readonly properties. You use the name `Point` wherever you use that type. Using a named type makes it clear how the type is used. Unlike tuples, you can't change the value of a property in a record, but you can still make a new copy using a `with` expression: +The preceding single line of code declares a named *record* type that stores the values `X` and `Y` in readonly properties. You use the name `Point` wherever you use that type. Using a named type makes it clear how the type is used. Unlike tuples, you can't change the value of a property in a record, but you can still make a new copy using a `with` expression. Record types can include behavior as well as data. In C#, any type declaration starts with `{` and ends with `}`. Replace the record declaration you made with the following: -:::code language="csharp" source="./snippets/TuplesAndTypes/Program.cs" id="CreateRecord"::: +:::code language="csharp" source="./snippets/TuplesAndTypes/PointStruct.cs" id="PointVersion3"::: -Record types can include behavior as well as data. In C#, any type declaration starts with `{` and ends with `}`. Replace the record declaration you made with the following: +:::code language="csharp" source="./snippets/TuplesAndTypes/PointStruct.cs" id="UseSlope"::: -:::code language="csharp" source="./snippets/TuplesAndTypes/PointEvolution.cs" id="PointVersion2"::: - -You can call it like the following: - -:::code language="csharp" source="./snippets/TuplesAndTypes/PointEvolution.cs" id="Version2Usage"::: +The `Main` method shows how you can create and use this record type. You've added a bit of 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 where some types are generated by the compiler. You can modify the `Point` type to make it a `record struct` as well: From 9d55ac6bb68e56cdf6ceda93fc2cdf3e0243d1b8 Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Thu, 3 Apr 2025 15:54:50 -0400 Subject: [PATCH 4/5] Final proofread Proofread, content and data check. --- .../tutorials/tuples-and-types.md | 44 ++++++++++++------- 1 file changed, 27 insertions(+), 17 deletions(-) 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 51037409df405..9a358a627e816 100644 --- a/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md +++ b/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md @@ -15,7 +15,7 @@ The preceding tutorials worked with text and numbers. Strings and Numbers are *s ## 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: +*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. :::code language="csharp" interactive="try-dotnet-method" source="./snippets/TuplesAndTypes/Program.cs" id="CreateTuple"::: @@ -23,61 +23,71 @@ The preceding tutorials worked with text and numbers. Strings and Numbers are *s > > 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. -You can reassign any member of a tuple: +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. :::code language="csharp" source="./snippets/TuplesAndTypes/Program.cs" id="Modify"::: -You can also create a new tuple that's a modified copy of the original using a `with` expression: +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: :::code language="csharp" source="./snippets/TuplesAndTypes/Program.cs" id="Wither"::: The tuple `pt2` contains the `X` value of `pt` (6), and `pt2.Y` is 10. -Tuples are structural types. In other words, tuple types don't have names like `string` or `int`. A tuple type is defined by the number of members, referred to as *arity* and the types of those members. The member names are for convenience. You can assign a tuple to a tuple with the same arity and types even if the members have different names: +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: :::code language="csharp" source="./snippets/TuplesAndTypes/Program.cs" id="NamedAssignment"::: The variable `subscript` has two members, both of which are integers. Both `subscript` and `pt` represent instances of the same tuple type: a tuple containing 2 `int` members. -Tuples are easy to create: You declare multiple members enclosed in parentheses. All the following declare different tuples of different arites and member types: +Tuples are easy to create: You declare multiple members enclosed in parentheses. All the following declare different tuples of different arities and member types. Add the following code to create new tuple types: :::code language="csharp" source="./snippets/TuplesAndTypes/Program.cs" id="TupleTypes"::: -Tuples are easy to create, but they are limited in their capabilities. Tuple types don't have names, so you can convey meaning to the set of values. Tuple types can't add behavior. For that, C# has other kinds of types you can create. +Tuples are easy to create, but they're limited in their capabilities. Tuple types don't have names, so you can 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 are 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: +Tuples are great for those times when you want multiple values in the same structure. They're lightweight, and can be declared as they're used. As your program goes, you might find that you use the same tuple type throughout your code. If your app does work in the 2D graph space, the tuples that represent points might be common. Once you find that, you can declare a `record` type that stores those values and provides more capabilities. The following code sample uses a `Main` method to represent the entry point for the program. That way, you can declare a `record` type preceding the entry point in the code. Press the "Run" button on the following code to replace your existing sample with the following code. + +> [!WARNING] +> +> Don't copy and paste. The interactive window must be reset to run the following sample. If you make a mistake, the window hangs, and you need to refresh the page to continue. + +The following code declares and uses a `record` type to represent a `Point`, and then uses that `Point` structure in the `Main` method: :::code language="csharp" interactive="try-dotnet-class" source="./snippets/TuplesAndTypes/PointEvolution.cs" id="PointVersion2"::: -The preceding single line of code declares a named *record* type that stores the values `X` and `Y` in readonly properties. You use the name `Point` wherever you use that type. Using a named type makes it clear how the type is used. Unlike tuples, you can't change the value of a property in a record, but you can still make a new copy using a `with` expression. Record types can include behavior as well as data. In C#, any type declaration starts with `{` and ends with `}`. Replace the record declaration you made with the following: +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 and `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 `;`, 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/PointStruct.cs" id="PointVersion3"::: -:::code language="csharp" source="./snippets/TuplesAndTypes/PointStruct.cs" id="UseSlope"::: +Then, add the following code to the `Main` method after the line containing the `with` expression: -The `Main` method shows how you can create and use this record type. +:::code language="csharp" source="./snippets/TuplesAndTypes/PointStruct.cs" id="UseSlope"::: -You've added a bit of 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 where some types are generated by the compiler. 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"::: -All named types in C# are either `class` or `struct` types. A `class` is a *reference type*. A `struct` is a *value type*. Variables of a value type store the contents of the the instance inline in memory. In other words, a `record struct Point` stores two integers: `X` and `Y`. Variables of a reference type store a reference, or pointer, to the storage for the instance. In other words, a `record class Point` stores a reference to a block of memory that holds the values for `X` and `Y`. +A `record struct` is a `struct` type that includes the extra behavior added to all `record` types. + +## Struct, class, and interface types -In practice, that means value types are copied when assigned, but a copy of a class instance is a copy of the *reference*. That copied reference refers to the same instance of `X` and `Y`. +All named types in C# are either `class` or `struct` types. A `class` is a *reference type*. A `struct` is a *value type*. Variables of a value type store the contents of the instance inline in memory. In other words, a `record struct Point` stores two integers: `X` and `Y`. Variables of a reference type store a reference, or pointer, to the storage for the instance. In other words, a `record class Point` stores a reference to a block of memory that holds the values for `X` and `Y`. -The `record` modifier instructs the compiler to write several members for you. You can learn much more in the article on [record types](../../fundamentals/types/records.md) in the fundamentals section. +In practice, that means value types are copied when assigned, but a copy of a class instance is a copy of the *reference*. That copied reference refers to the same instance of a point, with the same storage for `X` and `Y`. -## Struct, class, and interface types +The `record` modifier instructs the compiler to write several members for you. You can learn more in the article on [record types](../../fundamentals/types/records.md) in the fundamentals section. -When you declare a `record` type, you declare that your type should use a default set of behavior 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 behavior, consider using `struct` or `class` types, without the `record` modifier. +When you declare a `record` type, you declare that your type should use a default set of behavior 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. You can also define `interface` types to declare behavioral contracts that different types must implement. Both `struct` and `class` types can implement interfaces. -You'll 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 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. From 814e8fd1aeb6160edcf257a5077bc32413076713 Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Tue, 8 Apr 2025 09:58:23 -0400 Subject: [PATCH 5/5] Apply suggestions from code review Co-authored-by: Genevieve Warren <24882762+gewarren@users.noreply.github.com> --- docs/csharp/tour-of-csharp/tutorials/index.md | 4 ++-- .../tour-of-csharp/tutorials/tuples-and-types.md | 13 +++++-------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/docs/csharp/tour-of-csharp/tutorials/index.md b/docs/csharp/tour-of-csharp/tutorials/index.md index 18953931983f9..23d619b23026b 100644 --- a/docs/csharp/tour-of-csharp/tutorials/index.md +++ b/docs/csharp/tour-of-csharp/tutorials/index.md @@ -10,7 +10,7 @@ Welcome to the introduction to C# tutorials. These lessons start with interactiv > [!VIDEO https://www.youtube.com/embed/9THmGiSPjBQ?si=3kUKFtOMLpEzeq7J] -The first lessons explain C# concepts using small snippets of code. You'll learn the basics of C# syntax and how to work with data types like strings, numbers, and booleans. It's all interactive, and you'll be writing and running code within minutes. These first lessons assume no prior knowledge of programming or the C# language. Each lesson builds on the prior lessons. You should do them in order. However, if you have some programming experience you may skip or skim the first lessons and start with any new concepts. +The first lessons explain C# concepts using small snippets of code. You'll learn the basics of C# syntax and how to work with data types like strings, numbers, and booleans. It's all interactive, and you'll be writing and running code within minutes. These first lessons assume no prior knowledge of programming or the C# language. Each lesson builds on the prior lessons. You should do them in order. However, if you have some programming experience, you can skip or skim the first lessons and start with any new concepts. You can try these tutorials in different environments. The concepts you'll learn are the same. The difference is which experience you prefer: @@ -27,7 +27,7 @@ In the [Numbers in C#](numbers-in-csharp.md) tutorial, you'll learn how computer ## 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'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. ## Branches and loops 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 9a358a627e816..7dd87fe4b1b60 100644 --- a/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md +++ b/docs/csharp/tour-of-csharp/tutorials/tuples-and-types.md @@ -8,7 +8,6 @@ ms.date: 04/03/2025 This tutorial teaches you about creating types in C#. You write small amounts of code, then you compile and run that code. The tutorial contains a series of lessons that explore different kinds of types in C#. These lessons teach you the fundamentals of the C# language. > [!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. @@ -20,8 +19,7 @@ The preceding tutorials worked with text and numbers. Strings and Numbers are *s :::code language="csharp" interactive="try-dotnet-method" source="./snippets/TuplesAndTypes/Program.cs" id="CreateTuple"::: > [!TIP] -> -> As you explore C# (or any programming language), you make mistakes when you write code. The **compiler** finds those errors and 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 the interactive window to see what to fix. That exercise helps you learn the structure of C# code. 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. @@ -33,7 +31,7 @@ You can also create a new tuple that's a modified copy of the original using a ` 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 in the interactive window and try it: :::code language="csharp" source="./snippets/TuplesAndTypes/Program.cs" id="NamedAssignment"::: @@ -43,21 +41,20 @@ Tuples are easy to create: You declare multiple members enclosed in parentheses. :::code language="csharp" source="./snippets/TuplesAndTypes/Program.cs" id="TupleTypes"::: -Tuples are easy to create, but they're limited in their capabilities. Tuple types don't have names, so you can 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. +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. ## Create record types Tuples are great for those times when you want multiple values in the same structure. They're lightweight, and can be declared as they're used. As your program goes, you might find that you use the same tuple type throughout your code. If your app does work in the 2D graph space, the tuples that represent points might be common. Once you find that, you can declare a `record` type that stores those values and provides more capabilities. The following code sample uses a `Main` method to represent the entry point for the program. That way, you can declare a `record` type preceding the entry point in the code. Press the "Run" button on the following code to replace your existing sample with the following code. > [!WARNING] -> > Don't copy and paste. The interactive window must be reset to run the following sample. If you make a mistake, the window hangs, and you need to refresh the page to continue. The following code declares and uses a `record` type to represent a `Point`, and then uses that `Point` structure in the `Main` method: :::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 `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 and `pt` except that `Y` is assigned to 10." You can add any number of properties to change in a single `with` expression. +The `record` declaration is a single line of code for the `Point` type that stores the values `X` and `Y` in readonly properties. You use the name `Point` wherever you use that type. Properly named types, like `Point`, provide information about how the type is used. The `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 `;`, 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: @@ -81,7 +78,7 @@ In practice, that means value types are copied when assigned, but a copy of a cl The `record` modifier instructs the compiler to write several members for you. You can learn more in the article on [record types](../../fundamentals/types/records.md) in the fundamentals section. -When you declare a `record` type, you declare that your type should use a default set of behavior 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. +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.