Unit 2- Language Basics
Unit 2- Language Basics
Fifth
Technology SEMESTER
Chapter - 2
Sandeep Shrestha
1
Unit -2 C# Language Basics [12 Hrs]
Writing Console and GUI Applications; Identifiers and keywords; Writing comments; Data
Types; Expressions and Operators; Strings and Characters; Arrays; Variables and
Parameters; Statements (Declaration, Expression, Selection, Iteration and Jump
Statements); Namespaces
A First C# Program
Here is a program that multiplies 12 by 30 and prints the result, 360, to the screen. The
double forward slash indicates that the remainder of a line is a comment
Writing higher-level functions that call upon lower-level functions simplifies a pro- gram.
We can refactor our program with a reusable method that multiplies an integer by 12 as
follows:
Compilation
The C# compiler compiles source code, specified as a set of files with the .cs extension, into
an assembly. An assembly is the unit of packaging and deployment in .NET. An assembly
can be either an application or a library. A normal console or Windows application has a
Main method and is an .exe file.
A library is a .dll and is equivalent to an .exe without an entry point. Its purpose is to be
called upon (referenced) by an application or by other libraries. The .NET Framework is a
set of libraries.
The name of the C# compiler is csc.exe. You can either use an IDE such as Visual Studio to
compile, or call csc manually from the command line.
To compile manually, first save a program to a file such as MyFirstProgram.cs, and then go
to the command line and invoke csc (located in
C:\Windows\Microsoft.NET\Framework\v4.0.30319) as follows:
csc MyFirstProgram.cs
This produces an application named MyFirstProgram.exe
Keywords are names that mean something special to the compiler. These are the keywords
in our example program:
Most keywords are reserved, which means that you can’t use them as identifiers. Here is
the full list of C# reserved keywords (Total 77):
Avoiding conflicts
If you really want to use an identifier that clashes with a reserved keyword, you can do so
by qualifying it with the @ prefix. For instance:
The @ symbol doesn’t form part of the identifier itself. So @myVariable is the same as
myVariable.
Contextual keywords
Some keywords are contextual, meaning they can also be used as identifiers— without an
@ symbol. These are:
An operator transforms and combines expressions. Most operators in C# are denoted with
a symbol, such as the multiplication operator, *. We will discuss operators in more detail
later in this chapter. These are the operators we used in our example program:
A period denotes a member of something (or a decimal point with numeric literals).
Parentheses are used when declaring or calling a method; empty parentheses are used
when the method accepts no arguments.
An equals sign performs assignment. (The double equals sign, ==, performs equality
comparison).
Comments
C# offers two different styles of source-code documentation: single-line comments and
multiline comments. A single-line comment begins with a double forward slash and
continues until the end of the line. For example:
Type Basics
A type defines the blueprint for a value. In our example, we used two literals of type int
with values 12 and 30. We also declared a variable of type int whose name was x:
A variable denotes a storage location that can contain different values over time. In
contrast, a constant always represents the same value.
All values in C# are instances of a type. The meaning of a value, and the set of possible
values a variable can have, is determined by its type.
Another predefined C# type is string. The string type represents a sequence of characters,
such as “.NET” or “http://oreilly.com”. We can work with strings by calling functions on
them as follows:
The predefined bool type has exactly two possible values: true and false. The bool type is
commonly used to conditionally branch execution flow based with an if statement. For
example:
In C#, predefined types (also referred to as built-in types) are recognized with a C#
keyword. The System namespace in the .NET Framework contains many important types
that are not predefined by C# (e.g., DateTime).
A type contains data members and function members. The data member of UnitConverter
is the field called ratio. The function members of UnitConverter are the Convert method
and the UnitConverter’s constructor.
Conversions
C# can convert between instances of compatible types. A conversion always creates a new
value from an existing one. Conversions can be either implicit or explicit: implicit
conversions happen automatically, and explicit conversions require a cast.
In the following example, we implicitly convert an int to a long type (which has twice the
bitwise capacity of an int) and explicitly cast an int to a short type (which has half the
capacity of an int):
Implicit conversions are allowed when both of the following are true:
The compiler can guarantee they will always succeed.
No information is lost in conversion.
Conversely, explicit conversions are required when one of the following is true:
The compiler cannot guarantee they will always succeed.
Information may be lost during conversion.
Value types comprise most built-in types (specifically, all numeric types, the char type, and
the bool type) as well as custom struct and enum types.
Reference types comprise all class, array, delegate, and interface types. (This includes the
predefined string type.)
The fundamental difference between value types and reference types is how they are
handled in memory.
Value types
The content of a value type variable or constant is simply a value. For example, the content
of the built-in value type, int, is 32 bits of data.
You can define a custom value type with the struct keyword:
The assignment of a value-type instance always copies the instance. For example:
Reference types
A reference type is more complex than a value type, having two parts: an object and the
reference to that object. The content of a reference-type variable or constant is a reference
to an object that contains the value. Here is the Point type from our previous example
rewritten as a class, rather than a struct.
Numeric Types
C# has the predefined numeric types:
Numeric Conversions
Converting between integral types
Integral type conversions are implicit when the destination type can represent every
possible value of the source type. Otherwise, an explicit conversion is required. For
example:
Decimal conversions
All integral types can be implicitly converted to the decimal type, since a decimal can
represent every possible C# integral-type value. All other numeric conversions to and from
a decimal type must be explicit.
Operators in C #:
1. Arithmetic Operators
2. Relational Operators
3. Logical Operators
4. Bitwise Operators
5. Assignment Operators
6. Miscellaneous Operators
Arithmetic Operators
Following table shows all the arithmetic operators supported by C#. Assume variable
A holds 10 and variable B holds 20 then:
== Checks if the values of two operands are equal or not, if yes then (A == B)
condition becomes true. is not
true.
!= Checks if the values of two operands are equal or not, if values are (A != B)
not equal then condition becomes true. is true.
> Checks if the value of left operand is greater than the value of right (A > B) is
operand, if yes then condition becomes true. not true.
< Checks if the value of left operand is less than the value of right (A < B) is
operand, if yes then condition becomes true. true.
>= Checks if the value of left operand is greater than or equal to the (A >= B)
value of right operand, if yes then condition becomes true. is not
true.
<= Checks if the value of left operand is less than or equal to the value (A <= B)
of right operand, if yes then condition becomes true. is true.
Logical Operators
Following table shows all the logical operators supported by C#. Assume variable A holds
Boolean value true and variable B holds Boolean value false, then:
&& Called Logical AND operator. If both the operands are non zero then (A && B)
condition becomes true. is false.
Bitwise Operators
Bitwise operator works on bits and perform bit by bit operation. The Bitwise operators
supported by C# are listed in the following table. Assume variable A holds 60 and variable
B holds 13, then:
& Binary AND Operator copies a bit to the result if it exists in both (A & B) = 12,
operands. which is
0000 1100
^ Binary XOR Operator copies the bit if it is set in one operand but (A ^ B) = 49,
not both. which is
0011 0001
~ Binary Ones Complement Operator is unary and has the effect (~A ) = 61,
of 'flipping' bits. which is
1100 0011 in
2's
complement
due to a
signed
binary
number.
<< Binary Left Shift Operator. The left operands value is moved left A << 2 = 240,
by the number of bits specified by the right operand. which is
1111 0000
>> Binary Right Shift Operator. The left operands value is moved A >> 2 = 15,
right by the number of bits specified by the right operand. which is
0000 1111
Assignment Operators
There are following assignment operators supported by C#:
Miscellaneous Operators
There are few other important operators including sizeof, typeof and ? :supported by C#.
as Cast without raising an exception if the cast fails. Object obj = new
StringReader("Hello");
StringReader r = obj as
StringReader;
Conditional operator (ternary operator)
The conditional operator (more commonly called the ternary operator, as it’s the only
operator that takes three operands) has the form q ? a : b, where if condition q is true, a is
evaluated, else b is evaluated. For example:
The \u (or \x) escape sequence lets you specify any Unicode character via its four-digit
hexadecimal code:
Char Conversions
An implicit conversion from a char to a numeric type works for the numeric types that can
accommodate an unsigned short. For other numeric types, an explicit conversion is
required.
String Type
C#’s string type (aliasing the System.String type) represents an immutable sequence of
Unicode characters. A string literal is specified inside double quotes:
The cost of this is that whenever you need a literal backslash, you must write it twice:
To avoid this problem, C# allows verbatim string literals. A verbatim string literal is prefixed
with @ and does not support escape sequences. The following verbatim string is identical
to the preceding one:
String concatenation
The + operator concatenates two strings:
One of the operands may be a non-string value, in which case ToString is called on that
value. For example:
Using the + operator repeatedly to build up a string is inefficient: a better solution is to use
the System.Text.StringBuilder type.
String interpolation
A string preceded with the $ character is called an interpolated string. Interpolated strings
can include expressions inside braces:
String comparisons
string does not support < and > operators for comparisons. You must use the string’s
CompareTo method.
Arrays
An array represents a fixed number of variables (called elements) of a particular type. The
elements in an array are always stored in a contiguous block of memory, providing highly
efficient access.
An array is denoted with square brackets after the element type. For example:
Square brackets also index the array, accessing a particular element by position:
This prints “e” because array indexes start at 0. We can use a for loop statement to iterate
through each element in the array. The for loop in this example cycles the integer i from 0
to 4:
An array initialization expression lets you declare and populate an array in a single step:
Multidimensional Arrays
Multidimensional arrays come in two varieties: rectangular and jagged.
Rectangular arrays represent an n-dimensional block of memory, and jagged arrays are
arrays of arrays.
Rectangular arrays
Rectangular arrays are declared using commas to separate each dimension. The following
declares a rectangular two-dimensional array, where the dimensions are 3 by 3:
A rectangular array can be initialized as follows (to create an array identical to the previous
example):
Example Program,
Jagged arrays
Jagged arrays are declared using successive square brackets to represent each dimension.
Here is an example of declaring a jagged two-dimensional array, where the outermost
dimension is 3:
The inner dimensions aren’t specified in the declaration because, unlike a rectangular
array, each inner array can be an arbitrary length. Each inner array is implicitly initialized
to null rather than an empty array.
A jagged array can be initialized as follows (to create an array identical to the previous
example with an additional element at the end):
Example Program,
As with Java, array bounds checking is necessary for type safety and simplifies debugging.
Generally, the performance hit from bounds checking is minor, and the JIT (Just-In-Time)
compiler can perform optimizations, such as determining in advance whether all indexes
will be safe before entering a loop, thus avoiding a check on each iteration. In addition, C#
provides “unsafe” code that can explicitly bypass bounds checking.
new int is allocated on the stack, and each time the method exits, the int is deallocated.
Heap
The heap is a block of memory in which objects (i.e., reference-type instances) reside.
Whenever a new object is created, it is allocated on the heap, and a reference to that object
is returned. During a program’s execution, the heap starts filling up as new objects are
created. The runtime has a garbage collector that periodically deallocates objects from the
heap, so your program does not run out of memory. An object is eligible for deallocation
as soon as it’s not referenced by anything that’s itself “alive.”
Value-type instances (and object references) live wherever the variable was declared. If
the instance was declared as a field within a class type, or as an array element, that instance
lives on the heap.
Definite Assignment
C# enforces a definite assignment policy. In practice, this means that outside of an unsafe
context, it’s impossible to access uninitialized memory. Definite assignment has three
implications:
Local variables must be assigned a value before they can be read.
Function arguments must be supplied when a method is called (unless marked as
optional.
All other variables (such as fields and array elements) are automatically initialized
by the runtime.
Fields and array elements are automatically initialized with the default values for their type.
The following code outputs 0, because array elements are implicitly assigned to their
default values:
The following code outputs 0, because fields are implicitly assigned a default value:
Default Values
All type instances have a default value. The default value for the predefined types is the
result of a bitwise zeroing of memory:
You can obtain the default value for any type with the default keyword,
Parameters
A method has a sequence of parameters. Parameters define the set of arguments that must
be provided for that method. In this example, the method Foo has a single parameter
named p, of type int:
You can control how parameters are passed with the ref and out modifiers:
Passing arguments by value
By default, arguments in C# are passed by value, which is by far the most common case.
This means a copy of the value is created when passed to the method:
Assigning p a new value does not change the contents of x, since p and x reside in different
memory locations.
Optional parameters
A parameter is optional if it specifies a default value in its declaration:
Operator Precedence and Associativity
When an expression contains multiple operators, precedence and associativity determine
the order of their evaluation. Operators with higher precedence execute before operators
of lower precedence. If the operators have the same precedence, the operator’s
associativity determines the order of evaluation.
Left-associative operators
Binary operators (except for assignment, lambda, and null coalescing operators) are left-
associative; in other words, they are evaluated from left to right. For example, the following
expression:
Right-associative operators
The assignment operators, lambda, null coalescing, and conditional operator are right-
associative; in other words, they are evaluated from right to left. Right associativity allows
multiple assignments such as the following to compile:
Null Operators
C# provides two operators to make it easier to work with nulls: the null coalescing operator
and the null-conditional operator.
Statements
Functions comprise statements that execute sequentially in the textual order in which they
appear. A statement block is a series of statements appearing between braces (the {}
tokens).
Declaration Statements
A declaration statement declares a new variable, optionally initializing the variable with an
expression. A declaration statement ends in a semicolon. You may declare multiple
variables of the same type in a comma-separated list. For example:
A constant declaration is like a variable declaration, except that it cannot be changed after
it has been declared, and the initialization must occur with the declaration.
Local variables
The scope of a local variable or local constant extends throughout the current block. You
cannot declare another local variable with the same name in the current block or in any
nested blocks. For example:
Expression Statements
Expression statements are expressions that are also valid statements. An expression
statement must either change state or call something that might change state.
Changing state essentially means changing a variable. The possible expression statements
are:
Assignment expressions (including increment and decrement expressions)
Method call expressions (both void and non-void)
Object instantiation expressions
Conditional Operator ( ? : )
Conditional operator is also known as the ternary operator. This operator consists of three
operands and is used to evaluate Boolean expressions. The goal of the operator is to
decide, which value should be assigned to the variable. The operator is written as –
Following is an example –
Control Statements
A programming language uses control statements to cause the flow of execution to
advance and branch based on changes to the state of a program. C# program control
statements can be put into the following categories: selection, iteration, and jump.
- Selection statements allow your program to choose different paths of execution
based upon the outcome of an expression or the state of a variable.
- Iteration statements enable program execution to repeat one or more statements
(that is, iteration statements form loops).
- Jump statements allow your program to execute in a nonlinear fashion.
if
The if statement is C#’s conditional branch statement. It can be used to route program
execution through two different paths. Here is the general form of the if statement:
if (condition) statement1;
else statement2;
The if works like this: If the condition is true, then statement1 is executed. Otherwise,
statement2 (if it exists) is executed. In no case will both statements be executed. For
example, consider the following:
Here, if a is less than b, then a is set to zero. Otherwise, b is set to zero. In no case are they
both set to zero.
Nested ifs
A nested if is an if statement that is the target of another if or else. Nested ifs are very
common in programming. When you nest ifs, the main thing to remember is that an else
statement always refers to the nearest if statement that is within the same block as the
else and that is not already associated with an else. Here is an example:
The if-else-if Ladder
A common programming construct that is based upon a sequence of nested ifs is the if-
else-if ladder. It looks like this:
Here is a program that uses an if-else-if ladder to determine which season a particular
month is in.
switch
The switch statement is C#’s multiway branch statement. It provides an easy way to
dispatch execution to different parts of your code based on the value of an expression. As
such, it often provides a better alternative than a large series of if-else-if statements. Here
is the general form of a switch statement:
Here is a simple example that uses a switch statement:
Iteration Statements
C#’s iteration statements are for, while, do-while and for-each loop. These statements
create what we commonly call loops. As you probably know, a loop repeatedly executes
the same set of instructions until a termination condition is met. A loop statement allows
us to execute a statement or group of statements multiple times.
for loop
A for loop is a repetition control structure that allows you to efficiently write a loop that
needs to be executed a specific number of times. A for loop is useful when you know how
many times a task is to be repeated.
The syntax of a for loop is –
while Loop
A while loop statement in C# programming language repeatedly executes a target
statement as long as a given condition is true.
The syntax of a while loop is –
Here, key point of the while loop is that the loop might not ever run. When the expression
is tested and the result is false, the loop body will be skipped and the first statement after
the while loop will be executed.
Example:
do while loop
A do...while loop is similar to a while loop, except that a do...while loop is guaranteed to
execute at least one time.
Following is the syntax of a do...while loop –
Example
foreach Loop
The foreach statement iterates over each element in an enumerable object. Most of the
types in C# and the .NET Framework that represent a set or list of elements are
enumerable. For example, both an array and a string are enumerable. Here is an example
of enumerating over the characters in a string, from the first character through to the last:
Output:
10
20
30
40
50
Nested Loops
Like all other programming languages, C# allows loops to be nested. That is, one loop may
be inside another. For example, here is a program that nests for loops:
Jump Statements
The C# jump statements are break, continue, goto, return, and throw. These statements
transfer control to another part of your program.
Using break
In C#, the break statement has three uses. First, as you have seen, it terminates a statement
sequence in a switch statement. Second, it can be used to exit a loop. Third, it can be used
as a “civilized” form of goto.
Using continue
Sometimes it is useful to force an early iteration of a loop. That is, you might want to
continue running the loop but stop processing the remainder of the code in its body for
this particular iteration. This is, in effect, a goto just past the body of the loop, to the loop’s
end. The continue statement performs such an action.
In a while and do-while loops, a continue statement causes control to be transferred
directly to the conditional expression that controls the loop. In a for loop, control goes first
to the iteration portion of the for statement and then to the conditional expression. For all
three loops, any intermediate code is bypassed.
Here is an example program that uses continue to cause two numbers to be printed on
each line:
Using return
The last control statement is return. The return statement is used to explicitly return from
a method. That is, it causes program control to transfer back to the caller of the method.
As such, it is categorized as a jump statement.
Example:
Output:
Sum of two numbers=25
A label is a placeholder in a code block that precedes a statement, denoted with a colon
suffix. The following iterates the numbers 1 through 5, mimicking a for loop:
The throw statement
The throw statement throws an exception to indicate an error has occurred.
If(age<18)
throw new ArithmeticExcecption(“Not Eligible to Vote”);
Namespaces
A namespace is a domain for type names. Types are typically organized into hierarchical
namespaces, making them easier to find and avoiding conflicts. For example, the RSA type
that handles public key encryption is defined within the following namespace:
The namespace keyword defines a namespace for types within that block. For example:
The dots in the namespace indicate a hierarchy of nested namespaces. The code that
follows is semantically identical to the preceding example:
Name hiding
If the same type name appears in both an inner and an outer namespace, the inner name
wins. To refer to the type in the outer namespace, you must qualify its name. For example:
Repeated namespaces
You can repeat a namespace declaration, as long as the type names within the namespaces
don’t conflict:
We can even break the example into two source files such that we could compile each class
into a different assembly.
The application cannot compile, because Widget is ambiguous. Extern aliases can resolve
the ambiguity in our application:
}}