Chapter 2 demonstrated a very simple C# program. Nonetheless, that little program was complex enough that I had to skip some of the pertinent details. This chapter illuminates these details by delving more deeply into the syntax and structure of the C# language itself.
This chapter discusses the type system in C#, drawing a distinction
between built-in types (int
,
bool
, etc.) versus user-defined types (types you
create as classes and interfaces). The chapter also covers
programming fundamentals such as how to create and use variables and
constants. It then goes on to introduce enumerations, strings,
identifiers, expressions, and statements.
The second part of the chapter explains and demonstrates the use of
flow control statements, using the if
,
switch
, while
,
do...while
, for
, and
foreach
statements. Also discussed are operators,
including the assignment, logical, relational, and mathematical
operators. This is followed by an introduction to namespaces and a
short tutorial on the C# precompiler.
Although C# is principally concerned with the creation and manipulation of objects, it is best to start with the fundamental building blocks: the elements from which objects are created. These include the built-in types that are an intrinsic part of the C# language as well as the syntactic elements of C#.
C# is a
strongly typed language. In a strongly typed language you must
declare the type of each object you create (e.g., integers, floats,
strings, windows, buttons, etc.), and the compiler will help you
prevent bugs by enforcing that only data of the right type is
assigned to those objects. The type of an object signals to the
compiler the size of that object (e.g., int
indicates an object of 4 bytes) and its capabilities (e.g., buttons
can be drawn, pressed, and so forth).
C# 1.1 programmers take note: until Version 2, .NET was strongly typed in everything except collections. With the addition of generics, however, it is now easy to create strongly typed collection classes, as shown in Chapter 9.
Like C++ and Java, C# divides types into two sets: intrinsic (built-in) types that the language offers and user-defined types that the programmer defines.
C# also divides the set of types into two other categories: value types and reference types.[1] The principal difference between value and reference types is the manner in which their values are stored in memory. A value type holds its actual value in memory allocated on the stack (or it is allocated as part of a larger reference type object). The address of a reference type variable sits on the stack, but the actual object is stored on the heap.
C
and
C++
programmers
take
note: in C#, there is no explicit indication
that an object is a reference type (i.e., no use of the
&
operator). Also, pointers
aren’t normally used (but see Chapter 22 for the exception to this rule).
If you have a very large object, putting it on the heap has many advantages. Chapter 4 discusses the various advantages and disadvantages of working with reference types; the current chapter focuses on the intrinsic value types available in C#.
In C#, the size and format of the storage for different intrinsic types (e.g., int) are platform-independent and consistent across all .NET languages.
C# also supports C++ style pointer types, but these are used only when working with unmanaged code. Unmanaged code is created outside of the .NET platform (for example, COM objects; working with COM objects is discussed in Chapter 22).
The C# language offers the usual cornucopia of intrinsic (built-in) types one expects in a modern language, each of which maps to an underlying type supported by the .NET CLS. Mapping the C# primitive types to the underlying .NET type ensures that objects created in C# can be used interchangeably with objects created in any other language compliant with the .NET CLS, such as VB.NET.
Java programmers take note: C# has a broader range of basic types than Java. The C# decimal type is notable, and is useful for financial calculations.
Each type has a specific and unchanging size. Unlike with C++, a C#
int
is always 4 bytes because it maps to an
Int32
in the .NET CLS. Table 3-1 lists the built-in value types offered by
C#.
Table 3-1. C# built-in value types
C and C++ programmers take
note: in C#, Boolean variables can only have the values
true
or false
. Integer values
don’t equate to Boolean values in C# and there is no
implicit conversion.
In addition to these primitive types, C# has two other value types:
enum
(considered later in this chapter) and
struct
(see Chapter 4).
Chapter 4 also discusses other subtleties of
value types, such as forcing value types to act as reference types
through a process known as
boxing, and that
value types don’t
“inherit.”
C and C++ programmers take note: C# manages all memory with a garbage collection system—there is no delete operator.
Typically
you decide which size
integer to use
(short
, int
, or
long
) based on the magnitude of the value you want
to store. For example, a ushort
can only hold
values from 0 through 65,535, while a uint
can
hold values from 0 through 4,294,967,295.
That said, memory is fairly cheap, and programmer time is
increasingly expensive; most of the time you’ll
simply declare your variables to be of type int
,
unless there is a good reason to do otherwise.
Integers are often faster than smaller types because modern CPUs are optimized for dealing with them. Further, because of padding inserted for alignment, there’s often no space gain to be had from smaller datatypes.
Float
, double
, and
decimal
offer varying degrees of size and
precision. For most small fractional numbers,
float
is fine. Note that the compiler assumes that
any number with a decimal point is a double unless you tell it
otherwise. To assign a literal float
, follow the
number with the letter f
(assigning values to
literals is discussed in detail later in this chapter):
*Footnote: You need to use the f
suffix for a float
, however there are no other suffixes required for other types.
float someFloat = 57f;
The
char
type represents a Unicode character. char
literals
can be simple, Unicode, or escape characters enclosed by single quote
marks. For example, A
is a simple character while
u0041
is a Unicode character. Escape characters
are special two-character tokens in which the first character is a
backslash. For example,
is a horizontal tab.
The common escape
characters are shown in Table 3-2.