The course is part of this learning path
In this course, we look at how different types of data are stored using variables within a C# program. C# is a strongly typed language, meaning when you manipulate data in code, you must keep the data in variables that are specifically designed to hold that kind of data. For example, text is stored in a string data type and a letter in a char. There are over ten different numeric data types that vary in size and accuracy or precision of the data they can faithfully represent. We investigate some of the quirks in dealing with fractional numbers in a computer's binary environment. There are in-depth code examples for each of these topics to illustrate the discussed concepts and make you more familiar with C# programming in general.
This course builds upon the key concepts and examples covered in the Introduction to C# course. It includes guided demonstrations to give you practical knowledge of how to handle the concepts covered.
Learning Objectives
- Understand what variables are and how they're stored
- Learn about data types for storing and manipulating text values
- Learn about the various data types for storing and manipulating whole and fractional numbers
- Learn about variables for storing multiple values of the same data type
Intended Audience
This course is intended for anyone who has a basic understanding of C# and now wants to build upon that knowledge.
Prerequisites
This course carries on from our Introduction to C# course, so we suggest taking that one first if you haven't already done so.
Resources
Code examples used in demos on GitHub: https://github.com/cloudacademy/csharp-datatypes-variables
Let's put into practice what we've learned about integers. I'll start with a new C#.NET 5.0 console project called integers. The first thing I'll do is create variables for each of the signed integer types. So that will be byte, short, int, and long. For each of those variables, I will assign the maximum value for each of those data types using the max value property within .NET. I'll write out the variable name and the value it contains to the console. Having written out each variable's value, let's now write out each variable's size using the sizeof function.
Usually, you wouldn't use sizeof with standard data types as we know how big they are. Sizeof is intended to be used with more complex user-defined objects, but it serves our purpose here, returning each integer variable's size in bytes. When we run the program, the output is as we saw in the earlier lecture, with byte having a maximum value of 255, so 256 values including zero and a size of obviously one byte.
Grande, the long data type variable is eight bytes and is storing a vast number. We can assign the Piccolo value of 255 to the Grande variable as byte is smaller than long. Now we have two variables Piccolo and Grande, both holding 255, so the combined value of 510 should easily fit into the regular int variable. When I try to do this, the C# compiler won't allow as I can't assign a long value into an int variable. Two integer variables of different types combined in an expression will result in a larger data type.
The C# compiler has no idea what values will be stored in variables, so it correctly assumes that something bad will happen if I try to assign the value of a large data type into a smaller one. You can get around this by explicitly telling the compiler that one data type should be treated as another data type. This kind of type conversion is called casting and involves prefixing a variable or expression with the target data type enclosed in brackets. Casting is not unique to C# and is present in most programming languages. You cannot cast any data type into any other data type, but it works well enough within integer types.
When I run the program now, sure enough, we get the result of 510 as expected. I'll comment out these last three lines by highlighting them and using the shortcut of control+K+C, so that regular now contains the original int max value. I will show you some unusual behavior that illustrates why casting a larger data type into a smaller one is not a good idea and why the C# compiler doesn't allow you to assign a long to an int.
Let's write out regular's value which is the maximum value of an int data type, and then add one to it and write it out again. No, that is not witchcraft. Remember I said for signed numbers, there was one bit reserved to indicate whether the number is positive or negative. What's happened here is analogous to adding one to 99, where you go from two digits to three digits, and the existing or right-hand digits roll over to zero. In this case, adding one, we have done the same thing and pushed the extra digit into the bit that indicates positive or negative, thus going from int's maximum value to its minimum value.
Before we continue, I just want to show you another way of adding one to a value by using the increment operator, ++. We will see this notation used extensively in future lectures to increment a value by one. To demonstrate what I'm talking about at the binary level, let's perform this operation again, but this time output the result as binary text.
First, I'll set regular back to the int max value, as it's just been incremented. I'm doing this by using .NET's built-in conversion functionality of the convert class. Here I'm saying convert the regular int variable to a string outputting the result as a base two string. I'll remove the plus one text so that the output lines up and we can see the extra bit. So, just like adding one to 99, when we add one to the max value, we end up with one additional bit, and all the others have flipped over to zero giving us the equivalent of the minimum value. I'll do the same with an unsigned short variable.
Because all bits are used to represent the value in an unsigned integer data type when we add one to the maximum value, the same thing happens as did with the signed data type, except the one is effectively pushed out the end, leaving us with just zeros. While this is the default behavior for the C# compiler, you are not stuck with it. There are two options for getting the program to halt when this type of overflow error occurs.
In Visual Studio, you can go into the project properties build page and click the advanced button and then tick the check for arithmetic overflow box. Now when I run the program and try to increment regular past the maximum possible value, we get an overflow exception error. I'll stop the debugger and uncheck the arithmetic overflow exception setting.
Another way is to use the checked function, which tests the value being assigned to a variable making sure it does not exceed its capacity. I'll have to revert back to adding one to regular and assigning it back to itself, as the in-place incrementing doesn't produce a result that can be passed as a parameter into the checked function. Again when I run the program, we correctly get the same overflow error.
Hallam is a software architect with over 20 years experience across a wide range of industries. He began his software career as a Delphi/Interbase disciple but changed his allegiance to Microsoft with its deep and broad ecosystem. While Hallam has designed and crafted custom software utilizing web, mobile and desktop technologies, good quality reliable data is the key to a successful solution. The challenge of quickly turning data into useful information for digestion by humans and machines has led Hallam to specialize in database design and process automation. Showing customers how leverage new technology to change and improve their business processes is one of the key drivers keeping Hallam coming back to the keyboard.