All data types in .NET are implemented as classes within the System namespace. One such data type is System.Byte, which implements an 8-bit integer value, just like we discussed earlier. It holds integer values from 0 to 255. These values are always stored using eight bits of binary data, but they magically appear in decimal form whenever you ask them to be presented.
The .NET Framework includes 15 core interpretive data types: eight for integers, three for decimal numbers, two for character data, one combined data type for dates and times, and a Boolean data type.
Integer Data Types
Based on the number of available data types (eight out of the 15 core types), you would think that most programmers worked with integers all day longand you'd be right. Whether it's actual user data or loop counters or status codes or the storage method for enumerated data types, integers show up everywhere in .NET code.
The range of values for an integer data type depends directly on the number of binary digits managed by that data type; the more digits, the bigger the range. Also, half of the integer data types store both positive and negative values (called "signed" integers), while the other half supports only positive numbers ("unsigned"). Table 6-1 lists the eight integer data types included with .NET, and their associated ranges.
Looking at these types another way, Table 6-2 shows the relationship between the types and their number of bits and range style.
Decimal Data Types
Once upon a time, life was happy. Strangers said "hello" when they met you on the street. Succulent fruit burst forth from trees. In short, God was in his heaven, and everything was right with the worldand then came fractions. At first, it didn't seem that bad, because so many fractions could be converted easily into a plain numeric form by inserting a "decimal point" in the number. became 0.5. became the longer yet smaller 0.25. became 0.3333 33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333...Hey, what's going on here? I can't write all of those 3s. The book would be 2,000 pages, or more. Eventually people discovered that in many cases, it just wasn't worth the bother of writing out all of the 3s, so they just stopped at some point, as in 0.33333333. It wasn't perfectly accurate, but it was good enough.
This is what life is like for computer-based decimal values. You can have perfect accuracyup to a point. After that, you have to settle for good enough. The .NET Framework includes three decimal data types. Two of them accept limited accuracy in exchange for a large range of values. The third has perfect accuracy, but its range is more limited. Table 6-3 documents these three types.
Character Data Types
Hey, check this out. ktuefghbiokh. Pretty cool, eh? That's the power of a computer in action managing text data. So efficient; so graceful; so lskjdfljsdfjl. Although computers are really number machines, they handle text just as well. Of course, it's really just you doing all of the wordsmithing. In fact, the computer isn't even smart enough to tell the difference between numbers and letters; it's all bits to the CPU. Pretty mindless, if you ask me. I mean, what's the use of having all that computing power if you can't even think. Despite all of their speed and technology, computers are still just lumps of silicon wrapped up in a nice package. The computer I'm typing on doesn't even know that I'm insulting it; I can type these things on and on, and there's nutten that thiz komputre cann due about itt.
The Framework includes two text-related data types: System.Char and System.String. The Char data type holds a single characterno more, no less. At 16 bits, it holds any of the thousands of Unicode characters.
The String data type allows up to about two billion Unicode characters to be "strung" together into one long text block. Although Char and String are different data types, you can easily move data back and forth between them, because they are both based on basic 16-bit Unicode characters.
Date and Time Data Type
The System.DateTime data type lets you store either date or time values (or both) as data. Internally, DateTime is just a simple integer counter that displays a converted date or time format when needed. As a number, it counts the number of "ticks" since 12:00 a.m. on January 1, 1 AD. Each "tick" is exactly 100 nanoseconds, so it's pretty precise. The maximum allowed date is December 31, 9999 in the Gregorian calendar.
Boolean Data Type
The System.Boolean data type represents the true essence of computer data: the bit. It holds one of two possible values: True or False. Shockingly, the data type actually requires two bytes of data space to keep track of that single bit of data.
It turns out that Boolean values are very important in programs. As a developer, you are always testing to see if various conditions are met before you process a block of code. All of these conditions eventually boil down to Boolean values and operations. .NET even has ways to easily migrate data between integer values and the Boolean data type. In such conversions, zero becomes False, while the world of all other possible values becomes True. When moving from Boolean to an integer equivalent, False becomes zero and True becomes 1. (If you ever use the C# language, you'll find that it converts True to 1, not 1. Internally in .NET, True does convert to 1, but for historical reasons, Visual Basic uses 1. This difference normally isn't a problem unless you store Boolean values as integers in a disk file and expect both Visual Basic and C# programs to interpret the data correctly.)
The System.Object Class
You already knew that .NET is an object-oriented development environment. What you probably didn't know is that some pranksters at Microsoft placed a bet to see if they could make the entire .NET system one big derived class. Well, the group that said it could be done won the bet. Everything in .NETall code and all datais derived from a single base class: System.Object. By itself, this class doesn't have too many features. It can tell you its name, its type, and whether two instances of an object are in fact one and the same object. Other than that, it isn't useful for much except to be used as a starting point for all other classes and types.
Because all classes in .NETincluding all data typesderive from System.Object, you can treat an instance of any class (or data type) as Object. The data will remember what type it really is, so if you have a System.Int32 posing as System.Object, you can change it back to System.Int32 later.
Value Types and Reference Types
Back in Chapter 1, you read about the difference between value types and reference types: value types are buckets that contain actual data, while reference types contain instructions on where you can find the actual data. In general, value types contain simple and small data values, whereas reference types point to large and complex data blocks. This isn't always true, but for most data you work with, it will be true.
System.Object is a reference type from which all other types and classes derive. This includes all of the core data types, so you would think that they would be reference types as well. But there is another class stuck in between System.Object and most of the data types. This class, System.ValueType, implements the basic definition and usage of a value type. Table 6-4 lists some of the differences between value and reference types.
(In addition to classes and structures, Visual Basic also defines "modules." The .NET documentation claims that modules are neither value types nor reference types.)
A value type can only contain data of its own type, but reference types can point to derived instances. This is important in .NET, because it was designed to allow a System.Object instance to refer to any data in an application. System.Object instances can refer to either value type or reference type data. For reference types, this is easy to understand because that instance will just point to some derived instance of itself. But if you assign a value type to a System.Object reference, .NET has to mark that instance in a special way to indicate that a reference type contains a value type. This process is called boxing, and the reverse process is called unboxing. You don't really need to know how it works, but if you ever appear on Jeopardy and select ".NET Data Types" for $500, you'll be able to give the right question.