From 6b92b75b3465373f0333c14525c1468031add9c6 Mon Sep 17 00:00:00 2001 From: ipvg Date: Sat, 27 Jul 2024 14:08:24 -0400 Subject: [PATCH] end 020 --- .../019_csharp.md | 7 + 020_data_types/020_csharp.md | 645 ++++++++++++++++++ 020_data_types/test_app/Program.cs | 36 + 020_data_types/test_app/test_app.csproj | 10 + README.md | 1 + 5 files changed, 699 insertions(+) create mode 100644 020_data_types/020_csharp.md create mode 100644 020_data_types/test_app/Program.cs create mode 100644 020_data_types/test_app/test_app.csproj diff --git a/019_branching_and_looping_structures/019_csharp.md b/019_branching_and_looping_structures/019_csharp.md index c1c285b..b00d988 100644 --- a/019_branching_and_looping_structures/019_csharp.md +++ b/019_branching_and_looping_structures/019_csharp.md @@ -407,3 +407,10 @@ data that filled gaps in the ourAnimals array. Your ability to implement features of the Contoso Pets application based on a design specification demonstrates your understanding of the iteration and selection statements. + +--- + +Project Files + +- [Final](./ChallengeProject/Final/Program.cs) +- [Own](./ChallengeProject/Own/Program.cs) diff --git a/020_data_types/020_csharp.md b/020_data_types/020_csharp.md new file mode 100644 index 0000000..9fe7c28 --- /dev/null +++ b/020_data_types/020_csharp.md @@ -0,0 +1,645 @@ +# Choose the correct data type in your C# code + +## Introduction + +The C# programming language relies on data types extensively. Data types +restrict the kinds of values that can be stored in a given variable, which can +be helpful when trying to create error free code. As a developer, you +confidently perform operations on your variables because you know in advance +that it only stores valid values. + +Suppose your job is to build a new application that must retrieve, manipulate, +and store many different kinds of data, including individual numeric values and +sequences of numeric and text values. Choosing the right data types is critical +to the success of your software development efforts. But what are your options, +and what criteria should you use when faced with several data types that seem +similar? + +In this module, you learn how your application stores and processes data. You +learn that there are two kinds of data types that correspond with the two ways +that data is processed. You write code that identifies the maximum and minimum +values that can be stored in a particular numeric data type. And, you learn the +criteria to use when choosing between several numeric data types for your +application. + +By the end of this module, you'll be confident when working with different data +types in C# and able to choose the right data type for your particular application. + +### Learning objectives + +- Learn the fundamental differences between value types and reference types. +- Describe the properties of many new numeric data types, including new +integral types and floating point types. +- Write code that returns the maximum and minimum values that numeric data +types can store. +- Use the new keyword to create new instances of a reference type. +- Determine which data type you should choose for a given application. + +## Discover value types and reference types + +With many data types available in C#, choosing the right one to use means that +you need to understand when you might choose one data type over another. + +Before discussing why you might choose one data type over another, you need to +understand more about data types. You also need to know how data and data types +work in C# and .NET. + +### What is data? + +Answering the question "what is data" depends on who you ask, and in what +context you're asking it. + +In software development, data is essentially a value that is stored in the +computer's memory as a series of bits. A bit is a simple binary switch +represented as a `0` or `1`, or rather, "off" and "on." A single bit doesn't +seem useful, however when you combine 8 bits together in a sequence, they form +a byte. When used in a byte, each bit takes on a meaning in the sequence. In +fact, you can represent 256 different combinations with just 8 bits if you use +a binary (base-2) numeral system. + +For example, in a binary numeral system, you can represent the number `195` as +`11000011`. The following table helps you visualize how this works. The first +row has eight columns that correspond to a position in a byte. Each position +represents a different numeric value. The second row can store the value of an +individual bit, either 0 or 1. + +
+ +| | | | | | | | | +| :-: | :-: | :-: | :-: | :-: | :-: | :-: | :-: | +| 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 | +| 1 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | + +
+ +If you add up the number from each column in the first row that corresponds to +a `1` in the second row, you get the decimal equivalent to the binary numeral +system representation. In this case, it would be `128 + 64 + 2 + 1 = 195`. + +To work with larger values beyond `255`, your computer stores more bytes +(commonly 32-bit or 64-bit). If you're working with millions of large numbers +in a scientific setting, you may need to consider more carefully which data +types you're using. Your code could require more memory to run. + +#### What about textual data? + +If a computer only understands `0s` and `1s`, then how does it allow you to work +with text? Using a system like ASCII (American Standard Code for Information +Interchange), you can use a single byte to represent upper and lowercase +letters, numbers, tab, backspace, newline and many mathematical symbols. + +For example, if you wanted to store a lower-case letter `a` as a value in my +application, the computer would only understand the binary form of that value. +To better understand how a lower-case letter `a` is handled by the computer, I +need to locate an ASCII table that provides ASCII values and their decimal +equivalents. You can search for the terms "ASCII lookup decimal" to locate such +a resource online. + +In this case, the lower-case letter `a` is equivalent to the decimal value `97`. +Then, you would use the same binary numeral system in reverse to find how an +ASCII letter `a` is stored by the computer. + + +
+ +| | | | | | | | | +| :-: | :-: | :-: | :-: | :-: | :-: | :-: | :-: | +| 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 | +| 0 | 1 | 1 | 0 | 0 | 0 | 0 | 1 | + +
+ +Since `64 + 32 + 1 = 97`, the 8-bit binary ASCII code for `a` is `01100001`. + +It's likely that you'll never need to perform these types of conversions on +your own, but understanding the computer's perspective of data is a +foundational concept, especially as you're considering data types. + +#### What is a data type? + +A data type is a way a programming language defines how much memory to save for +a value. There are many data types in the C# language to be used for many +different applications and sizes of data. + +For most of the applications you build in your career, you'll settle on a small +subset of all the available data types. However, it's still vital to know +others exist and why. + +#### Value vs. reference types + +This module focuses on the two kinds of types in C#: reference types and value +types. + +Variables of reference types store references to their data (objects), that is +they point to data values stored somewhere else. In comparison, variables of +value types directly contain their data. As you learn more about C#, new +details emerge related to the fundamental difference between value and +reference types. + +#### Simple value types + +Simple value types are a set of predefined types provided by C# as keywords. +These keywords are aliases (a nickname) for predefined types defined in the +.NET Class Library. For example, the C# keyword `int` is an alias of a value +type defined in the .NET Class Library as `System.Int32`. + +Simple value types include many of the data types that you may have used +already like `char` and `bool`. There are also many integral and floating-point +value types to represent a wide range of whole and fractional numbers. + +### Recap + +Values are stored as bits, which are simple on / off switches. Combining enough +of these switches allows you to store just about any possible value. +There are two basic categories of data types: value and reference types. The +difference is in how and where the values are stored by the computer as your +program executes. +Simple value types use a keyword alias to represent formal names of types in +the .NET Library. + +--- + +## Exercise + +### Discover integral types + +In this exercise, you work with integral types. An integral type is a simple +value type that represents whole numbers with no fraction (such as `-1`, `0`, +`1`, `2`, `3`). The most popular in this category is the `int` data type. + +There are two subcategories of integral types: **signed** and **unsigned** +integral types. + +A signed type uses its bytes to represent an equal number of positive and +negative numbers. The following exercise gives you exposure to the signed +integral types in C#. + +#### Prepare your coding environment + +You're using this C# console project to create, build, and run code samples +during this module. + +#### Use the MinValue and MaxValue properties for each signed integral type + +Program.cs should be empty. If it isn't, select and delete all code lines. + +To see the value ranges for the various data types, type the following code +into the code editor. + +```cs +Console.WriteLine("Signed integral types:"); + +Console.WriteLine($"sbyte : {sbyte.MinValue} to {sbyte.MaxValue}"); +Console.WriteLine($"short : {short.MinValue} to {short.MaxValue}"); +Console.WriteLine($"int : {int.MinValue} to {int.MaxValue}"); +Console.WriteLine($"long : {long.MinValue} to {long.MaxValue}"); +``` + +The Program.cs file must be saved before building or running the code. + +At the Terminal command prompt, to run your code, type `dotnet run` and then +press Enter. + +You should see the following output: + +```txt +Signed integral types: +sbyte : -128 to 127 +short : -32768 to 32767 +int : -2147483648 to 2147483647 +long : -9223372036854775808 to 9223372036854775807 +``` + +For most non-scientific applications, you likely only need to work with int. +Most of the time, you won't need more than a positive to negative 2.14 billion +whole numbers. + +### Unsigned integral types + +An unsigned type uses its bytes to represent only positive numbers. The +remainder of the exercise introduces the unsigned integral types in C#. + +#### Use the MinValue and MaxValue properties for each unsigned integral type + +Below the previous code passage, add the following code: + +```cs +Console.WriteLine(""); +Console.WriteLine("Unsigned integral types:"); + +Console.WriteLine($"byte : {byte.MinValue} to {byte.MaxValue}"); +Console.WriteLine($"ushort : {ushort.MinValue} to {ushort.MaxValue}"); +Console.WriteLine($"uint : {uint.MinValue} to {uint.MaxValue}"); +Console.WriteLine($"ulong : {ulong.MinValue} to {ulong.MaxValue}"); +``` + +Save your code file, and then run your code. + +You should see the following output: + +```txt +Signed integral types: +sbyte : -128 to 127 +short : -32768 to 32767 +int : -2147483648 to 2147483647 +long : -9223372036854775808 to 9223372036854775807 + +Unsigned integral types: +byte : 0 to 255 +ushort : 0 to 65535 +uint : 0 to 4294967295 +ulong : 0 to 18446744073709551615 +``` + +While a given data type can be used for many cases, given the fact that the +`byte` data type can represent a value from 0 to 255, it's obvious that this is +intended to hold a value that represents a byte of data. Data stored in files +or data transferred across the internet is often in a binary format. When +working with data from these external sources, you need to receive data as an +array of bytes, then convert them into strings. Many of the methods in the .NET +Class Library that deal with encoding and decoding data requires you handle byte +arrays. + +### Recap + +- An integral type is a simple value data type that can hold whole numbers. +- There are signed and unsigned numeric data types. Signed integral types use 1 +bit to store whether the value is positive or negative. +- You can use the `MaxValue` and `MinValue` properties of numeric data types to +evaluate whether a number can fit in a given data type. + +--- + +## Exercise + +### Discover floating-point types + +In this exercise, you work with floating-point data types to learn about the +nuanced differences between each data type. + +A floating point is a simple value type that represents numbers to the right of +the decimal place. Unlike integral numbers, there are other considerations +beyond the maximum and minimum values you can store in a given floating-point +type. + +#### Evaluate floating-point types + +First, you must consider the digits of precision each type allows. Precision is +the number of value places stored after the decimal point. + +Second, you must consider the manner in which the values are stored and the +impact on the accuracy of the value. For example, `float` and `double` values are +stored internally in a binary (base 2) format, while `decimal` is stored in a +decimal (base 10) format. Why does this matter? + +Performing math on binary floating-point values can produce results that may +surprise you if you're used to decimal (base 10) math. Often, binary +floating-point math is an approximation of the real value. Therefore, `float` and +`double` are useful because large numbers can be stored using a small memory +footprint. However, `float` and `double` should only be used when an +approximation is useful. For example, being a few thousandths off when +calculating the splatter of a snowball in a video game is close enough. + +When you need more a more precise answer, you should use `decimal`. Each value +of type `decimal` has a relatively large memory footprint, however performing +math operations gives you a more precise result. So, you should use decimal +when working with financial data or any scenario where you need an accurate +result from a calculation. + +#### Use the MinValue and MaxValue properties for each signed float type + +- Delete or use the line comment operator `//` to comment out all of the code from +the previous exercises. + +- To see the value ranges for the various data types, update your code in the +editor as follows: + +```cs +Console.WriteLine(""); +Console.WriteLine("Floating point types:"); +Console.WriteLine($"float : {float.MinValue} to {float.MaxValue} (with ~6-9 digits of precision)"); +Console.WriteLine($"double : {double.MinValue} to {double.MaxValue} (with ~15-17 digits of precision)"); +Console.WriteLine($"decimal: {decimal.MinValue} to {decimal.MaxValue} (with 28-29 digits of precision)"); +``` + +The Program.cs file must be saved before building or running the code. + +At the Terminal command prompt, to run your code, type `dotnet run` and then +press Enter. + +You should see the following output: + +```txt +Floating point types: +float : -3.402823E+38 to 3.402823E+38 (with ~6-9 digits of precision) +double : -1.79769313486232E+308 to 1.79769313486232E+308 (with ~15-17 digits of precision) +decimal: -79228162514264337593543950335 to 79228162514264337593543950335 (with 28-29 digits of precision) +``` + +As you can see, `float` and `double` use a different notation than is used by +`decimal` to represent its largest and smallest possible values. But what does +this notation mean? + +#### Deciphering large floating-point values + +Because floating-point types can hold large numbers with precision, their +values can be represented using "E notation", which is a form of scientific +notation that means "times 10 raised to the power of." So, a value like `5E+2` +would be the value 500 because it's the equivalent of `5 x 10^2`, or `5 x 10²`. + +### Recap + +- A floating-point type is a simple value data type that can hold fractional +numbers. +- Choosing the right floating-point type for your application requires you to +consider more than just the maximum and minimum values that it can hold. You +must also consider how many values can be preserved after the decimal, how the +numbers are stored, and how their internal storage affects the outcome of math +operations. +- Floating-point values can sometimes be represented using "E notation" when +the numbers grow especially large. +- There's a fundamental difference in how the compiler and runtime handle +decimal as opposed to float or double, especially when determining how much +accuracy is necessary from math operations. + +--- + +## Exercise - Discover reference types + +Reference types include arrays, classes, and strings. Reference types are +treated differently from value types regarding the way values are stored when +the application is executing. + +In this exercise, you learn how reference types are different from value types, +and how to use the `new` operator to associate a variable with a value in the +computer's memory. + +### How reference types are different from value types + +A value type variable stores its values directly in an area of storage called +the stack. The stack is memory allocated to the code that is currently running +on the CPU (also known as the stack frame, or activation frame). When the stack +frame has finished executing, the values in the stack are removed. + +A reference type variable stores its values in a separate memory region called +the heap. The heap is a memory area that is shared across many applications +running on the operating system at the same time. The .NET Runtime communicates +with the operating system to determine what memory addresses are available, and +requests an address where it can store the value. The .NET Runtime stores the +value, and then returns the memory address to the variable. When your code uses +the variable, the .NET Runtime seamlessly looks up the address stored in the +variable, and retrieves the value that's stored there. + +You'll next write some code that illustrates these ideas more clearly. + +### Define a reference type variable + +Delete or use the line comment operator `//` to comment out all of the code +from the previous exercises. + +Update your code in the editor as follows: + +```cs +int[] data; +``` + +The previous code defines a variable that can hold a value of type int array. + +At this point, `data` is merely a variable that could hold a reference, or +rather, a memory address of a value in the heap. Because it's not pointing to a +memory address, it's called a null reference. + +Create an instance of `int` array using the `new` keyword + +Update your code in the editor to create and assign a new instance of `int` +array, using the following code: + + +```cs +int[] data; +data = new int[3]; +``` + +The `new` keyword informs .NET Runtime to create an instance of `int` array, +and then coordinate with the operating system to store the array sized for +three int values in memory. The .NET Runtime complies, and returns a memory +address of the new `int` array. Finally, the memory address is stored in the +variable data. The `int` array's elements default to the value `0`, because that +is the default value of an `int`. + +Modify the code example to perform both operations in a single line of code + +The two lines of code in the previous step are typically shortened to a single +line of code to both declare the variable, and create a new instance of the +`int` array. Modify the code from step 3 to the following. + +```cs +int[] data = new int[3]; +``` + +While there's no output to observe, hopefully this exercise added clarity to +how the C# syntax relates to the steps of the process for working with +reference types. + +#### What's different about the C# string data type? + +The `string` data type is also a reference type. You might be wondering why a +`new` operator wasn't used when declaring a string. This is purely a convenience +afforded by the designers of C#. Because the `string` data type is used so +frequently, you can use this format: + +```cs +string shortenedString = "Hello World!"; +Console.WriteLine(shortenedString); +``` + +Behind the scenes, however, a new instance of `System.String` is created and +initialized to "Hello World!". + +#### Practical concerns using value and reference types + +1. **Value Type (int)**: In this example, `val_A` and `val_B` are integer value types. + + ```cs + int val_A = 2; + int val_B = val_A; + val_B = 5; + + Console.WriteLine("--Value Types--"); + Console.WriteLine($"val_A: {val_A}"); + Console.WriteLine($"val_B: {val_B}"); + ``` + + You should see the following output: + + ```txt + --Value Types-- + val_A: 2 + val_B: 5 + ``` + + When `val_B` = `val_A` is executed, the value of `val_A` is copied and stored in + `val_B`. So, when `val_B` is changed, `val_A` remains unaffected. + +2. **Reference Type (array)**: In this example, `ref_A` and `ref_B` are array +reference types. + + ```cs + int[] ref_A= new int[1]; + ref_A[0] = 2; + int[] ref_B = ref_A; + ref_B[0] = 5; + + Console.WriteLine("--Reference Types--"); + Console.WriteLine($"ref_A[0]: {ref_A[0]}"); + Console.WriteLine($"ref_B[0]: {ref_B[0]}"); + ``` + + You should see the following output: + + ```txt + --Reference Types-- + ref_A[0]: 5 + ref_B[0]: 5 + ``` + + When `ref_B` = `ref_A` is executed, `ref_B` points to the same memory + location as `ref_A`. So, when `ref_B[0]` is changed, `ref_A[0]` also changes + because they both point to the same memory location. This is a key difference + between value types and reference types. + +### Recap + +- Value types can hold smaller values and are stored in the stack. Reference +types can hold large values, and a new instance of a reference type is created +using the `new` operator. Reference type variables hold a reference (the memory +address) to the actual value stored in the heap. +- Reference types include arrays, strings, and classes. + +--- + +## Choose the right data type + +You've been introduced to the difference between value types and reference type +s, as well as integral and floating point types. + +Suppose your job is to build a new application that retrieves, manipulates, and +stores different types of data. Which data types do you use? + +In some cases, it is an easy choice. For example, when you need to work with +text, then you default to using the `string` data type unless you need to +perform a significant amount of concatenation. + +But what about working with numeric data? There are 11 different options. How +do you choose the right data type? + +### Choose the right data type + +With so many data types to choose from, what criteria should you use to choose +the right data type for the particular situation? + +When evaluating your options, you must weigh several important considerations. +Often there's no one single correct answer, but some answers are more correct +than others. + +#### Choose the data type that meets the boundary value range requirements of your application + +Your choice of a data type can help to set the boundaries for the size of the +data you might store in that particular variable. For example, if you know a +particular variable should only store a number between 1 and 10,000 otherwise +it's outside of the boundaries of what would be expected, you would likely +avoid `byte` and `sbyte` since their ranges are too low. + +Furthermore, you would likely not need `int`, `long`, `uint`, and `ulong` +because they can store more data than is necessary. Likewise, you would +probably skip `float`, `double`, and `decimal` if you didn't need fractional +values. You might narrow it down to `short` and `ushort`, of which both may be +viable. If you're confident that a negative value would have no meaning in your +application, you might choose `ushort` (positive unsigned integer, 0 to 65,535). +Now, any value assigned to a variable of type `ushort` outside of the boundary +of 0 to 65535 would throw an exception, thereby subtly helping you enforce a +degree of sanity checking in your application. + +#### Start with choosing the data type to fit the data (not to optimize performance) + +You may be tempted to choose the data type that uses the fewest bits to store +data thinking it improves your application's performance. However, some of the +best advice related to application performance (that is, how fast your +application runs) is to not "prematurely optimize". You should resist the +temptation to guess at the parts of your code, including the selection of data +types that may impact your application's performance. + +Many assume that because a given data type stores less information it must use +less of the computer's processor and memory than a data type that stores more +information. Instead, you should choose the right fit for your data, then later +you can empirically measure the performance of your application using special +software that provides factual insights to the parts of your application that +negatively impact performance. + +#### Choose data types based on the input and output data types of library functions used + +Suppose you want to work with a span of years between two dates. Since the +application is a business application, you might determine that you only need a +range from about 1960 to 2200. You might think to try to work with byte since +it can represent numbers between 0 and 255. + +However, when you look at the built-in methods on the `System.TimeSpan` and +`System.DateTime` classes, you realize they mostly accept values of type +`double` and `int`. If you choose `sbyte`, you'll constantly be casting back +and forth between `sbyte` and `double` or `int`. In this case, it might make +more sense to choose `int` if you don't need subsecond precision, and `double` +if you do need subsecond precision. + +#### Choose data types based on impact to other systems + +Sometimes, you must consider how the information will be consumed by other +applications or other systems like a database. For example, SQL Server's type +system is different from C#'s type system. As a result, some mapping between +the two must happen before you can save data into that database. + +If your application's purpose is to interface with a database, then you would +likely need to consider how the data is stored and how much data is stored. The +choice of a larger data type might impact the amount (and cost) of the physical +storage required to store all the data your application will generate. + +#### When in doubt, stick with the basics + +While you've looked at several considerations, as you're getting started, for +simplicity's sake you should prefer a subset of basic data types, including: + +- `int` for most whole numbers +- `decimal` for numbers representing money +- `bool` for true or false values +- `string` for alphanumeric value + +#### Choose specialty complex types for special situations + +Don't reinvent data types if one or more data type already exists for a given +purpose. The following examples identify where a specific .NET data types can +be useful: + +- `byte`: working with encoded data that comes from other computer systems or +using different character sets. +- `double`: working with geometric or scientific purposes. double is used +frequently when building games involving motion. +- `System.DateTime` for a specific date and time value. +- `System.TimeSpan` for a span of years / months / days / hours / minutes / +seconds / milliseconds. + +### Recap + +There are considerations when choosing data types for your code, and often more +than one option. Think through your choices, and unless you have a good reason, +try to stick with the basic types like `int`, `decimal`, `string`, and `bool`. + +## Summary + +Choosing the right data type for your application is a vital programming skill. +Your goal was to understand the differences between each data type to make an +informed decision on the data types in your code. + +You started building a mental model of how data is stored as your application +executes. You have experience working with new integral and floating point data +types. You have criteria you can use when deciding which data types to employ +in your code. Finally, you understand why you need to use the `new` keyword when +creating instances of reference types. diff --git a/020_data_types/test_app/Program.cs b/020_data_types/test_app/Program.cs new file mode 100644 index 0000000..bda0684 --- /dev/null +++ b/020_data_types/test_app/Program.cs @@ -0,0 +1,36 @@ +Console.WriteLine("-------------------------------------------"); +Console.WriteLine("Signed integral types:"); +Console.WriteLine($"sbyte : {sbyte.MinValue} to {sbyte.MaxValue}"); +Console.WriteLine($"short : {short.MinValue} to {short.MaxValue}"); +Console.WriteLine($"int : {int.MinValue} to {int.MaxValue}"); +Console.WriteLine($"long : {long.MinValue} to {long.MaxValue}"); +Console.WriteLine("-------------------------------------------"); +Console.WriteLine("Unsigned integral types:"); +Console.WriteLine($"byte : {byte.MinValue} to {byte.MaxValue}"); +Console.WriteLine($"ushort : {ushort.MinValue} to {ushort.MaxValue}"); +Console.WriteLine($"uint : {uint.MinValue} to {uint.MaxValue}"); +Console.WriteLine($"ulong : {ulong.MinValue} to {ulong.MaxValue}"); + +Console.WriteLine("-------------------------------------------"); +Console.WriteLine("Floating point types:"); +Console.WriteLine($"float : {float.MinValue} to {float.MaxValue} (with ~6-9 digits of precision)"); +Console.WriteLine($"double : {double.MinValue} to {double.MaxValue} (with ~15-17 digits of precision)"); +Console.WriteLine($"decimal: {decimal.MinValue} to {decimal.MaxValue} (with 28-29 digits of precision)"); +Console.WriteLine("-------------------------------------------"); +int val_A = 2; +int val_B = val_A; +val_B = 5; + +Console.WriteLine("--Value Types--"); +Console.WriteLine($"val_A: {val_A}"); +Console.WriteLine($"val_B: {val_B}"); + +int[] ref_A= new int[1]; +ref_A[0] = 2; +int[] ref_B = ref_A; +ref_B[0] = 5; + +Console.WriteLine("--Reference Types--"); +Console.WriteLine($"ref_A[0]: {ref_A[0]}"); +Console.WriteLine($"ref_B[0]: {ref_B[0]}"); +Console.WriteLine("-------------------------------------------"); diff --git a/020_data_types/test_app/test_app.csproj b/020_data_types/test_app/test_app.csproj new file mode 100644 index 0000000..2150e37 --- /dev/null +++ b/020_data_types/test_app/test_app.csproj @@ -0,0 +1,10 @@ + + + + Exe + net8.0 + enable + enable + + + diff --git a/README.md b/README.md index d62463c..dd62589 100644 --- a/README.md +++ b/README.md @@ -24,3 +24,4 @@ Following - [Looping logic using the do-while and while](./017_Looping_logic_using_do-while_and_while/017_csharp.md) - [Conditional branching and looping](./018_Conditional_branching_and_looping/018_csharp.md) - [Branching and looping structures](./019_branching_and_looping_structures/019_csharp.md) +- [Choose the correct data type](/020_data_types/020_csharp.md)