Chapter 2 Language Fundamentals
Chapter 2 Language Fundamentals
Data Type
.NET Framework supports multiple programming languages and code written in one
language may interoperate with code written in other languages. In order to facilitate this
language interoperability, the .NET Framework designer defines the Common Type
System (CTS).
Common Type System (CTS).
The CTS specifies all data types supported by the runtime (that is, the CLR). A
requirement for a program written in one language to be used by programs written in
other languages is that the former should only expose CTS-compliant types.
Table: C# intrinsic types
C# Type
.NET
Size Size Values/Range
Type
(byt (Bits
es) )
byte
Byte
0 to 255.
char
Char
16
bool
Boolean
true or false.
sbyte*
SByte
-128 to 127.
short
Int16
16
-32,768 to 32,767.
ushort*
UInt16
16
0 to 65,535.
int
Int32
32
-2,147,483,648 to 2,147,483,647
uint*
UInt32
32
0 to 4,294,967,295
float
Single
32
-3.402823e38 to 3.402823e38
double
Double
64
-1.79769313486232e308 to
1.79769313486232e308
decimal
Decimal
16
128
long
Int64
32
-9,223,372,036,854,775,808 to
9,223,372,036,854,775,807
ulong*
UInt64
32
0 to 18,446,744,073,709,551,615
string
String
A sequence of characters
object
Object
C# is rich enough to support intrinsic data types that are both CTS-compliant and CTSnoncompliant. However, C# codes that expose non-CTS-compliant data types may not
interoperate well with codes written in another language.
The four intrinsic types with an asterisk (sbyte, ushort, uint, ulong) are not CTScompliant,
Floating-Point Literals
Numbers such as 0.4, 1.23, 0.5e10 are floating point numbers. A floating point number
has the following parts:
a whole number part
a decimal point
a fractional part
an optional exponent
In the .NET Framework, there are two types of floating points, float and double.
To express float literals, you use one of the following formats.
Digits . [Digits] [ExponentPart] f_or_F
. Digits [ExponentPart] f_or_F
Digits ExponentPart f_or_F
Digits [ExponentPart] f_or_F
where
ExponentIndicator
is either e or E and
SignedInteger
is .
Signopt Digits
and
Sign
Character Literals
Here are character literals that are escape sequences:
'\b'
'\t'
'\\'
'\''
'\"'
'\n'
'\r'
In addition, C# allows you to escape a Unicode character so that you can express a
Unicode character using a sequence of ASCII characters. For example, the Unicode code
for the character is 2299.
You can write the following character literal to express this character:
''
However, if you do not have the tool to produce that character using your keyboard, you
can escape it like so:
'\u2299'
Primitive Conversions
There are two other kinds of primitive conversions, the widening conversion and the
narrowing conversion.
The Widening Conversion
The widening primitive conversion occurs from one type to another type whose size is
the same or larger than that of the first type
byte to short, int, long, float, or double
short to int, long, float, or double
char to int, long, float, or double
int to long, float, or double
long to float or double
float to double
A widening conversion from an integer type to another integer type will not risk
information loss.
The widening primitive conversion occurs implicitly. You do not need to do anything in
your code.
For example:
int a = 10;
long b = a; // widening conversion
The narrowing conversion may incur information loss, if the converted value is larger
than the capacity of the target type.
ReadLine returns the text the user entered. Then, the string is used as an argument to
class Converts ToInt32 method, which converts this sequence of characters into data of
type int. In this case, method ToInt32 returns the int representation of the users input.
Technically, the user can type anything as the input value. ReadLine will accept it and
pass it off to the ToInt32 method. This method assumes that the string contains a valid
integer value.
In this app, if the user types a noninteger value, a runtime logic error called an
exception will occur and the app will terminate.
Operators
Table list C# operators.
=
==
+
+=
>
<=
-=
<
>=
*
*=
!
!=
/
/=
~
&&
&
&=
?
||
|
|=
:
++
^
^=
-%
%=
<<
<<=
>>
>>=
>>>
>>>=
Unary Operators
Unary operators operate on one operand. There are six unary operators,
Unary Minus Operator
The unary minus operator returns the negative of its operand. The operand must be a
numeric primitive or a variable of a numeric primitive type
float x = 4.5f;
float y = -x;
Increment Operator ++
This operator increments the value of its operand by one. The operand must be a
variable of a numeric primitive type.
The operator can appear before or after the operand.
If the operator appears before the operand, it is called the prefix increment operator .
If it is written after the operand, it becomes the postfix increment operator.
As an example, here is a prefix increment operator in action:
int x = 4;
++x;
//After ++x, the value of x is 5.
With the postfix increment operator, the value of the operand (x) is incremented after
the value of the operand is assigned to another variable (y).
Decrement Operator -Similar to above.
Logical Complement Operator !
This operator can only be applied to a bool primitive or an instance of System.Boolean. The
value of this operator is true if the operand isfalse, and false if the operand is true. For
example:
bool x = false;
bool y = !x;
// at this point, y is true and x is false
sizeof(int) returns 4.
Arithmetic Operators
There
and
Equality Operators
There are two equality operators,
== (equal to) and
!= (not equal to),
both operating on two operands that can be integers, floating points, characters, or bool.
The outcome of equality operators is a boolean.
For example,
int a = 5;
int b = 5;
bool c = a == b;
Relational Operators
There are five relational operators:
<, >, <=, and >=.
The <, >, <=, and >= operators operate on two operands whose types must be
convertible to a numeric primitive type. Relational operations return a bool.
Conditional Operators
There are three conditional operators :
AND operator, &&,
OR operator, ||,
? : operator.
The ? : Operator
This operator operates on three operands.
The syntax is
expression1 ? expression2 : expression3
expression1
expression2
boolean.
If
expression1
evaluates to true,
Shift Operators
A shift operator takes two operands whose type must be convertible to an integer
primitive.
The left-hand operand is the value to be shifted, the right-hand operand indicates the
shift distance.
There are three types of shift operators:
>>>
which is equal to 8.
Assignment Operators
There are twelve assignment operators :
=
+=
-=
*=
/=
%=
<<=
>>=
>>>=
&=
^=
|=
Assignment operators take two operands whose type must be of an integral primitive.
The two-part assignment operators work by applying the first operator to both operands
and then assign the result to the left-hand operand.
For example
x += 5 is the same as x = x + 5.
x &= 5 produces the same result as x = x &= 5.
Operator Precedence
Table lists all the operators in the order of precedence. Operators in the same column
have equal precedence.
Operator
postfix operators
unary operators
creation or cast
new (type)expr
multiplicative
* / %
additive
+ -
shift
relational
equality
== !=
bitwise AND
&
bitwise exclusive
OR
bitwise inclusive
OR
logical AND
&&
logical OR
||
conditional
? :
assignment
Promotion
Some unary operators (such as +, -, and ~) and binary operators (such as +, -, *, /) cause
automatic promotion, i.e. elevation to a wider type such as from byte to int.
Consider the following code:
sbyte x = 5;
sbyte y = -x; // error
The second line surprisingly causes an error even though a sbyte can accommodate -5.
The reason for this is the unary operator - causes the result of -x to be promoted to int.
To rectify the problem, either change y to int or perform an explicit narrowing conversion
like this.
sbyte x = 5;
sbyte y = (sbyte) x;
For unary operators, if the type of the operand is byte, sbyte, short, or char, the
outcome is promoted to int.
For binary operators, the promotion rules are as follows.
If any of the operands is of type byte, sbyte, or short, then both operands
will be converted to int and the outcome will be an int.
If any of the operands is of type double, then the other operand is
converted to double and the outcome will be a double.
If any of the operands is of type float, then the other operand is converted
to float and the outcome will be a float.
If any of the operands is of type long, then the other operand is converted
to long and the outcome will be a long.
You can fix this by changing z to int or perform an explicit narrowing conversion of x + y,
such as
short z = (short) (x + y);
Note that the parentheses around x + y is required, otherwise only x would be converted
to int and the result of addition of a short and an int will be an int.
Also note that since C# uses Unicode characters, you can simply define the variable pi as
if you dont think typing it is harder than typing pi.
const float = (float) 22 / 7;
Comments
There are two types of comments in C#, both with syntax similar to comments in C and
C++.
Traditional comments. Enclose a traditional comment in /* and */.
End-of-line comments. Use double slashes (//) which causes the rest of the
line after // to be ignored by the compiler.
On the other hand, end-of-line comments can contain anything, including the sequences
of characters /* and */, such as this:
// /* this comment is okay */
Simple-Type
Simple-Type structs
Each simple type (see Table, Simple Types) has a corresponding struct in namespace
System that defines the simple type.
These structs are called Boolean, Byte, SByte, Char, Decimal, Double, Single, Int16, Uint16,
Int32, UInt32, Int64 and Uint64. (Refer to section Data Type above). Types declared with
keyword struct are value types.
Simple types are actually aliases for their corresponding structs, so a variable of a
simple type can be declared using either
the keyword for that simple type or
the struct name
e.g., int and Int32 are interchangeable.
The methods related to a simple type are located in the corresponding struct (e.g.,
method Parse, which converts a string to an int value, is located in struct Int32).
Boxing (simple-type)
In a boxing conversion, the simple-type value is copied into an object so that
the simple-type value can be manipulated as an object.
Boxing conversions can be performed either explicitly or implicitly as shown in the
following statements:
int i = 5; // create an int value
object object1 = ( object ) i; // explicitly box the int value
object object2 = i; // implicitly box the int value
After executing the preceding code, both object1 and object2 refer to two different
objects that contain a copy of the integer value in int variable i.
Unboxing(simple-type)
An unboxing conversion can be used to explicitly convert an object reference
to a simple value,
int int1 = ( int ) object1; // explicitly unbox the int value
Explicitly attempting to unbox an object reference that does not refer to the correct
simple value type causes an InvalidCastException.