Csharp

You might also like

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 96

C# Version History

C# was first introduced with .NET Framework 1.0 in the year 2002 and evolved much since then.
The following table lists important features introduced in each version of C#:

Version .NET Framework Visual Studio Important Features


C# 1.0 .NET Framework 1.0/1.1 Visual Studio .NET 2002 Basic features

C# 2.0 .NET Framework 2.0 Visual Studio 2005 Generics


Partial types
Anonymous methods
Iterators
Nullable types
Private setters (properties)
Method group conversions (delegates)
Covariance and Contra-variance
Static classes

C# 3.0 .NET Framework 3.0\3.5 Visual Studio 2008 Implicitly typed local variables
Object and collection initializers
Auto-Implemented properties
Anonymous types
Extension methods
Query expressions
Lambda expressions
Expression trees
Partial Methods

C# 4.0 .NET Framework 4.0 Visual Studio 2010 Dynamic binding (late binding)
Named and optional arguments
Generic co- and contravariance
Embedded interop types

C# 5.0 .NET Framework 4.5 Visual Studio 2012/2013 Async features


Caller information

C# 6.0 .NET Framework 4.6 Visual Studio 2013/2015 Expression Bodied Methods
Auto-property initializer
nameof Expression
Primary constructor
Await in catch block
Exception Filter
String Interpolation

C# 7.0 .NET Core 2.0 Visual Studio 2017 out variables


Tuples
Discards
Pattern Matching
Local functions
Generalized async return types

C# 8.0 .NET Core 3.0 Visual Studio 2019 Readonly members


Default interface methods
Using declarations
Version .NET Framework Visual Studio Important Features
Static local functions
Disposable ref structs
Nullable reference types

C# 9.0 .NET 5.0 Visual Studio 2019 Records


Init-only properties
Top-level statements
Init accessors and readonly fields
With-expressions
Value-based equality

C# 10.0 .NET 6.0 Visual Studio 2022 Record structs


Global using directives
File-scoped namespace declaration
Extended Proptery Patterns
Null Parameter Checking
Constant interpolated strings

First C# Program

Here, you will learn to create a simple console application in C# and understand the basic building
blocks of a console application.

C# can be used in a window-based, web-based, or console application. To start with, we will create a
console application to work with C#.

Open Visual Studio (2017 or later) installed on your local machine. Click on File -> New Project...
from the top menu, as shown below.

Create a New Project in Visual Studio 2017

From the New Project popup, shown below, select Visual C# in the left side panel and select the
Console App in the right-side panel.
Select Visual C# Console App Template

In the name section, give any appropriate project name, a location where you want to create all the
project files, and the name of the project solution.

Click OK to create the console project. Program.cs will be created as default a C# file in Visual
Studio where you can write your C# code in Program class, as shown below. (The .cs is a file
extension for C# file.)

C# Console Program
Every console application starts from the Main() method of the Program class. The following
example displays "Hello World!!" on the console.

Example: C# Console Application


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharpTutorials
{
class Program
{
static void Main(string[] args)
{
string message = "Hello World!!";

Console.WriteLine(message);
}
}
}
Try it

The following image illustrates the important parts of the above example.

C# Code Structure

Let's understand the above C# structure.

1. Every .NET application takes the reference of the necessary .NET framework namespaces that it
is planning to use with the using keyword, e.g., using System.Text.
2. Declare the namespace for the current class using the namespace keyword, e.g., namespace
CSharpTutorials.FirstProgram
3. We then declared a class using the class keyword: class Program
4. The Main() is a method of Program class is the entry point of the console application.
5. String is a data type.
6. A message is a variable that holds the value of a specified data type.
7. "Hello World!!" is the value of the message variable.
8. The Console.WriteLine() is a static method, which is used to display a text on the console.

Note:
Every line or statement in C# must end with a semicolon (;).

Compile and Run C# Program

To see the output of the above C# program, we have to compile it and run it by pressing Ctrl + F5 or
clicking the Run button or by clicking the "Debug" menu and clicking "Start Without Debugging".
You will see the following output in the console:

Output:

Hello World!!

So this is the basic code items that you will probably use in every C# code.

C# Keywords

C# contains reserved words that have special meaning for the compiler. These reserved words are
called "keywords". Keywords cannot be used as an identifier (name of a variable, class, interface,
etc.).

Keywords in C# are distributed under the following categories:

Modifier Keywords

Modifier keywords are specific keywords that indicate who can modify types and type members.
Modifiers allow or prevent certain parts of programs from being modified by other parts.

Modifier keywords
abstract
async
const
event
extern
new
override
partial
readonly
sealed
static
unsafe
virtual
volatile

Access Modifier Keywords:

Access modifiers are applied to the declaration of the class, method, properties, fields, and other
members. They define the accessibility of the class and its members.
Access
Modifiers Usage
public The Public modifier allows any part of the program in the same assembly or another assembly
to access the type and its members.
private The Private modifier restricts other parts of the program from accessing the type and its
members. Only code in the same class or struct can access it.
internal The Internal modifier allows other program code in the same assembly to access the type or its
members. This is default access modifiers if no modifier is specified.
protected The Protected modifier allows codes in the same class or a class that derives from that class to
access the type or its members.

Statement Keywords

Statement keywords are related to program flow.

Statement Keywords
if
else
switch
case
do
for
foreach
in
while
break
continue
default
goto
return
yield
throw
try
catch
finally
checked
unchecked
fixed
lock

Method Parameter Keywords

These keywords are applied to the parameters of a method.

Method Parameter Keywords


params
ref
out

Namespace Keywords
These keywords are applied with namespace and related operators.

Namespace Keywords
using
. operator
:: operator
extern alias
ADVERTISEMENT

Operator Keywords

Operator keywords perform miscellaneous actions.

Operator Keywords
as
await
is
new
sizeof
typeof
stackalloc
checked
unchecked

Access Keywords

Access keywords are used to access the containing class or the base class of an object or class.

Access keywords
base
this

Literal Keywords

Literal keywords apply to the current instance or value of an object.

Literal Keywords
null
false
true
value
void

Type Keywords

Type keywords are used for data types.

Type keywords
bool
byte
Type keywords
char
class
decimal
double
enum
float
int
long
sbyte
short
string
struct
uint
ulong
ushort

Contextual Keywords

Contextual keywords are considered as keywords, only if used in specific contexts. They are not
reserved and so can be used as names or identifiers.

Contextual Keywords
add
var
dynamic
global
set
value

Contextual keywords are not converted into blue color (default color for keywords in visual studio)
when used as an identifier in Visual Studio. For example, var in the below figure is not in blue,
whereas the color of this is the blue color. So var is a contextual keyword.

C# Keywords

Query Keywords

Query keywords are contextual keywords used in LINQ queries.

Query Keywords
from
where
Query Keywords
select
group
into
orderby
join
let
in
on
equals
by
ascending
descending

As mentioned above, a keyword cannot be used as an identifier (name of the variable, class,
interface, etc.). However, they can be used with the prefix '@'. For example, the class is a reserved
keyword, so it cannot be used as an identifier, but @class can be used as shown below.

Example: Use Keyword as Identifier


public class @class
{
public static int MyProperty { get; set; }
}

@class.MyProperty = 100;
Try it

C# Class

A class is like a blueprint of a specific object. In the real world, every object has some color, shape,
and functionalities - for example, the luxury car Ferrari. Ferrari is an object of the luxury car type.
The luxury car is a class that indicates some characteristics like speed, color, shape, interior, etc. So
any company that makes a car that meets those requirements is an object of the luxury car type. For
example, every single car of BMW, Lamborghini, Cadillac are an object of the class called 'Luxury
Car'. Here, 'Luxury Car' is a class, and every single physical car is an object of the luxury car class.

Likewise, in object-oriented programming, a class defines some properties, fields, events, methods,
etc. A class defines the kinds of data and the functionality their objects will have.

A class enables you to create your custom types by grouping variables of other types, methods, and
events.

In C#, a class can be defined by using the class keyword.

Example: C# Class
public class MyClass
{
public string myField = string.Empty;

public MyClass()
{
}

public void MyMethod(int parameter1, string parameter2)


{
Console.WriteLine("First Parameter {0}, second parameter {1}",
parameter1, parameter2);
}

public int MyAutoImplementedProperty { get; set; }

private int myPropertyVar;

public int MyProperty


{
get { return myPropertyVar; }
set { myPropertyVar = value; }
}
}

The following image shows the important building blocks of C# class.

C#
Class

C# Access Modifiers

Access modifiers are applied to the declaration of the class, method, properties, fields, and other
members. They define the accessibility of the class and its members. Public, private, protected, and
internal are access modifiers in C#.

C# Field

The field is a class-level variable that holds a value. Generally, field members should have a private
access modifier and used with property.

C# Constructor
A class can have parameterized or parameterless constructors. The constructor will be called when
you create an instance of a class. Constructors can be defined by using an access modifier and class
name: <access modifiers> <class name>(){ }

Example: Constructor in C#
class MyClass
{
public MyClass()
{

}
}

C# Method

A method can be defined using the following template:

{access modifier} {return type} MethodName({parameterType parameterName})

Example: Method in C#
public void MyMethod(int parameter1, string parameter2)
{
// write your method code here..

Property

A property can be defined using getters and setters, as shown below:

Example: Property in C#
private int _myPropertyVar;

public int MyProperty


{
get { return _myPropertyVar; }
set { _myPropertyVar = value; }
}

Property encapsulates a private field. It provides getters (get{}) to retrieve the value of the
underlying field and setters (set{}) to set the value of the underlying field. In the above example,
_myPropertyVar is a private field that cannot be accessed directly. It will only be accessed via
MyProperty. Thus, MyProperty encapsulates _myPropertyVar.

You can also apply some additional logic in get and set, as in the below example.

Example: Property in C#
private int _myPropertyVar;

public int MyProperty


{
get {
return _myPropertyVar / 2;
}

set {
if (value > 100)
_myPropertyVar = 100;
else
_myPropertyVar = value; ;
}
}

Auto-implemented Property

From C# 3.0 onwards, property declaration has been made easy if you don't want to apply some
logic in get or set.

The following is an example of an auto-implemented property:

Example: Auto implemented property in C#


public int MyAutoImplementedProperty { get; set; }

Notice that there is no private backing field in the above property example. The backing field will be
created automatically by the compiler. You can work with an automated property as you would with
a normal property of the class. Automated-implemented property is just for easy declaration of the
property when no additional logic is required in the property accessors.

Namespace

The namespace is a container for a set of related classes and namespaces. The namespace is also
used to give unique names to classes within the namespace name. Namespace and classes are
represented using a dot (.).

In C#, namespace can be defined using the namespace keyword.

Example: Namespace
namespace CSharpTutorials
{
class MyClass
{

}
}

In the above example, the fully qualified class name of MyClass is CSharpTutorials.MyClass.

A namespace can contain other namespaces. Inner namespaces can be separated using (.).

Example: Namespace
namespace CSharpTutorials.Examples
{
class MyClassExample
{

}
}

In the above example, the fully qualified class name


of MyClassExample is CSharpTutorials.Examples.MyClassExample.

C# Variables
In C#, a variable contains a data value of the specific data type.

Syntax
<data type> <variable name> = <value>;

The following declares and initializes a variable of an int type.

Example: C# Variable
int num = 100;

Above, int is a data type, num is a variable name (identifier). The = operator is used to assign a value
to a variable. The right side of the = operator is a value that will be assigned to left side variable.
Above, 100 is assigned to a variable num.

The following declares and initializes variables of different data types.

Example: C# Variables
int num = 100;
float rate = 10.2f;
decimal amount = 100.50M;
char code = 'C';
bool isValid = true;
string name = "Steve";
Try it

The followings are naming conventions for declaring variables in C#:

 Variable names must be unique.


 Variable names can contain letters, digits, and the underscore _ only.
 Variable names must start with a letter.
 Variable names are case-sensitive, num and Num are considered different names.
 Variable names cannot contain reserved keywords. Must prefix @ before keyword if want
reserve keywords as identifiers.

C# is the strongly typed language. It means you can assign a value of the specified data type. You
cannot assign an integer value to string type or vice-versa.

Example: Cannot assign string to int type variable


int num = "Steve";

Variables can be declared first and initialized later.

Example: Late Initialization


int num;
num = 100;

A variable must be assigned a value before using it, otherwise, C# will give a compile-time error.

Error: Invalid Assignment


int i;
int j = i; //compile-time error: Use of unassigned local variable 'i'

The value of a variable can be changed anytime after initializing it.

Example: C# Variable
int num = 100;
num = 200;
Console.WriteLine(num); //output: 200

Multiple variables of the same data type can be declared and initialized in a single line separated by
commas.

Example: Multiple Variables in a Single Line


int i, j = 10, k = 100;
Try it

Multiple variables of the same type can also be declared in multiple lines separated by a comma. The
compiler will consider it to be one statement until it encounters a semicolon ;.

Example: Multi-Line Declarations


int i = 0,
j = 10,
k = 100;
Try it

The value of a variable can be assigned to another variable of the same data type. However, a value
must be assigned to a variable before using it.

Example: Variable Assignment


int i = 100;

int j = i; // value of j will be 100


Try it

In C#, variables are categorized based on how they store their value in memory. Variables can
be value type or reference type or pointer type.

It is not necessary to specify the specific type when declaring variables. Use the var keyword instead
of a data type. Learn about it next.

C# - var

In C#, variables must be declared with the data type. These are called explicitly typed variables.

Example: Explicitly Typed Variable


int i = 100;// explicitly typed variable

C# 3.0 introduced var keyword to declare method level variables without specifying a data type
explicitly.

Example: Implicitly Typed Local Variable


var j = 100; // implicitly typed local variable

The compiler will infer the type of a variable from the expression on the right side of the = operator.
Above, var will be compiled as int.

The following infers the type from an expression.

Example: var from expression


int i = 10;
var j = i + 1; // compiles as int
var can be used to declare any built-in data type or a user-defined type or an anonymous type
variable. The following example shows C# compiler infers type based on the value:

Example: Implicitly-Typed Variable


static void Main(string[] args)
{
var i = 10;
Console.WriteLine("Type of i is {0}", i.GetType());

var str = "Hello World!!";


Console.WriteLine("Type of str is {0}", str.GetType());

var dbl = 100.50d;


Console.WriteLine("Type of dbl is {0}", dbl.GetType());

var isValid = true;


Console.WriteLine("Type of isValid is {0}", isValid.GetType());

var ano = new { name = "Steve" };


Console.WriteLine("Type of ano is {0}", ano.GetType());

var arr = new[] { 1, 10, 20, 30 };


Console.WriteLine("Type of arr is {0}", arr.GetType());

var file = new FileInfo("MyFile");


Console.WriteLine("Type of file is {0}", file.GetType());

}
Try it

Implicitly-typed variables must be initialized at the time of declaration; otherwise C# compiler


would give an error: Implicitly-typed variables must be initialized.

var i; // Compile-time error: Implicitly-typed variables must be initialized


i = 100;

Multiple declarations of var variables in a single statement are not allowed.

var i = 100, j = 200, k = 300; // Error: cannot declare var variables in a single statement

//The followings are also valid


var i = 100;
var j = 200;
var k = 300;

var cannot be used for function parameters.

void Display(var param) //Compile-time error


{
Console.Write(param);
}

var can be used in for, and foreach loops.

for(var i = 0; i < 10; i++)


{
Console.WriteLine(i);
}

var can also be used with LINQ queries.

Example: LINQ Query Syntax in C#


// string collection
IList<string> stringList = new List<string>() {
"C# Tutorials",
"VB.NET Tutorials",
"Learn C++",
"MVC Tutorials" ,
"Java"
};

// LINQ Query Syntax


var result = from s in stringList
where s.Contains("Tutorials")
select s;
Try it

C# - Data Types

C# is a strongly-typed language. It means we must declare the type of a variable that indicates the
kind of values it is going to store, such as integer, float, decimal, text, etc.

The following declares and initialized variables of different data types.

Example: Variables of Different Data Types


string stringVar = "Hello World!!";
int intVar = 100;
float floatVar = 10.2f;
char charVar = 'A';
bool boolVar = true;
Try it

C# mainly categorized data types in two types: Value types and Reference types. Value types
include simple types (such as int, float, bool, and char), enum types, struct types, and Nullable value
types. Reference types include class types, interface types, delegate types, and array types. Learn
about value types and reference types in detail in the next chapter.
Predefined Data Types in C#

C# includes some predefined value types and reference types. The following table lists predefined
data types:

Suffi
Type Description Range x
byte 8-bit unsigned integer 0 to 255
sbyte 8-bit signed integer -128 to 127
short 16-bit signed integer -32,768 to 32,767
ushort 16-bit unsigned integer 0 to 65,535
int 32-bit signed integer -2,147,483,648
to
2,147,483,647
uint 32-bit unsigned integer 0 to 4,294,967,295 u
long 64-bit signed integer -9,223,372,036,854,775,808 l
to
9,223,372,036,854,775,807
ulong 64-bit unsigned integer 0 to 18,446,744,073,709,551,615 ul
float 32-bit Single-precision floating point type -3.402823e38 to 3.402823e38 f
double 64-bit double-precision floating point type -1.79769313486232e308 to d
1.79769313486232e308
decimal 128-bit decimal type for financial and (+ or -)1.0 x 10e-28 m
monetary calculations to
7.9 x 10e28
char 16-bit single Unicode character Any valid character, e.g. a,*, \x0058 (hex), or\
u0058 (Unicode)
bool 8-bit logical true/false value True or False
object Base type of all other types.
string A sequence of Unicode characters
DateTime Represents date and time 0:00:00am 1/1/01
to
Suffi
Type Description Range x
11:59:59pm 12/31/9999

As you can see in the above table that each data type (except string and object) includes value range.
The compiler will give an error if the value goes out of datatype's permitted range. For example, int
data type's range is -2,147,483,648 to 2,147,483,647. So if you assign a value which is not in this
range, then the compiler would give an error.

Example: Compile time error


// compile time error: Cannot implicitly convert type 'long' to 'int'.
int i = 21474836470;

The value of unsigned integers, long, float, double, and decimal type must be suffix by u,l,f,d, and
m, respectively.

Example: Value Suffix


uint ui = 100u;
float fl = 10.2f;
long l = 45755452222222l;
ulong ul = 45755452222222ul;
double d = 11452222.555d;
decimal mon = 1000.15m;
Try it
ADVERTISEMENT

Alias vs .NET Type

The predefined data types are alias to their .NET type (CLR class) name. The following table lists
alias for predefined data types and related .NET class name.

Alias .NET Type Type


byte System.Byte struct
sbyte System.SByte struct
int System.Int32 struct
uint System.UInt32 struct
short System.Int16 struct
ushort System.UInt16 struct
long System.Int64 struct
ulong System.UInt64 struct
float System.Single struct
double System.Double struct
char System.Char struct
bool System.Boolean struct
object System.Object Class
string System.String Class
decimal System.Decimal struct
DateTime System.DateTime struct

It means that whether you define a variable of int or Int32, both are the same.

int i = 345;
Int32 i = 345;// same as above

Default Values

Every data type has a default value. Numeric type is 0, boolean has false, and char has '\0' as default
value. Use the default(typename) to assign a default value of the data type or C# 7.1 onward,
use default literal.

int i = default(int); // 0
float f = default(float);// 0
decimal d = default(decimal);// 0
bool b = default(bool);// false
char c = default(char);// '\0'

// C# 7.1 onwards
int i = default; // 0
float f = default;// 0
decimal d = default;// 0
bool b = default;// false
char c = default;// '\0'

Conversions

The values of certain data types are automatically converted to different data types in C#. This is
called an implicit conversion.

Example: Implicit Conversion


int i = 345;
float f = i;

Console.WriteLine(f); //output: 345

In the above example, the value of an integer variable i is assigned to the variable of float
type f because this conversion operation is predefined in C#.

The following is an implicit data type conversion table.

Implicit Conversion From To


sbyte short, int, long, float, double, decimal
byte short, ushort, int, uint, long, ulong, float, double, decimal
short int, long, float, double, or decimal
ushort int, uint, long, ulong, float, double, or decimal
int long, float, double, or decimal.
uint long, ulong, float, double, or decimal
long float, double, or decimal
ulong float, double, or decimal
char ushort, int, uint, long, ulong, float, double, or decimal
float Double

Conversions from int, uint, long, or ulong to float and from long or ulong to double may cause a loss
of precision. No data type implicitly converted to the char type.

However, not all data types are implicitly converted to other data types. For example, int type cannot
be converted to uint implicitly. It must be specified explicitly, as shown below.
Example: Explicit Conversion
public static void Main()
{
int i = 100;
uint u = (uint) i;
Console.Write(i);
}

In the above example, integer i is converted to uint explicitly by specifying uint in the brackets
(uint). This will convert an integer to uint

Numbers in C#

Numbers, in general, can be divided into two types: Integer type and floating-point types.

Integer type numbers are whole numbers without decimal points. It can be negative or positive
numbers.

Floating-point type is numbers with one or more decimal points. It can be negative or positive
numbers.

C# includes different data types for integer types and floating-point types based on their size in the
memory and capacity to store numbers.

The following figure illustrates numeric types in C#.

Nume
ric Types

Integer Types

Integer type numbers are positive or negative whole numbers without decimal points. C# includes
four data types for integer numbers: byte, short, int, and long.

Byte

The byte data type stores numbers from 0 to 255. It occupies 8-bit in the memory. The byte keyword
is an alias of the Byte struct in .NET.

The sbyte is the same as byte, but it can store negative numbers from -128 to 127. The sbyte
keyword is an alias for SByte struct in .NET.

Example: byte, sbyte


byte b1 = 255;
byte b2 = -128;// compile-time error: Constant value '-128' cannot be converted to a 'byte'
sbyte sb1 = -128;
sbyte sb2 = 127;

Console.WriteLine(Byte.MaxValue);//255
Console.WriteLine(Byte.MinValue);//0
Console.WriteLine(SByte.MaxValue);//127
Console.WriteLine(SByte.MinValue);//-128
Try it

Short

The short data type is a signed integer that can store numbers from -32,768 to 32,767. It occupies 16-
bit memory. The short keyword is an alias for Int16 struct in .NET.

The ushort data type is an unsigned integer. It can store only positive numbers from 0 to 65,535. The
ushort keyword is an alias for UInt16 struct in .NET.

Example: short, ushort


short s1 = -32768;
short s2 = 32767;
short s3 = 35000;//Compile-time error: Constant value '35000' cannot be converted to a 'short'

ushort us1 = 65535;


ushort us2 = -32000; //Compile-time error: Constant value '-32000' cannot be converted to a 'ushort'

Console.WriteLine(Int16.MaxValue);//32767
Console.WriteLine(Int16.MinValue);//-32768
Console.WriteLine(UInt16.MaxValue);//65535
Console.WriteLine(UInt16.MinValue);//0
Try it

Int

The int data type is 32-bit signed integer. It can store numbers from -2,147,483,648 to
2,147,483,647. The int keyword is an alias of Int32 struct in .NET.

The uint is 32-bit unsigned integer. The uint keyword is an alias of UInt32 struct in .NET. It can
store positive numbers from 0 to 4,294,967,295. Optionally use U or u suffix after a number to
assign it to uint variable.

Example: int, uint


int i = -2147483648;
int j = 2147483647;
int k = 4294967295; //Compile-time error: Cannot implicitly convert type 'uint' to 'int'.

uint ui1 = 4294967295;


uint ui2 =-1; //Compile-time error: Constant value '-1' cannot be converted to a 'uint'

Console.WriteLine(Int32.MaxValue);//2147483647
Console.WriteLine(Int32.MinValue);//-2147483648
Console.WriteLine(UInt32.MaxValue);//4294967295
Console.WriteLine(UInt32.MinValue);//0
Try it

The int data type is also used for hexadecimal and binary numbers. A hexadecimal number starts
with 0x or 0X prefix. C# 7.2 onwards, a binary number starts with 0b or 0B.
Example: Hexadecimal, Binary
int hex = 0x2F;
int binary = 0b_0010_1111;

Console.WriteLine(hex);
Console.WriteLine(binary);
Try it
ADVERTISEMENT

Long

The long type is 64-bit signed integers. It can store numbers from -9,223,372,036,854,775,808 to
9,223,372,036,854,775,807. Use l or L suffix with number to assign it to long type variable. The
long keyword is an alias of Int64 struct in .NET.

The ulong type stores positive numbers from 0 to 18,446,744,073,709,551,615. If a number is


suffixed by UL, Ul, uL, ul, LU, Lu, lU, or lu, its type is ulong. The uint keyword is an alias
of UInt64 struct in .NET.

Example: long, ulong


long l1 = -9223372036854775808;
long l2 = 9223372036854775807;

ulong ul1 = 18223372036854775808ul;


ulong ul2 = 18223372036854775808UL;

Console.WriteLine(Int64.MaxValue);//9223372036854775807
Console.WriteLine(Int64.MinValue);//-9223372036854775808
Console.WriteLine(UInt64.MaxValue);//18446744073709551615
Console.WriteLine(UInt64.MinValue);//0
Try it

Floating Point Types

Floating-point numbers are positive or negative numbers with one or more decimal points. C#
includes three data types for floating-point numbers: float, double, and decimal.

Float

The float data type can store fractional numbers from 3.4e−038 to 3.4e+038. It occupies 4 bytes in
the memory. The float keyword is an alias of Single struct in .NET.

Use f or F suffix with literal to make it float type.

Example: float
float f1 = 123456.5F;
float f2 = 1.123456f;

Console.WriteLine(f1);//123456.5
Console.WriteLine(f2);//1.123456
Try it

Double
The double data type can store fractional numbers from 1.7e−308 to 1.7e+308. It occupies 8 bytes in
the memory. The double keyword is an alias of the Double struct in .NET.

Use d or D suffix with literal to make it double type.

Example: double
double d1 = 12345678912345.5d;
double d2 = 1.123456789123456d;

Console.WriteLine(d1);//12345678912345.5
Console.WriteLine(d2);//1.123456789123456
Try it

Decimal

The decimal data type can store fractional numbers from ±1.0 x 10-28 to ±7.9228 x 1028. It occupies
16 bytes in the memory. The decimal is a keyword alias of the Decimal struct in .NET.

The decimal type has more precision and a smaller range than both float and double, and so it is
appropriate for financial and monetary calculations.

Use m or M suffix with literal to make it decimal type.

Example: decimal
decimal d1 = 123456789123456789123456789.5m;
decimal d2 = 1.1234567891345679123456789123m;

Console.WriteLine(d1);
Console.WriteLine(d2);
Try it

Scientific Notation

Use e or E to indicate the power of 10 as exponent part of scientific notation with float, double or
decimal.

Example:
double d = 0.12e2;
Console.WriteLine(d); // 12;

float f = 123.45e-2f;
Console.WriteLine(f); // 1.2345

decimal m = 1.2e6m;
Console.WriteLine(m);// 1200000
Try it

C# Strings

In C#, a string is a series of characters that is used to represent text. It can be a character, a word or a
long passage surrounded with the double quotes ". The following are string literals.

Example: String Literals


"S"
"String"
"This is a string."
C# provides the String data type to store string literals. A variable of the string type can be declared
and assign string literal, as shown below.

Example: String Type Variables


string ch = "S";
string word = "String";
string text = "This is a string.";
Try it

The maximum size of a String object in memory is 2GB or about 1 billion characters. However,
practically it will be less depending upon CPU and memory of the computer.

There two ways to declare a string variable in C#. Using System.String class and
using string keyword. Both are the same and make no difference. Learn string vs String for more
info.

Example: String and string


string str1 = "Hello"; // uses string keyword

String str2 = "Hello"; // uses System.String class


Try it

In C#, a string is a collection or an array of characters. So, string can be created using a char array or
accessed like a char array.

Example: String as char Array


char[] chars = {'H','e','l','l','o'};

string str1 = new string(chars);


String str2 = new String(chars);

foreach (char c in str1)


{
Console.WriteLine(c);
}
Try it

Special Characters

A text in the real world can include any character. In C#, because a string is surrounded with double
quotes, it cannot include " in a string. The following will give a compile-time error.

Example: Invalid String


string text = "This is a "string" in C#.";

C# includes escaping character \ (backslash) before these special characters to include in a string.

Use backslash \ before double quotes and some special characters such as \,\n,\r,\t, etc. to include it
in a string.

Example: Escape Char \


string text = "This is a \"string\" in C#.";
string str = "xyzdef\\rabc";
string path = "\\\\mypc\\ shared\\project";
Try it
However, it will be very tedious to prefix \ for every special character. Prefixing the string with an
@ indicates that it should be treated as a literal and should not escape any character.

Example: Escape Sequence


string str = @"xyzdef\rabc";
string path = @"\\mypc\shared\project";
string email = @"test@test.com";
Try it

Use @ and \ to declare a multi-line string.

Example: Multi-line String


string str = @"this is a \
multi line \
string";
Try it

Please note that you must use a backslash to allow " in a string. @ is only for special characters in
C#.

string text = @"This is a "string." in C#."; // error


string text = @"This is a \"string\" in C#."; // error
string text = "This is a \"string\" in C#."; // valid
ADVERTISEMENT

String Concatenation

Multiple strings can be concatenated with + operator.

Example: String Concatenation


string name = "Mr." + "James " + "Bond" + ", Code: 007";

string firstName = "James";


string lastName = "Bond";
string code = "007";

string agent = "Mr." + firstName + " " + lastName + ", Code: " + code;
Try it

A String is immutable in C#. It means it is read-only and cannot be changed once created in the
memory. Each time you concatenate strings, .NET CLR will create a new memory location for the
concatenated string. So, it is recommended to use StringBuilder instead of string if you concatenate
more than five strings.

String Interpolation

String interpolation is a better way of concatenating strings. We use + sign to concatenate string
variables with static strings.

C# 6 includes a special character $ to identify an interpolated string. An interpolated string is a


mixture of static string and string variable where string variables should be in {} brackets.

Example: String Interpolation


string firstName = "James";
string lastName = "Bond";
string code = "007";

string fullName = $"Mr. {firstName} {lastName}, Code: {code}";


Try it

In the above example of interpolation, $ indicates the interpolated string, and {} includes string
variable to be incorporated with a string.

Use two braces, "{{" or "}}" to include { or } in a string.

Working with Date and Time in C#

C# includes DateTime struct to work with dates and times.

To work with date and time in C#, create an object of the DateTime struct using the new keyword.
The following creates a DateTime object with the default value.

Example: Create DateTime Object


DateTime dt = new DateTime(); // assigns default value 01/01/0001 00:00:00

The default and the lowest value of a DateTime object is January 1, 0001 00:00:00 (midnight). The
maximum value can be December 31, 9999 11:59:59 P.M.

Use different constructors of the DateTime struct to assign an initial value to a DateTime object.

Example: Set Date & Time


//assigns default value 01/01/0001 00:00:00
DateTime dt1 = new DateTime();

//assigns year, month, day


DateTime dt2 = new DateTime(2015, 12, 31);

//assigns year, month, day, hour, min, seconds


DateTime dt3 = new DateTime(2015, 12, 31, 5, 10, 20);

//assigns year, month, day, hour, min, seconds, UTC timezone


DateTime dt4 = new DateTime(2015, 12, 31, 5, 10, 20, DateTimeKind.Utc);
Try it

In the above example, we specified a year, a month, and a day in the constructor. The year can be
from 0001 to 9999, and the Month can be from 1 to 12, and the day can be from 1 to 31. Setting any
other value out of these ranges will result in a run-time exception.

Example: Invalid Date


DateTime dt = new DateTime(2015, 12, 32); //throws exception: day out of range

Use different DateTime constructors to set date, time, time zone, calendar, and culture.

Ticks

Ticks is a date and time expressed in the number of 100-nanosecond intervals that have elapsed since
January 1, 0001, at 00:00:00.000 in the Gregorian calendar. The following initializes
a DateTime object with the number of ticks.

Example: Ticks
DateTime dt = new DateTime(636370000000000000);
DateTime.MinValue.Ticks; //min value of ticks
DateTime.MaxValue.Ticks; // max value of ticks
Try it

DateTime Static Fields

The DateTime struct includes static fields, properties, and methods. The following example
demonstrates important static fields and properties.

Example: Static Fields


DateTime currentDateTime = DateTime.Now; //returns current date and time
DateTime todaysDate = DateTime.Today; // returns today's date
DateTime currentDateTimeUTC = DateTime.UtcNow;// returns current UTC date and time

DateTime maxDateTimeValue = DateTime.MaxValue; // returns max value of DateTime


DateTime minDateTimeValue = DateTime.MinValue; // returns min value of DateTime
Try it

TimeSpan

TimeSpan is a struct that is used to represent time in days, hour, minutes, seconds, and milliseconds.

Example: TimeSpan
DateTime dt = new DateTime(2015, 12, 31);

TimeSpan ts = new TimeSpan(25,20,55);

DateTime newDate = dt.Add(ts);

Console.WriteLine(newDate);//1/1/2016 1:20:55 AM
Try it

Subtraction of two dates results in TimeSpan.

Example: Subtract Dates


DateTime dt1 = new DateTime(2015, 12, 31);
DateTime dt2 = new DateTime(2016, 2, 2);
TimeSpan result = dt2.Subtract(dt1);//33.00:00:00
Try it
ADVERTISEMENT

Operators

The DateTime struct overloads +, -, ==, !=, >, <, <=, >= operators to ease out addition, subtraction,
and comparison of dates. These make it easy to work with dates.

Example: Operators
DateTime dt1 = new DateTime(2015, 12, 20);
DateTime dt2 = new DateTime(2016, 12, 31, 5, 10, 20);
TimeSpan time = new TimeSpan(10, 5, 25, 50);

Console.WriteLine(dt2 + time); // 1/10/2017 10:36:10 AM


Console.WriteLine(dt2 - dt1); //377.05:10:20
Console.WriteLine(dt1 == dt2); //False
Console.WriteLine(dt1 != dt2); //True
Console.WriteLine(dt1 > dt2); //False
Console.WriteLine(dt1 < dt2); //True
Console.WriteLine(dt1 >= dt2); //False
Console.WriteLine(dt1 <= dt2);//True
Try it

Convert String to DateTime

A valid date and time string can be converted to a DateTime object


using Parse(), ParseExact(), TryParse() and TryParseExact() methods.

The Parse() and ParseExact() methods will throw an exception if the specified string is not a valid
representation of a date and time. So, it's recommended to use TryParse() or TryParseExact() method
because they return false if a string is not valid.

Example:
var str = "5/12/2020";
DateTime dt;

var isValidDate = DateTime.TryParse(str, out dt);

if(isValidDate)
Console.WriteLine(dt);
else
Console.WriteLine($"{str} is not a valid date string");
Try it

C# - StringBuilder

Updated on: June 26, 2020

In C#, the string type is immutable. It means a string cannot be changed once created. For example, a
new string, "Hello World!" will occupy a memory space on the heap. Now, by changing the initial
string "Hello World!" to "Hello World! from Tutorials Teacher" will create a new string object on
the memory heap instead of modifying an original string at the same memory address. This behavior
would hinder the performance if the original string changed multiple times by replacing, appending,
removing, or inserting new strings in the original string.
Memory Allocation for String Object

To solve this problem, C# introduced the StringBuilder in the System.Text namespace.


The StringBuilder doesn't create a new object in the memory but dynamically expands memory to
accommodate the modified string.

Memory Allocation for StringBuilder Object

Creating a StringBuilder Object

You can create an object of the StringBuilder class using the new keyword and passing an initial
string. The following example demonstrates creating StringBuilder objects.

Example: StringBuilder
using System.Text; // include at the top

StringBuilder sb = new StringBuilder(); //string will be appended later


//or
StringBuilder sb = new StringBuilder("Hello World!");

Optionally, you can also specify the maximum capacity of the StringBuilder object using overloaded
constructors, as shown below.

Example: StringBuilder
StringBuilder sb = new StringBuilder(50); //string will be appended later
//or
StringBuilder sb = new StringBuilder("Hello World!", 50);

Above, C# allocates a maximum of 50 spaces sequentially on the memory heap. This capacity will
automatically be doubled once it reaches the specified capacity. You can also use
the capacity or length property to set or retrieve the StringBuilder object's capacity.

You can iterate the using for loop to get or set a character at the specified index.

Example: StringBuilder Iteration


StringBuilder sb = new StringBuilder("Hello World!");

for(int i = 0; i < sb.Length; i++)


Console.Write(sb[i]); // output: Hello World!
Try it

Retrieve String from StringBuilder

The StringBuilder is not the string. Use the ToString() method to retrieve a string from
the StringBuilder object.

Example: Retrieve String from StringBuilder


StringBuilder sb = new StringBuilder("Hello World!");

var greet = sb.ToString(); //returns "Hello World!"


ADVERTISEMENT

Add/Append String to StringBuilder

Use the Append() method to append a string at the end of the current StringBuilder object. If
a StringBuilder does not contain any string yet, it will add it. The AppendLine() method append a
string with the newline character at the end.

Example: Adding or Appending Strings in StringBuilder


StringBuilder sb = new StringBuilder();
sb.Append("Hello ");
sb.AppendLine("World!");
sb.AppendLine("Hello C#");
Console.WriteLine(sb);
Try it
Output:

Hello World!

Hello C#.

Append Formated String to StringBuilder

Use the AppendFormat() method to format an input string into the specified format and append it.

Example: AppendFormat()
StringBuilder sbAmout = new StringBuilder("Your total amount is ");
sbAmout.AppendFormat("{0:C} ", 25);

Console.WriteLine(sbAmout);//output: Your total amount is $ 25.00


Try it

Insert String into StringBuilder

Use the Insert() method inserts a string at the specified index in the StringBuilder object.

Example: Insert()
StringBuilder sb = new StringBuilder("Hello World!");
sb.Insert(5," C#");

Console.WriteLine(sb); //output: Hello C# World!


Try it

Remove String in StringBuilder

Use the Remove() method to remove a string from the specified index and up to the specified length.

Example: Remove()
StringBuilder sb = new StringBuilder("Hello World!",50);
sb.Remove(6, 7);

Console.WriteLine(sb); //output: Hello


Try it

Replace String in StringBuilder

Use the Replace() method to replace all the specified string occurrences with the specified
replacement string.

Example: Replace()
StringBuilder sb = new StringBuilder("Hello World!");
sb.Replace("World", "C#");

Console.WriteLine(sb);//output: Hello C#!


Try it
Points to Remember :

1. StringBuilder is mutable.
2. StringBuilder performs faster than string when appending multiple string values.
3. Use StringBuilder when you need to append more than three or four strings.
4. Use the Append() method to add or append strings to the StringBuilder object.
5. Use the ToString() method to retrieve a string from the StringBuilder object.

Value Type and Reference Type

In C#, these data types are categorized based on how they store their value in the memory. C#
includes the following categories of data types:

1. Value type
2. Reference type
3. Pointer type

Value Type

A data type is a value type if it holds a data value within its own memory space. It means the
variables of these data types directly contain values.

All the value types derive from System.ValueType, which in-turn, derives
from System.Object.

For example, consider integer variable int i = 100;

The system stores 100 in the memory space allocated for the variable i. The following image
illustrates how 100 is stored at some hypothetical location in the memory (0x239110) for 'i':

Memory Allocation of Value Type Variable

The following data types are all of value type:

 bool
 byte
 char
 decimal
 double
 enum
 float
 int
 long
 sbyte
 short
 struct
 uint
 ulong
 ushort

Passing Value Type Variables

When you pass a value-type variable from one method to another, the system creates a separate copy
of a variable in another method. If value got changed in the one method, it wouldn't affect the
variable in another method.

Example: Passing Value Type Variables


static void ChangeValue(int x)
{
x = 200;

Console.WriteLine(x);
}
static void Main(string[] args)
{
int i = 100;

Console.WriteLine(i);

ChangeValue(i);

Console.WriteLine(i);
}
Try it
Output:

100

200

100

In the above example, variable i in the Main() method remains unchanged even after we pass it to
the ChangeValue() method and change it's value there.

ADVERTISEMENT

Reference Type

Unlike value types, a reference type doesn't store its value directly. Instead, it stores the address
where the value is being stored. In other words, a reference type contains a pointer to another
memory location that holds the data.

For example, consider the following string variable:

string s = "Hello World!!";

The following image shows how the system allocates the memory for the above string variable.

Memory Allocation of
Reference Type Variable

As you can see in the above image, the system selects a random location in memory (0x803200) for
the variable s. The value of a variable s is 0x600000, which is the memory address of the actual data
value. Thus, reference type stores the address of the location where the actual value is stored instead
of the value itself.
The followings are reference type data types:

 String
 Arrays (even if their elements are value types)
 Class
 Delegate

Passing Reference Type Variables

When you pass a reference type variable from one method to another, it doesn't create a new copy;
instead, it passes the variable's address. So, If we change the value of a variable in a method, it will
also be reflected in the calling method.

Example: Passing Reference Type Variable


static void ChangeReferenceType(Student std2)
{
std2.StudentName = "Steve";
}

static void Main(string[] args)


{
Student std1 = new Student();
std1.StudentName = "Bill";

ChangeReferenceType(std1);

Console.WriteLine(std1.StudentName);
}
Try it
Output:

Steve

In the above example, we pass the Student object std1 to the ChangeReferenceType() method. Here,
it actually pass the memory address of std1. Thus, when the ChangeReferenceType() method
changes StudentName, it is actually changing StudentName of std1 object, because std1 and std2 are
both pointing to the same address in memory.

String is a reference type, but it is immutable. It means once we assigned a value, it cannot be
changed. If we change a string value, then the compiler creates a new string object in the memory
and point a variable to the new memory location. So, passing a string value to a function will create
a new variable in the memory, and any change in the value in the function will not be reflected in the
original value, as shown below.

Example: Passing String


static void ChangeReferenceType(string name)
{
name = "Steve";
}

static void Main(string[] args)


{
string name = "Bill";

ChangeReferenceType(name);
Console.WriteLine(name);
}
Try it
Output:

Bill

Null

The default value of a reference type variable is null when they are not initialized. Null means not
refering to any object.

Null Reference Type

A value type variable cannot be null because it holds value, not a memory address. C# 2.0
introduced nullable types, using which you can assign null to a value type variable or declare a value
type variable without assigning a value to it.

C# - Interface

In the human world, a contract between the two or more humans binds them to act as per the
contract. In the same way, an interface includes the declarations of related functionalities. The
entities that implement the interface must provide the implementation of declared functionalities.

In C#, an interface can be defined using the interface keyword. An interface can contain declarations
of methods, properties, indexers, and events. However, it cannot contain fields, auto-implemented
properties.

The following interface declares some basic functionalities for the file operations.

Example: C# Interface
interface IFile
{
void ReadFile();
void WriteFile(string text);
}

You cannot apply access modifiers to interface members. All the members are public by default. If
you use an access modifier in an interface, then the C# compiler will give a compile-time error "The
modifier 'public/private/protected' is not valid for this item.". (Visual Studio will show an error
immediately without compilation.)

Example: Invalid Interface with Access Modifiers


interface IFile
{
protected void ReadFile(); //compile-time error
private void WriteFile(string text);//compile-time error
}

An interface can only contain declarations but not implementations. The following will give a
compile-time error.

Example: Invalid Interface with Implementation


interface IFile
{
void ReadFile();
void WriteFile(string text){
Console.Write(text); //error: cannot implement method
}
}

Implementing an Interface

A class or a Struct can implement one or more interfaces using colon (:).

Syntax: <Class or Struct Name> : <Interface Name>

For example, the following class implements the IFile interface implicitly.

Example: Interface Implementation


interface IFile
{
void ReadFile();
void WriteFile(string text);
}

class FileInfo : IFile


{
public void ReadFile()
{
Console.WriteLine("Reading File");
}

public void WriteFile(string text)


{
Console.WriteLine("Writing to file");
}
}

In the above example, the FileInfo class implements the IFile interface. It defines all the members of
the IFile interface with public access modifier. The FileInfo class can also contain members other
than interface members.

Note:
Interface members must be implemented with the public modifier; otherwise, the compiler will give
compile-time errors.

You can create an object of the class and assign it to a variable of an interface type, as shown below.

Example: Interface Implementation


public class Program
{
public static void Main()
{
IFile file1 = new FileInfo();
FileInfo file2 = new FileInfo();

file1.ReadFile();
file1.WriteFile("content");

file2.ReadFile();
file2.WriteFile("content");
}
}
Try it

Above, we created objects of the FileInfo class and assign it to IFile type variable and FileInfo type
variable. When interface implemented implicitly, you can access IFile members with the IFile type
variables as well as FileInfo type variable.

ADVERTISEMENT

Explicit Implementation

An interface can be implemented explicitly using <InterfaceName>.<MemberName>. Explicit


implementation is useful when class is implementing multiple interfaces; thereby, it is more readable
and eliminates the confusion. It is also useful if interfaces have the same method name coincidently.

Note:
Do not use public modifier with an explicit implementation. It will give a compile-time error.
Example: Explicit Implementation
interface IFile
{
void ReadFile();
void WriteFile(string text);
}

class FileInfo : IFile


{
void IFile.ReadFile()
{
Console.WriteLine("Reading File");
}

void IFile.WriteFile(string text)


{
Console.WriteLine("Writing to file");
}
}

When you implement an interface explicitly, you can access interface members only through the
instance of an interface type.

Example: Explicit Implementation


interface IFile
{
void ReadFile();
void WriteFile(string text);
}

class FileInfo : IFile


{
void IFile.ReadFile()
{
Console.WriteLine("Reading File");
}

void IFile.WriteFile(string text)


{
Console.WriteLine("Writing to file");
}

public void Search(string text)


{
Console.WriteLine("Searching in file");
}
}

public class Program


{
public static void Main()
{
IFile file1 = new FileInfo();
FileInfo file2 = new FileInfo();

file1.ReadFile();
file1.WriteFile("content");
//file1.Search("text to be searched")//compile-time error

file2.Search("text to be searched");
//file2.ReadFile(); //compile-time error
//file2.WriteFile("content"); //compile-time error
}
}
Try it

In the above example, file1 object can only access members of IFile, and file2 can only access
members of FileInfo class. This is the limitation of explicit implementation.

Implementing Multiple Interfaces

A class or struct can implement multiple interfaces. It must provide the implementation of all the
members of all interfaces.

Example: Implement Multiple Interfaces


interface IFile
{
void ReadFile();
}

interface IBinaryFile
{
void OpenBinaryFile();
void ReadFile();
}

class FileInfo : IFile, IBinaryFile


{
void IFile.ReadFile()
{
Console.WriteLine("Reading Text File");
}

void IBinaryFile.OpenBinaryFile()
{
Console.WriteLine("Opening Binary File");
}

void IBinaryFile.ReadFile()
{
Console.WriteLine("Reading Binary File");
}

public void Search(string text)


{
Console.WriteLine("Searching in File");
}
}

public class Program


{
public static void Main()
{
IFile file1 = new FileInfo();
IBinaryFile file2 = new FileInfo();
FileInfo file3 = new FileInfo();

file1.ReadFile();
//file1.OpenBinaryFile(); //compile-time error
//file1.SearchFile("text to be searched"); //compile-time error

file2.OpenBinaryFile();
file2.ReadFile();
//file2.SearchFile("text to be searched"); //compile-time error

file3.Search("text to be searched");
//file3.ReadFile(); //compile-time error
//file3.OpenBinaryFile(); //compile-time error
}
}
Try it

Above, the FileInfo implements two interfaces IFile and IBinaryFile explicitly. It is recommended to
implement interfaces explicitly when implementing multiple interfaces to avoid confusion and more
readability.

Points to Remember :
1. Interface can contain declarations of method, properties, indexers, and events.
2. Interface cannot include private, protected, or internal members. All the members are public by
default.
3. Interface cannot contain fields, and auto-implemented properties.
4. A class or a struct can implement one or more interfaces implicitly or explicitly. Use public modifier
when implementing interface implicitly, whereas don't use it in case of explicit implementation.
5. Implement interface explicitly using InterfaceName.MemberName.
6. An interface can inherit one or more interfaces.

C# Operators

Operators in C# are some special symbols that perform some action on operands. In mathematics,
the plus symbol (+) do the sum of the left and right numbers. In the same way, C# includes various
operators for different types of operations.

The following example demonstrates the + operator in C#.

Example: + Operator
int x = 5 + 5;
int y = 10 + x;
int z = x + y;
Try it

In the above example, + operator adds two number literals and assign the result to a variable. It also
adds the values of two int variables and assigns the result to a variable.

Some operators behave differently based on the type of the operands. For example, + operator
concatenates two strings.

Example: + Operator with Strings


string greet1 = "Hello " + "World!";
string greet2 = greeting + name;
Try it
Note:
There are two types of operators in C#, Unary operators and Binary operators. Unary operators act on
single operand, whereas binary operators act on two operands (left-hand side and right-hand side
operand of an operator).

C# includes the following categories of operators:

 Arithmetic operators
 Assignment operators
 Comparison operators
 Equality operators
 Boolean logical operators
 Betwise and shift operators
 Member access operators
 Type-cast operators
 Pointer related operators

Arithmetic Operators
The arithmetic operators perform arithmetic operations on all the numeric type operands such as
sbyte, byte, short, ushort, int, uint, long, ulong, float, double, and decimal.

Operator Name Description Example


+ Addition Computes the sum of left and right operands. int x = 5 + 5; Try it
- Subtraction Subtract the right operand from the left operand int x = 5 - 1; Try it
* Multiplication Multiply left and right operand int x = 5 * 1; Try it
/ Division Divides the left operand by the right operand int x = 10 / 2; Try it
% Reminder Computes the remainder after dividing its left int x = 5 % 2; Try it
operand by its right operand
++ Unary increment Unary increment ++ operator increases its x++ Try it
operand by 1
-- Unary decrement Unary decrement -- operator decreases its x-- Try it
operand by 1
+ Unary plus Returns the value of operand +5 Try it
- Unary minus Computes the numeric negation of its operand. -5 Try it

Assignment Operators

The assignment operator = assigns its right had value to its left-hand variable, property, or indexer. It
can also be used with other arithmetic, Boolean logical, and bitwise operators.

Operato
r Name Description Example
= Assignment Assigns its right had value to its left-hand variable, property or x = 10; Try
indexer. it
x op= y Compound Short form of x =x op y where op = any arithmetic, Boolean x += 5; Try
assignment logical, and bitwise operator. it
??= Null-coalescing C# 8 onwards, ??= assigns value of the right operand only if the x ??= 5; Try
assignment left operand is null it

Comparison Operators

Comparison operators compre two numeric operands and returns true or false.

Operator Description Example


< Returns true if the right operand is less than the left operand x < y; Try it
> Returns true if the right operand is greater than the left operand x > y; Try it
<= Returns true if the right operand is less than or equal to the left operand x <= y Try it
>= Returns true if the right operand is greater than or equal to the left operand x >= y; Try it
ADVERTISEMENT

Equality Operators

The equality operator checks whether the two operands are equal or not.

Operator Description Example


== Returns true if operands are equal otherwise false. x == y; Try it
!= Returns true if operands are not equal otherwise false. x != y; Try it

Boolean Logical Operators


The Boolean logical operators perform a logical operation on bool operands.

Operato
r Description Example
! Reverses the bool result of bool expression. Returns false if result is true and returns !false Try
true if result is false. it
&& Computes the logical AND of its bool operands. Returns true both operands are true, x && y; Try
otherwise returns false. it
|| Computes the logical OR of its bool operands. Returns true when any one operand is x || y; Try
true. it

Operator Evaluation & Precedence

Evaluation of the operands in an expression starts from left to right. If multiple operators are used in
an expression, then the operators with higher priority are evaluated before the operators with lower
priority.

The following table lists operators starting with the higher precedence operators to lower precedence
operators.

Operators Category
x.y, x?.y, x?[y], f(x), a[i], x++, x--, new, typeof, checked, unchecked, default, Primary
nameof, delegate, sizeof, stackalloc, x->y
+x, -x, !x, ~x, ++x, --x, ^x, (T)x, await, &x, *x, true and false Unary
x..y Range
x * y, x / y, x % y Multiplicative
x + y, x � y Additive
x << y, x >> y Shift
x < y, x > y, x <= y, x >= y, is, as Relational and type-testing
x == y, x != y Equality
x&y Boolean logical AND
x^y Boolean logical XOR
x|y Boolean logical OR
x && y Conditional AND
x || y Conditional OR
x ?? y Null-coalescing operator
c?t:f Conditional operator
x = y, x += y, x -= y, x *= y, x /= y, x %= y, x &= y, x |= y, x ^= y, x <<= y, x >>= Assignment and lambda
y, x ??= y, => declaration

The following example demonstrates operator precedence:

Example: Operator Precedence


int a = 5 + 3 * 3;
int b = 5 + 3 * 3 / 2;
int c = (5 + 3) * 3 / 2;
int d = (3 * 3) * (3 / 3 + 5);
Try it

C# - if, else if, else Statements


Updated on: June 24, 2020

C# provides many decision-making statements that help the flow of the C# program based on certain
logical conditions. Here, you will learn about if, else if, else, and nested if else statements to control
the flow based on the conditions.

C# includes the following flavors of if statements:

1. if statement
2. else-if statement
3. else statement

C# if Statement

The if statement contains a boolean condition followed by a single or multi-line code block to be
executed. At runtime, if a boolean condition evaluates to true, then the code block will be executed,
otherwise not.

Syntax:
if(condition)
{
// code block to be executed when if condition evaluates to true
}
Example: if Statement
int i = 10, j = 20;

if (i < j)
{
Console.WriteLine("i is less than j");
}

if (i > j)
{
Console.WriteLine("i is greater than j");
}
Try it
Output:

i is less than j

In the above example, a boolean condition in the first if statement i < j evaluates to true, so the C#
compiler will execute the following code block. The second if statement's condition i > j evaluates to
false, so the compiler will not execute its code block.

The conditional expression must return a boolean value, otherwise C# compiler will give a compile-
time error.

Example: Wrong if Statement


int i = 10, j = 20;

if (i + 1)
{
Console.WriteLine("i is less than j");
}
if (i + j)
{
Console.WriteLine("i is greater than j");
}

You can call a function in the if statement that returns a boolean value.

Example: Calling Function as Condition


static void Main(string[] args)
{
int i = 10, j = 20;

if (isGreater(i, j))
{
Console.WriteLine("i is less than j");
}

if (isGreater(j, i))
{
Console.WriteLine("j is greater than i");
}
}

static bool isGreater(int i, int j)


{
return i > j;
}
Try it

else if Statement

Multiple else if statements can be used after an if statement. It will only be executed when
the if condition evaluates to false. So, either if or one of the else if statements can be executed, but
not both.

Syntax:
if(condition1)
{
// code block to be executed when if condition1 evaluates to true
}
else if(condition2)
{
// code block to be executed when
// condition1 evaluates to flase
// condition2 evaluates to true
}
else if(condition3)
{
// code block to be executed when
// condition1 evaluates to flase
// condition2 evaluates to false
// condition3 evaluates to true
}
The following example demonstrates else if statements.

Example: else if Statements


int i = 10, j = 20;

if (i == j)
{
Console.WriteLine("i is equal to j");
}
else if (i > j)
{
Console.WriteLine("i is greater than j");
}
else if (i < j)
{
Console.WriteLine("i is less than j");
}
Try it
Output:

i is less than j

ADVERTISEMENT

else Statement

The else statement can come only after if or else if statement and can be used only once in the if-
else statements. The else statement cannot contain any condition and will be executed when all the
previous if and else if conditions evaluate to false.

Example: else Statement


int i = 20, j = 20;

if (i > j)
{
Console.WriteLine("i is greater than j");
}
else if (i < j)
{
Console.WriteLine("i is less than j");
}
else
{
Console.WriteLine("i is equal to j");
}
Try it
Output:

i is equal to j

Nested if Statements

C# supports if else statements inside another if else statements. This are called nested if
else statements. The nested if statements make the code more readable.
Syntax:
if(condition1)
{
if(condition2)
{
// code block to be executed when
// condition1 and condition2 evaluates to true
}
else if(condition3)
{
if(condition4)
{
// code block to be executed when
// only condition1, condition3, and condition4 evaluates to true
}
else if(condition5)
{
// code block to be executed when
// only condition1, condition3, and condition5 evaluates to true
}
else
{
// code block to be executed when
// condition1, and condition3 evaluates to true
// condition4 and condition5 evaluates to false
}
}
}

The following example demonstrates the nested if else statements.

Example: Nested if else statements


int i = 10, j = 20;

if (i != j)
{
if (i < j)
{
Console.WriteLine("i is less than j");
}
else if (i > j)
{
Console.WriteLine("i is greater than j");
}
}
else
Console.WriteLine("i is equal to j");

Try it
Output:

i is less than j

C# - Ternary Operator ?:
Updated on: June 24, 2020

C# includes a decision-making operator ?: which is called the conditional operator or ternary


operator. It is the short form of the if else conditions.

Syntax:
condition ? statement 1 : statement 2

The ternary operator starts with a boolean condition. If this condition evaluates to true then it will
execute the first statement after ?, otherwise the second statement after : will be executed.

The following example demonstrates the ternary operator.

Example: Ternary operator


int x = 20, y = 10;

var result = x > y ? "x is greater than y" : "x is less than y";

Console.WriteLine(result);
Try it
output:

x is greater than y

Above, a conditional expression x > y returns true, so the first statement after ? will be execute.

The following executes the second statement.

Example: Ternary operator


int x = 10, y = 100;

var result = x > y ? "x is greater than y" : "x is less than y";

Console.WriteLine(result);
output:

x is less than y

Thus, a ternary operator is short form of if else statement. The above example can be re-write
using if else condition, as shown below.

Example: Ternary operator replaces if statement


int x = 10, y = 100;

if (x > y)
Console.WriteLine("x is greater than y");
else
Console.WriteLine("x is less than y");
Try it
output:
x is greater than y

Nested Ternary Operator

Nested ternary operators are possible by including a conditional expression as a second statement.

Example: Nested ?:
int x = 10, y = 100;

string result = x > y ? "x is greater than y" :


x < y ? "x is less than y" :
x == y ? "x is equal to y" : "No result";

Console.WriteLine(result);
Try it

The ternary operator is right-associative. The expression a ? b : c ? d : e is evaluated as a ? b : (c ? d :


e), not as (a ? b : c) ? d : e.

Example: Nested ?:
var x = 2, y = 10;

var result = x * 3 > y ? x : y > z? y : z;


Console.WriteLine(result);
Try it

C# - Switch Statement

Updated on: June 25, 2020

The switch statement can be used instead of if else statement when you want to test a variable
against three or more conditions. Here, you will learn about the switch statement and how to use it
efficiently in the C# program.

The following is the general syntax of the switch statement.

Syntax:
switch(match expression/variable)
{
case constant-value:
statement(s) to be executed;
break;
default:
statement(s) to be executed;
break;
}

The switch statement starts with the switch keyword that contains a match expression or a variable in
the bracket switch(match expression). The result of this match expression or a variable will be tested
against conditions specified as cases, inside the curly braces { }. A case must be specified with the
unique constant value and ends with the colon :. Each case includes one or more statements to be
executed. The case will be executed if a constant value and the value of a match expression/variable
are equal. The switch statement can also contain an optional default label. The default label will be
executed if no cases executed. The break, return, or goto keyword is used to exit the program control
from a switch case.

The following example demonstrates a simple switch statement.

Example: C# Switch Statement


int x = 10;

switch (x)
{
case 5:
Console.WriteLine("Value of x is 5");
break;
case 10:
Console.WriteLine("Value of x is 10");
break;
case 15:
Console.WriteLine("Value of x is 15");
break;
default:
Console.WriteLine("Unknown value");
break;
}
Try it
Output:

Value of x is 10

Above, the switch(x) statement includes a variable x whose value will be matched with the value of
each case value. The above switch statement contains three cases with constant values 5, 10, and 15.
It also contains the default label, which will be executed if none of the case value match with the
switch variable/expression. Each case starts after : and includes one statement to be executed. The
value of x matches with the second case case 10:, so the output would be Value of x is 10.

Note:
The switch statement can include any non-null expression that returns a value of type: char, string, bool,
int, or enum.

The switch statement can also include an expression whose result will be tested against each case at
runtime.

Example: C# Switch Statement


int x = 125;

switch (x % 2)
{
case 0:
Console.WriteLine($"{x} is an even value");
break;
case 1:
Console.WriteLine($"{x} is an odd Value");
break;
}
Try it
Output:

125 is an odd value

ADVERTISEMENT

Switch Case

The switch cases must be unique constant values. It can be bool, char, string, integer, enum, or
corresponding nullable type.

Note
C# 7.0 onward, switch cases can include non-unique values. In this case, the first matching case will be
executed.

Consider the following example of a simple switch statement.

Example: switch statement


string statementType = "switch";

switch (statementType)
{
case "if.else":
Console.WriteLine("if...else statement");
break;
case "ternary":
Console.WriteLine("Ternary operator");
break;
case "switch":
Console.WriteLine("switch statement");
break;
}
Try it
Output:

switch statement

Multiple cases can be combined to execute the same statements.

Example: C# Combined Switch Cases


int x = 5;

switch (x)
{
case 1:
Console.WriteLine("x = 1");
break;
case 2:
Console.WriteLine("x = 2");
break;
case 4:
case 5:
Console.WriteLine("x = 4 or x = 5");
break;
default:
Console.WriteLine("x > 5");
break;
}
Try it

Each case must exit the case explicitly by using break, return, goto statement, or some other way,
making sure the program control exits a case and cannot fall through to the default case.

The following use the return keyword.

Example: return in Switch Case


static void Main(string[] args)
{
int x = 125;
Console.Write( isOdd(x)? "Even value" : "Odd value");
}

static bool isOdd(int i, int j)


{
switch (x % 2)
{
case 0:
return true;
case 1:
return false;
default:
return false;
}

return false;
}
Try it
Output:

Odd value

The switch cases without break, return, or goto statement or with the same constant values would
give a compile-time error.

Example: C# Switch Statement


int x = 1;

switch (x)
{
case 0:
Console.WriteLine($"{x} is even value");
break;
case 1:
Console.WriteLine($"{x} is odd Value");
break;
case 1: // Error - Control cannot fall through from one case label ('case 1:') to another
Console.WriteLine($"{x} is odd Value");
defaut:
Console.WriteLine($"{x} is odd Value");
break;
}

Nested Switch Statements

A switch statement can be used inside another switch statement.

Example: Nested switch statements


int j = 5;

switch (j)
{
case 5:
Console.WriteLine(5);
switch (j - 1)
{
case 4:
Console.WriteLine(4);
switch (j - 2)
{
case 3:
Console.WriteLine(3);
break;
}
break;
}
break;
case 10:
Console.WriteLine(10);
break;
case 15:
Console.WriteLine(15);
break;
default:
Console.WriteLine(100);
break;
}

Try it
Output:

Points to Remember :

1. The switch statement is an alternative to if else statement.


2. The switch statement tests a match expression/variable against a set of constants specified as cases.
3. The switch case must include break, return, goto keyword to exit a case.
4. The switch can include one optional default label, which will be executed when no case executed.
5. C# compiler will give errors on missing :, constant value with cases, exit from a case.
6. C# 7.0 onward, switch cases can include non-unique values. In this case, the first matching case will
be executed.

C# for Loop

Updated on: June 17, 2020

Here, you will learn how to execute a statement or code block multiple times using the for loop,
structure of the for loop, nested for loops, and how to exit from the for loop.

The for keyword indicates a loop in C#. The for loop executes a block of statements repeatedly until
the specified condition returns false.

Syntax:
for (initializer; condition; iterator)
{
//code block
}

The for loop contains the following three optional sections, separated by a semicolon:

Initializer: The initializer section is used to initialize a variable that will be local to a for loop and
cannot be accessed outside loop. It can also be zero or more assignment statements, method call,
increment, or decrement expression e.g., ++i or i++, and await expression.

Condition: The condition is a boolean expression that will return either true or false. If an
expression evaluates to true, then it will execute the loop again; otherwise, the loop is exited.

Iterator: The iterator defines the incremental or decremental of the loop variable.

The following for loop executes a code block 10 times.

Example: for Loop


for(int i = 0; i < 10; i++)
{
Console.WriteLine("Value of i: {0}", i);
}
Try it
Output:

Value of i: 0

Value of i: 1

Value of i: 2
Value of i: 3

Value of i: 4

Value of i: 5

Value of i: 6

Value of i: 7

Value of i: 8

Value of i: 9

In the above example, int i = 0 is an initializer where we define an int variable i and initialize it with
0. The second section is the condition expression i < 10, if this condition returns true then it will
execute a code block. After executing the code block, it will go to the third section, iterator. The i+
+ is an incremental statement that increases the value of a loop variable i by 1. Now, it will check the
conditional expression again and repeat the same thing until conditional expression returns false.
The below figure illustrates the execution steps of the for loop.

The below figure illustrates the execution steps of the for loop.

for Loop Execution Steps

If a code block only contains a single statement, then you don't need to wrap it inside curly
brackets { }, as shown below.

Example: for Loop


for(int i = 0; i < 10; i++)
Console.WriteLine("Value of i: {0}", i);

An Initializer, condition, and iterator sections are optional. You can initialize a variable
before for loop, and condition and iterator can be defined inside a code block, as shown below.

Example: for loop C#


int i = 0;

for(;;)
{
if (i < 10)
{
Console.WriteLine("Value of i: {0}", i);
i++;
}
else
break;
}
Try it
Output:

Value of i: 0

Value of i: 1

Value of i: 2

Value of i: 3

Value of i: 4

Value of i: 5

Value of i: 6

Value of i: 7

Value of i: 8

Value of i: 9

Since all three sections are optional in the for loop, be careful in defining a condition and iterator.
Otherwise, it will be an infinite loop that will never end the loop.

Example: Infinite for Loop


for ( ; ; )
{
Console.Write(1);
}
Output:

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1.....

The control variable for the for loop can be of any numeric data type, such as double, decimal, etc.

Example: Decimal for Loop


for (double d = 1.01D; d < 1.10; d+= 0.01D)
{
Console.WriteLine("Value of i: {0}", d);
}
Try it
Output:

Value of i: 1.01

Value of i: 1.02

Value of i: 1.03

Value of i: 1.04

Value of i: 1.05

Value of i: 1.06

Value of i: 1.07

Value of i: 1.08

Value of i: 1.09

The steps part in a for loop can either increase or decrease the value of a variable.

Example: Reverse for Loop


for(int i = 10; i > 0; i--)
{
Console.WriteLine("Value of i: {0}", i);
}
Try it
Output:

Value of i: 10

Value of i: 9

Value of i: 8

Value of i: 7

Value of i: 6

Value of i: 5
Value of i: 4

Value of i: 3

Value of i: 2

Value of i: 1

Exit the for Loop

You can also exit from a for loop by using the break keyword.

Example: break in for loop


for (int i = 0; i < 10; i++)
{
if( i == 5 )
break;

Console.WriteLine("Value of i: {0}", i);


}
Try it
Output:

Value of i: 0

Value of i: 1

Value of i: 2

Value of i: 3

Value of i: 4

Multiple Expressions

A for loop can also include multiple initializer and iterator statements separated by comma, as shown
below.

Example: Multiple Expressions


for (int i = 0, j = 0; i+j < 5; i++, j++)
{
Console.WriteLine("Value of i: {0}, J: {1} ", i,j);
}
Try it
Output:
Value of i: 0, J: 0

Value of i: 1, J: 1

Value of i: 2, J: 2

A for loop can also contain statements as an initializer and iterator.

Example: Initializer and Iterator Statements


int i = 0, j = 5;
for (Console.WriteLine($"Initializer: i={i}, j={j}");
i++ < j--;
Console.WriteLine($"Iterator: i={i}, j={j}"))
{
}
Try it
Output:

Initializer: i=0, j=5

Iterator: i=1, j=4

Iterator: i=2, j=3

Iterator: i=3, j=2

Nested for Loop

C# allows a for loop inside another for loop.

Example: Nested for loop


for (int i = 0; i < 2; i++)
{
for(int j =i; j < 4; j++)
Console.WriteLine("Value of i: {0}, J: {1} ", i,j);
}
Try it
Output:

Value of i: 0, J: 0

Value of i: 0, J: 1

Value of i: 0, J: 2
Value of i: 0, J: 3

Value of i: 1, J: 1

Value of i: 1, J: 2

Value of i: 1, J: 3

C# - while Loop

C# provides the while loop to repeatedly execute a block of code as long as the specified condition
returns false.

Syntax:
While(condition)
{
//code block
}

The while loop starts with the while keyword, and it must include a boolean conditional expression
inside brackets that returns either true or false. It executes the code block until the specified
conditional expression returns false.

The for loop contains the initialization and increment/decrement parts. When using the while loop,
initialization should be done before the loop starts, and increment or decrement steps should be
inside the loop.

Example: C# while Loop


int i = 0; // initialization

while (i < 10) // condition


{
Console.WriteLine("i = {0}", i);

i++; // increment
}
Try it
Output:

i = 0

i = 1

i = 2

i = 3
i = 4

i = 5

i = 6

i = 7

i = 8

i=9

Above, a while loop includes an expression i < 10. Inside a while loop, the value of i increased to 1
using i++. The above while loop will be executed when the value of i equals to 10 and a condition i
< 10 returns false.

Use the break or return keyword to exit from a while loop on some condition, as shown below.

Example: Exit from the while Loop


int i = 0;

while (true)
{
Console.WriteLine("i = {0}", i);

i++;

if (i > 10)
break;
}
Try it

Ensure that the conditional expression evaluates to false or exit from the while loop on some
condition to avoid an infinite loop. The following loop is missing an appropriate condition or break
the loop, which makes it an infinite while loop.

Example: Infinite While Loop


int i = 1;

while (i > 0)
{
Console.WriteLine("i = {0}", i);
i++;
}

Nested while Loop

C# allows while loops inside another while loop, as shown below. However, it is not recommended
to use nested while loop because it makes it hard to debug and maintain.
Example: Nested while Loop
int i = 0, j = 1;

while (i < 2)
{
Console.WriteLine("i = {0}", i);
i++;

while (j < 2)
{
Console.WriteLine("j = {0}", j);
j++;
}
}
Try it
Output:

i = 0

j = 1

i=1

C# - do while Loop

The do while loop is the same as while loop except that it executes the code block at least once.

Syntax:
do
{
//code block

} while(condition);

The do-while loop starts with the do keyword followed by a code block and a boolean expression
with the while keyword. The do while loop stops execution exits when a boolean condition evaluates
to false. Because the while(condition) specified at the end of the block, it certainly executes the code
block at least once.

Example: do-while Loop


int i = 0;

do
{
Console.WriteLine("i = {0}", i);
i++;

} while (i < 5);


Try it
Output:
i = 0

i = 1

i = 2

i = 3

i=4

Specify initialization out of the loop and increment/decrement counter inside do while loop.

Use break or return to exit from the do while loop.

Example: Exit from the do-while Loop


int i = 0;

do
{
Console.WriteLine("i = {0}", i);
i++;

if (i > 5)
break;

} while (i < 10);


Try it
Output:

i = 0

i = 1

i = 2

i = 3

i = 4

i=5

Nested do-while

The do-while loop can be used inside another do-while loop.

Example: Nested do-while Loop


int i = 0;

do
{
Console.WriteLine("Value of i: {0}", i);
int j = i;

i++;

do
{
Console.WriteLine("Value of j: {0}", j);
j++;
} while (j < 2);

} while (i < 2);


Try it
Output:

i = 0

j = 0

j = 1

i = 1

j=1

C# - Static Class, Methods, Constructors, Fields

Updated on: June 28, 2020

In C#, static means something which cannot be instantiated. You cannot create an object of a static
class and cannot access static members using an object.

C# classes, variables, methods, properties, operators, events, and constructors can be defined as
static using the static modifier keyword.

Static Class

Apply the static modifier before the class name and after the access modifier to make a class static.
The following defines a static class with static fields and methods.

Example: C# Static Class


public static class Calculator
{
private static int _resultStorage = 0;
public static string Type = "Arithmetic";

public static int Sum(int num1, int num2)


{
return num1 + num2;
}

public static void Store(int result)


{
_resultStorage = result;
}
}

Above, the Calculator class is a static. All the members of it are also static.

You cannot create an object of the static class; therefore the members of the static class can be
accessed directly using a class name like ClassName.MemberName, as shown below.

Example: Accessing Static Members


class Program
{
static void Main(string[] args)
{
var result = Calculator.Sum(10, 25); // calling static method
Calculator.Store(result);

var calcType = Calculator.Type; // accessing static variable


Calculator.Type = "Scientific"; // assign value to static variable
}
}
Try it

Rules for Static Class

1. Static classes cannot be instantiated.


2. All the members of a static class must be static; otherwise the compiler will give an error.
3. A static class can contain static variables, static methods, static properties, static operators, static
events, and static constructors.
4. A static class cannot contain instance members and constructors.
5. Indexers and destructors cannot be static
6. var cannot be used to define static members. You must specify a type of member explicitly after
the static keyword.
7. Static classes are sealed class and therefore, cannot be inherited.
8. A static class cannot inherit from other classes.
9. Static class members can be accessed using ClassName.MemberName.
10. A static class remains in memory for the lifetime of the application domain in which your
program resides.

Static Members in Non-static Class

The normal class (non-static class) can contain one or more static methods, fields, properties, events
and other non-static members.

It is more practical to define a non-static class with some static members, than to declare an entire
class as static.
Static Fields

Static fields in a non-static class can be defined using the static keyword.

Static fields of a non-static class is shared across all the instances. So, changes done by one instance
would reflect in others.

Example: Shared Static Fields


public class StopWatch
{
public static int InstanceCounter = 0;
// instance constructor
public StopWatch()
{
}
}

class Program
{
static void Main(string[] args)
{
StopWatch sw1 = new StopWatch();
StopWatch sw2 = new StopWatch();
Console.WriteLine(StopWatch.NoOfInstances); //2

StopWatch sw3 = new StopWatch();


StopWatch sw4 = new StopWatch();
Console.WriteLine(StopWatch.NoOfInstances);//4
}
}
Try it
ADVERTISEMENT

Static Methods

You can define one or more static methods in a non-static class. Static methods can be called without
creating an object. You cannot call static methods using an object of the non-static class.

The static methods can only call other static methods and access static members. You cannot access
non-static members of the class in the static methods.

Example: Static Method


class Program
{
static int counter = 0;
string name = "Demo Program";

static void Main(string[] args)


{
counter++; // can access static fields
Display("Hello World!"); // can call static methods

name = "New Demo Program"; //Error: cannot access non-static members


SetRootFolder("C:\MyProgram"); //Error: cannot call non-static method
}
static void Display(string text)
{
Console.WriteLine(text);
}

public void SetRootFolder(string path) { }


}

Rules for Static Methods

1. Static methods can be defined using the static keyword before a return type and after an access
modifier.
2. Static methods can be overloaded but cannot be overridden.
3. Static methods can contain local static variables.
4. Static methods cannot access or call non-static variables unless they are explicitly passed as
parameters.

Static Constructors

A non-static class can contain a parameterless static constructor. It can be defined with the static
keyword and without access modifiers like public, private, and protected.

The following example demonstrates the difference between static constructor and instance
constructor.

Example: Static Constructor vs Instance Constructor


public class StopWatch
{
// static constructor
static StopWatch()
{
Console.WriteLine("Static constructor called");
}

// instance constructor
public StopWatch()
{
Console.WriteLine("Instance constructor called");
}

// static method
public static void DisplayInfo()
{
Console.WriteLine("DisplayInfo called");
}

// instance method
public void Start() { }

// instance method
public void Stop() { }
}
Try it

Above, the non-static class StopWatch contains a static constructor and also a non-static constructor.
The static constructor is called only once whenever the static method is used or creating an instance
for the first time. The following example shows that the static constructor gets called when the static
method called for the first time. Calling the static method second time onwards won't call a static
constructor.

Example: Static Constructor Execution


StopWatch.DisplayInfo(); // static constructor called here
StopWatch.DisplayInfo(); // none of the constructors called here
Output:

Static constructor called.

DisplayInfo called

DisplayInfo called

The following example shows that the static constructor gets called when you create an instance for
the first time.

Example: Static Constructor Execution


StopWatch sw1 = new StopWatch(); // First static constructor and then instance constructor called
StopWatch sw2 = new StopWatch();// only instance constructor called
StopWatch.DisplayInfo();
Output:

Static constructor called

instance constructor called

instance constructor called

DisplayInfo called

Rules for Static Constructors

1. The static constructor is defined using the static keyword and without using access modifiers
public, private, or protected.
2. A non-static class can contain one parameterless static constructor. Parameterized static
constructors are not allowed.
3. Static constructor will be executed only once in the lifetime. So, you cannot determine when it
will get called in an application if a class is being used at multiple places.
4. A static constructor can only access static members. It cannot contain or access instance
members.

Note:
Static members are stored in a special area in the memory called High-Frequency Heap. Static members
of non-static classes are shared across all the instances of the class. So, the changes done by one
instance will be reflected in all the other instances.

C# Arrays
Updated on: May 10, 2020

A variable is used to store a literal value, whereas an array is used to store multiple literal values.

An array is the data structure that stores a fixed number of literal values (elements) of the same data
type. Array elements are stored contiguously in the memory.

In C#, an array can be of three types: single-dimensional, multidimensional, and jagged array. Here
you will learn about the single-dimensional array.

The following figure illustrates an array representation.

Array Representation

Array Declaration and Initialization

An array can be declared using by specifying the type of its elements with square brackets.

Example: Array Declaration


int[] evenNums; // integer array

string[] cities; // string array

The following declares and adds values into an array in a single statement.

Example: Array Declaration & Initialization


int[] evenNums = new int[5]{ 2, 4, 6, 8, 10 };

string[] cities = new string[3]{ "Mumbai", "London", "New York" };

Above, evenNums array can store up to five integers. The number 5 in the square brackets new
int[5] specifies the size of an array. In the same way, the size of cities array is three. Array elements
are added in a comma-separated list inside curly braces { }.

Arrays type variables can be declared using var without square brackets.

Example: Array Declaration using var


var evenNums = new int[]{ 2, 4, 6, 8, 10};

var cities = new string[]{ "Mumbai", "London", "New York" };

If you are adding array elements at the time of declaration, then size is optional. The compiler will
infer its size based on the number of elements inside curly braces, as shown below.

Example: Short Syntax of Array Declaration


int[] evenNums = { 2, 4, 6, 8, 10};

string[] cities = { "Mumbai", "London", "New York" }

The following example demonstrate invalid array declarations.

Example: Invalid Array Creation


//must specify the size
int[] evenNums = new int[];

//number of elements must be equal to the specified size


int[] evenNums = new int[5] { 2, 4 };

//cannot use var with array initializer


var evenNums = { 2, 4, 6, 8, 10};

Late Initialization

It is not necessary to declare and initialize an array in a single statement. You can first declare an
array then initialize it later on using the new operator.

Example: Late Initialization


int[] evenNums;

evenNums = new int[5];


// or
evenNums = new int[]{ 2, 4, 6, 8, 10 };
ADVERTISEMENT

Accessing Array Elements

Array elements can be accessed using an index. An index is a number associated with each array
element, starting with index 0 and ending with array size - 1.

The following example add/update and retrieve array elements using indexes.

Example: Access Array Elements using Indexes


int[] evenNums = new int[5];
evenNums[0] = 2;
evenNums[1] = 4;
//evenNums[6] = 12; //Throws run-time exception IndexOutOfRange

Console.WriteLine(evenNums[0]); //prints 2
Console.WriteLine(evenNums[1]); //prints 4
Try it

Note that trying to add more elements than its specified size will result
in IndexOutOfRangeException.

Accessing Array using for Loop

Use the for loop to access array elements. Use the length property of an array in conditional
expression of the for loop.

Example: Accessing Array Elements using for Loop


int[] evenNums = { 2, 4, 6, 8, 10 };

for(int i = 0; i < evenNums.Length; i++)


Console.WriteLine(evenNums[i]);

for(int i = 0; i < evenNums.Length; i++)


evenNums[i] = evenNums[i] + 10; // update the value of each element by 10
Try it

Accessing Array using foreach Loop

Use foreach loop to read values of an array elements without using index.

Example: Accessing Array using foreach Loop


int[] evenNums = { 2, 4, 6, 8, 10};
string[] cities = { "Mumbai", "London", "New York" };

foreach(var item in evenNums)


Console.WriteLine(item);

foreach(var city in cities)


Console.WriteLine(city);
Try it

LINQ Methods

All the arrays in C# are derived from an abstract base class System.Array.

The Array class implements the IEnumerable interface, so you can LINQ extension methods such
as Max(), Min(), Sum(), reverse(), etc. See the list of all extension methods here.

Example: LINQ Methods


int[] nums = new int[5]{ 10, 15, 16, 8, 6 };

nums.Max(); // returns 16
nums.Min(); // returns 6
nums.Sum(); // returns 55
nums.Average(); // returns 55
Try it

The System.Array class also includes methods for creating, manipulating, searching, and sorting
arrays. See list of all Array methods here.

Example: Array Methods


int[] nums = new int[5]{ 10, 15, 16, 8, 6 };

Array.Sort(nums); // sorts array


Array.Reverse(nums); // sorts array in descending order
Array.ForEach(nums, n => Console.WriteLine(n)); // iterates array
Array.BinarySearch(nums, 5);// binary search
Try it

Passing Array as Argument

An array can be passed as an argument to a method parameter. Arrays are reference types, so the
method can change the value of the array elements.
Example: Passing Array as Argument
public static void Main(){
int[] nums = { 1, 2, 3, 4, 5 };

UpdateArray(nums);

foreach(var item in nums)


Console.WriteLine(item);
}

public static void UpdateArray(int[] arr)


{
for(int i = 0; i < arr.Length; i++)
arr[i] = arr[i] + 10;
}
Try it

C# - Multidimensional Arrays

C# supports multidimensional arrays up to 32 dimensions. The multidimensional array can be


declared by adding commas in the square brackets. For example, [,] declares two-dimensional array,
[, ,] declares three-dimensional array, [, , ,] declares four-dimensional array, and so on. So, in a
multidimensional array, no of commas = No of Dimensions - 1.

The following declares multidimensional arrays.

Example: Multidimensional Arrays


int[,] arr2d; // two-dimensional array
int[, ,] arr3d; // three-dimensional array
int[, , ,] arr4d ; // four-dimensional array
int[, , , ,] arr5d; // five-dimensional array

Let's understand the two-dimensional array. The following initializes the two-dimensional array.

Example: two-dimensional Array


int[,] arr2d = new int[3,2]{
{1, 2},
{3, 4},
{5, 6}
};

// or
int[,] arr2d = {
{1, 2},
{3, 4},
{5, 6}
};

In the above example of a two-dimensional array, [3, 2] defines the no of rows and columns. The
first rank denotes the no of rows, and the second rank defines no of columns. The following figure
illustrates the two-dimensional array divided into rows and columns.
Two-dimensional Array

The following access values of the two-dimensional array.

Example: Access two-dimensional Array


int[,] arr2d = new int[3,2]{
{1, 2},
{3, 4},
{5, 6}
};

arr2d[0, 0]; //returns 1


arr2d[0, 1]; //returns 2
arr2d[1, 0]; //returns 3
arr2d[1, 1]; //returns 4
arr2d[2, 0]; //returns 5
arr2d[2, 1]; //returns 6
//arr2d[3, 0]; //throws run-time error as there is no 4th row
Try it

In the above example, the value of a two-dimensional array can be accessed by index no of row and
column as [row index, column index]. So, [0, 0] returns the value of the first row and first column
and [1, 1] returns the value from the second row and second column.

Now, let's understand the three-dimensional array. The following declares and initializes three-
dimensional arrays.

Example: Three-dimensional Array


int[, ,] arr3d1 = new int[1, 2, 2]{
{ { 1, 2}, { 3, 4} }
};

int[, ,] arr3d2 = new int[2, 2, 2]{


{ {1, 2}, {3, 4} },
{ {5, 6}, {7, 8} }
};

int[, ,] arr3d3 = new int[2, 2, 3]{


{ { 1, 2, 3}, {4, 5, 6} },
{ { 7, 8, 9}, {10, 11, 12} }
};

arr3d2[0, 0, 0]; // returns 1


arr3d2[0, 0, 1]; // returns 2
arr3d2[0, 1, 0]; // returns 3
arr3d2[0, 1, 1]; // returns 4
arr3d2[1, 0, 0]; // returns 5
arr3d2[1, 0, 1]; // returns 6
arr3d2[1, 1, 0]; // returns 7
arr3d2[1, 1, 1]; // returns 8
Try it

As you can see in the above example, [1, 2, 2] of arr3d1 specifies that it will contain one row of two-
dimensional array [2, 2]. arr3d2 specifies dimensions [2, 2, 2], which indicates that it includes two
rows of two-dimensional array of [2, 2]. Thus, the first rank indicates the number of rows of inner
two-dimensional arrays.

Now, consider the following four-dimensional array.

Example: Four-dimensional Array


int[,,,] arr4d1 = new int[1, 1, 2, 2]{
{
{ { 1, 2}, { 3, 4} }
}
};

arr4d1[0, 0, 0, 0]; // returns 1


arr4d1[0, 0, 0, 1]; // returns 2
arr4d1[0, 0, 1, 0]; // returns 3
arr4d1[0, 0, 1, 1]; // returns 4

int[,,,] arr4d2 = new int[1, 2, 2, 2]{


{
{ {1, 2}, {3, 4} },
{ {5, 6}, {7, 8} }
}
};

arr4d2[0, 0, 0, 0]; // returns 1


arr4d2[0, 0, 0, 1]; // returns 2
arr4d2[0, 0, 1, 0]; // returns 3
arr4d2[0, 0, 1, 1]; // returns 4
arr4d2[0, 1, 0, 0]; // returns 5
arr4d2[0, 1, 0, 1]; // returns 6
arr4d2[0, 1, 1, 0]; // returns 7
arr4d2[0, 1, 1, 1]; // returns 8
Try it

In the above example, the four-dimensional array arr4d1 specifies [1, 1, 2, 2], which indicates that it
includes one row of the three-dimensional array.

In the same way, you can declare and initialize five-dimensional, six-dimensional array, and up to
32-dimensional arrays in C#.

C# Jagged Arrays: An Array of Array

A jagged array is an array of array. Jagged arrays store arrays instead of literal values.

A jagged array is initialized with two square brackets [][]. The first bracket specifies the size of an
array, and the second bracket specifies the dimensions of the array which is going to be stored.

The following example declares jagged arrays.


Example: Jagged Arrays
int[][] jArray1 = new int[2][]; // can include two single-dimensional arrays
int[][,] jArray2 = new int[3][,]; // can include three two-dimensional arrays

In the above example, jArray1 can store up to two single-dimensional arrays. jArray2 can store up to
three two-dimensional, arrays [,] specifies the two-dimensional array.

Example: Jagged Array


int[][] jArray = new int[2][];

jArray[0] = new int[3]{1, 2, 3};

jArray[1] = new int[4]{4, 5, 6, 7 };

You can also initialize a jagged array upon declaration like the below.

Example: Jagged Array


int[][] jArray = new int[2][]{
new int[3]{1, 2, 3},

new int[4]{4, 5, 6, 7}
};

jArray[0][0]; //returns 1
jArray[0][1]; //returns 2
jArray[0][2]; //returns 3
jArray[1][0]; //returns 4
jArray[1][1]; //returns 5
jArray[1][2]; //returns 6
jArray[1][3]; //returns 7
Try it

You can access a jagged array using two for loops, as shown below.

Example: Jagged Array


int[][] jArray = new int[2][]{
new int[3]{1, 2, 3},

new int[4]{4, 5, 6, 7}
};

for(int i=0; i<jArray.Length; i++)


{
for(int j=0; j < (jArray[i]).Length; j++)
Console.WriteLine(jArray[i][j]);
}
Try it

The following jagged array stores two-dimensional arrays where the second bracket [,] indicates the
two-dimensional array.

Example: Jagged Array


int[][,] jArray = new int[2][,];

jArray[0] = new int[3, 2] { { 1, 2 }, { 3, 4 }, { 5, 6 } };


jArray[1] = new int[2, 2] { { 7, 8 }, { 9, 10 } };

jArray[0][1, 1]; //returns 4

jArray[1][1, 0]; //returns 9

jArray[1][1, 1]; //returns 10


Try it

If you add one more bracket then it will be array of array of arry.

Example: Jagged Array


int[][][] intJaggedArray = new int[2][][]
{
new int[2][]
{
new int[3] { 1, 2, 3},
new int[2] { 4, 5}
},
new int[1][]
{
new int[3] { 7, 8, 9}
}
};

Console.WriteLine(intJaggedArray[0][0][0]); // 1

Console.WriteLine(intJaggedArray[0][1][1]); // 5

Console.WriteLine(intJaggedArray[1][0][2]); // 9
Try it

In the above example of a jagged array, three brackets [][][] means an array of array of array.
So, intJaggedArray will contain two elements, which means two arrays. Now, each of these arrays
also contains an array (single-dimension). intJaggedArray[0][0][0] points to the first element of first
inner array. intJaggedArray[1][0][2] points to the third element of the second inner array. The
following figure illustrates this.

Jagged Array

Built-in Exception Classes in C#


Here you will learn about the built-in exception classes in C#.

C# .NET includes built-in exception classes for every possible error. The Exception class is the base
class of all the exception classes.

The following is a hierarchy of exception classes in .NET:

E
xception Classes in .NET

In the above figure, the Exception class is the base class of


the SystemException and ApplicationException classes. The SystemException class is the base class
for all the built-in exception classes in .NET Framework.

The ApplicationException was recommended to be base class for all your custom exceptions classes
(The custom exeception class should be created if non of the system exception classes can be used
and you need new exception class for business rule violations or for other application related errors).
It was meant to differentiates between exceptions defined by applications versus exceptions defined
by the system. However, Microsoft now recommends to derive custom exception classes from
the Exception class rather than the ApplicationException class .

The following figure shows how the NullReferenceException is thrown in Visual Studio debug
mode when you access a null object property at runtime.

NullRefer
enceException
Built-in Exception Classes

The following table lists important built-in exception classes in .NET.

Exception Class Description


ArgumentException Raised when a non-null argument that is passed to a method is invalid.
ArgumentNullException Raised when null argument is passed to a method.
ArgumentOutOfRangeExceptio Raised when the value of an argument is outside the range of valid values.
n
DivideByZeroException Raised when an integer value is divide by zero.
FileNotFoundException Raised when a physical file does not exist at the specified location.
FormatException Raised when a value is not in an appropriate format to be converted from a
string by a conversion method such as Parse.
IndexOutOfRangeException Raised when an array index is outside the lower or upper bounds of an array
or collection.
InvalidOperationException Raised when a method call is invalid in an object's current state.
KeyNotFoundException Raised when the specified key for accessing a member in a collection is not
exists.
NotSupportedException Raised when a method or operation is not supported.
NullReferenceException Raised when program access members of null object.
OverflowException Raised when an arithmetic, casting, or conversion operation results in an
overflow.
OutOfMemoryException Raised when a program does not get enough memory to execute the code.
StackOverflowException Raised when a stack in memory overflows.
TimeoutException The time interval allotted to an operation has expired.

When an error occurs, either the application code or the default handler handles the exception. Learn
how to handle the excetion in the next section.

Exception Handling in C#

Here, you will learn about exception handling in C# using try, catch, and finally blocks.

Exceptions in the application must be handled to prevent crashing of the program and unexpected
result, log exceptions and continue with other functionalities. C# provides built-in support to handle
the exception using try, catch & finally blocks.

Syntax:
try
{
// put the code here that may raise exceptions
}
catch
{
// handle exception here
}
finally
{
// final cleanup code
}

try block: Any suspected code that may raise exceptions should be put inside a try{ } block. During
the execution, if an exception occurs, the flow of the control jumps to the first matching catch block.
catch block: The catch block is an exception handler block where you can perform some action such
as logging and auditing an exception. The catch block takes a parameter of an exception type using
which you can get the details of an exception.

finally block: The finally block will always be executed whether an exception raised or not.
Usually, a finally block should be used to release resources, e.g., to close any stream or file objects
that were opened in the try block.

The following may throw an exception if you enter a non-numeric character.

Example: C# Program
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Enter a number: ");

var num = int.Parse(Console.ReadLine());

Console.WriteLine($"Squre of {num} is {num * num}");


}
}
Try it

To handle the possible exceptions in the above example, wrap the code inside a try block and handle
the exception in the catch block, as shown below.

Example: Exception handling using try-catch blocks


class Program
{
static void Main(string[] args)
{
try
{
Console.WriteLine("Enter a number: ");

var num = int.parse(Console.ReadLine());

Console.WriteLine($"Squre of {num} is {num * num}");


}
catch
{
Console.Write("Error occurred.");
}
finally
{
Console.Write("Re-try with a different number.");
}
}
}
Try it

In the above example, we wrapped this code inside a try block. If an exception occurs inside
a try block, then the program will jump to the catch block. Inside a catch block, we display a
message to instruct the user about his mistake, and in the finally block, we display a message about
what to do after running a program.
Note:
A try block must be followed by catch or finally or both blocks. The try block without
a catch or finally block will give a compile-time error.

Ideally, a catch block should include a parameter of a built-in or custom exception class to get an
error detail. The following includes the Exception type parameter that catches all types of
exceptions.

Example: Exception handling using try catch block


class Program
{
static void Main(string[] args)
{
try
{
Console.WriteLine("Enter a number: ");

var num = int.parse(Console.ReadLine());

Console.WriteLine($"Squre of {num} is {num * num}");


}
catch(Exception ex)
{
Console.Write("Error info:" + ex.Message);
}
finally
{
Console.Write("Re-try with a different number.");
}
}
}

Exception Filters

You can use multiple catch blocks with the different exception type parameters. This is called
exception filters. Exception filters are useful when you want to handle different types of exceptions
in different ways.

Example: Exception Filters


class Program
{
static void Main(string[] args)
{
Console.Write("Please enter a number to divide 100: ");

try
{
int num = int.Parse(Console.ReadLine());

int result = 100 / num;

Console.WriteLine("100 / {0} = {1}", num, result);


}
catch(DivideByZeroException ex)
{
Console.Write("Cannot divide by zero. Please try again.");
}
catch(InvalidOperationException ex)
{
Console.Write("Invalid operation. Please try again.");
}
catch(FormatException ex)
{
Console.Write("Not a valid format. Please try again.");
}
catch(Exception ex)
{
Console.Write("Error occurred! Please try again.");
}
}

}
Try it

In the above example, we have specified multiple catch blocks with different exception types. We
can display an appropriate message to the user, depending upon the error, so the user does not repeat
the same mistake again.

Note:
Multiple catch blocks with the same exception type are not allowed. A catch block with the base
Exception type must be the last block.
ADVERTISEMENT

Invalid catch Block

A parameterless catch block and a catch block with the Exception parameter are not allowed in the
same try-catch statements, because they both do the same thing.

Example: Invalid catch


try
{
//code that may raise an exception
}
catch //cannot have both catch and catch(Exception ex)
{
Console.WriteLine("Exception occurred");
}
catch(Exception ex) //cannot have both catch and catch(Exception ex)
{
Console.WriteLine("Exception occurred");
}

Also, parameterless catch block catch{ } or general catch block catch(Exception ex){ } must be the
last block. The compiler will give an error if you have other catch blocks after
a catch{ } or catch(Exception ex) block.

Example: Invalid catch


try
{
//code that may raise an exception
}
catch
{
// this catch block must be last block
}
catch (NullReferenceException nullEx)
{
Console.WriteLine(nullEx.Message);
}
catch (InvalidCastException inEx)
{
Console.WriteLine(inEx.Message);
}

finally Block

The finally block is an optional block and should come after a try or catch block. The finally block
will always be executed whether or not an exception occurred. The finally block generally used for
cleaning-up code e.g., disposing of unmanaged objects.

Example: finally Block


static void Main(string[] args)
{
FileInfo file = null;

try
{
Console.Write("Enter a file name to write: ");
string fileName = Console.ReadLine();
file = new FileInfo(fileName);
file.AppendText("Hello World!")
}
catch(Exception ex)
{
Console.WriteLine("Error occurred: {0}", ex.Message );
}
finally
{
// clean up file object here;
file = null;
}
}
Note:
Multiple finally blocks are not allowed. Also, the finally block cannot have the return, continue, or
break keywords. It doesn't let control to leave the finally block.

Nested try-catch

C# allows nested try-catch blocks. When using nested try-catch blocks, an exception will be caught
in the first matching catch block that follows the try block where an exception occurred.

Example: Nested try-catch


static void Main(string[] args)
{
var divider = 0;

try
{
try
{
var result = 100/divider;
}
catch
{
Console.WriteLine("Inner catch");
}
}
catch
{
Console.WriteLine("Outer catch");
}
}

Try it
Output:

Inner catch

An inner catch block will be executed in the above example because it is the first catch block that
handles all exception types.

If there isn't an inner catch block that matches with raised exception type, then the control will flow
to the outer catch block until it finds an appropriate exception filter. Consider the following example.

Example: Nested try-catch


static void Main(string[] args)
{
var divider = 0;

try
{
try
{
var result = 100/divider;
}
catch(NullReferenceException ex)
{
Console.WriteLine("Inner catch");
}
}
catch
{
Console.WriteLine("Outer catch");
}
}

Try it
Output:

Outer catch
In the above example, an exception of type DivideByZeroException will be raised.Because an
inner catch block handles only the NullReferenceTypeException, it will be handle by an
outer catch block.

C# - throw keyword

We have seen in the previous section how to handle exceptions which are automatically raised by
CLR. Here, we will see how to raise an exception manually.

An exception can be raised manually by using the throw keyword. Any type of exceptions which is
derived from Exception class can be raised using the throw keyword.

Example: throw an exception


static void Main(string[] args)
{
Student std = null;

try
{
PrintStudentName(std);
}
catch(Exception ex)
{
Console.WriteLine(ex.Message );
}

Console.ReadKey();
}

private static void PrintStudentName( Student std)


{
if (std == null)
throw new NullReferenceException("Student object is null.");

Console.WriteLine(std.StudentName);
}
Try it
Output:

Student object is null.

In the above example, PrintStudentName() method raises NullReferenceException if Student object


is null.

Please notice that throw creates an object of any valid exception type using the new keyword. The
throw keyword cannot be used with any other type which does not derive from the Exception class.

Re-throwing an Exception

You can also re-throw an exception from the catch block to pass on to the caller and let the caller
handle it the way they want. The following example re-throws an exception.

Example: throw an exception


static void Main(string[] args)
{
try
{
Method1();
}
catch(Exception ex)
{
Console.WriteLine(ex.StackTrace);
}
}

static void Method1()


{
try
{
Method2();
}
catch(Exception ex)
{
throw;
}
}

static void Method2()


{
string str = null;
try
{
Console.WriteLine(str[0]);
}
catch(Exception ex)
{
throw;
}
}
Try it

In the above example, an exception occurs in Method2(). The catch block simply throws that
exception using only throw keyword (not throw e). This will be handled in catch block in Method1()
where it again re-throw the same exception and finally it is being handled in the Main() method. The
stack trace of this exception will give you the full detail of where exactly this exception occurred.

If you re-throw an exception using exception parameter then it will not preserve the original
exception and creates a new exception. The following example demonstrates this.

Example: throw an exception


static void Main(string[] args)
{
try
{
Method1();
}
catch(Exception ex)
{
Console.WriteLine(ex.StackTrace);
}
}
static void Method1()
{
try
{
Method2();
}
catch(Exception ex)
{
throw ex;
}
}

static void Method2()


{
string str = null;
try
{
Console.WriteLine(str[0]);
}
catch(Exception ex)
{
throw;
}
}
Try it

In the above example, exception caught in the Main() method will display stack trace from Method1
and Main method. It will not display Method1 in stack trace as we re-throw exception in Method1()
using throw ex. So, never throw an exception using throw <exception parameter>.

Custom Exception Type in C#

C# includes the built-in exception types such


as NullReferenceException, MemoryOverflowException, etc. However, you often like to raise an
exception when the business rule of your application gets violated. So, for this, you can create a
custom exception class by deriving the ApplicationException class.

The .Net framework includes ApplicationException class since .Net v1.0. It was designed to use as a
base class for the custom exception class. However, Microsoft now recommends Exception class to
create a custom exception class. You should not throw an ApplicationException exception in your
code, and you should not catch an ApplicationException exception unless you intend to re-throw the
original exception.

For example, create InvalidStudentNameException class in a school application, which does not
allow any special character or numeric value in a name of any of the students.

Example: ApplicationException
class Student
{
public int StudentID { get; set; }
public string StudentName { get; set; }
}

[Serializable]
class InvalidStudentNameException : Exception
{
public InvalidStudentNameException() { }

public InvalidStudentNameException(string name)


: base(String.Format("Invalid Student Name: {0}", name))
{

}
}

Now, you can raise InvalidStudentNameException in your program whenever the name contains
special characters or numbers. Use the throw keyword to raise an exception.

Example: throw custom exception


class Program
{
static void Main(string[] args)
{
Student newStudent = null;

try
{
newStudent = new Student();
newStudent.StudentName = "James007";

ValidateStudent(newStudent);
}
catch(InvalidStudentNameException ex)
{
Console.WriteLine(ex.Message );
}

Console.ReadKey();
}

private static void ValidateStudent(Student std)


{
Regex regex = new Regex("^[a-zA-Z]+$");

if (!regex.IsMatch(std.StudentName))
throw new InvalidStudentNameException(std.StudentName);

}
}
Output:

Invalid Student Name: James000

Thus, you can create custom exception classes to differentiate from system exceptions.

C# - Stream

C# includes following standard IO (Input/Output) classes to read/write from different sources like
files, memory, network, isolated storage, etc.
Stream: System.IO.Stream is an abstract class that provides standard methods to transfer bytes (read,
write, etc.) to the source. It is like a wrapper class to transfer bytes. Classes that need to read/write
bytes from a particular source must implement the Stream class.

The following classes inherit Stream class to provide the functionality to Read/Write bytes from a
particular source:

FileStream reads or writes bytes from/to a physical file, whether it is a .txt, .exe, .jpg, or any other
file. FileStream is derived from the Stream class.

MemoryStream: MemoryStream reads or writes bytes that are stored in memory.

BufferedStream: BufferedStream reads or writes bytes from other Streams to improve certain I/O
operations' performance.

NetworkStream: NetworkStream reads or writes bytes from a network socket.

PipeStream: PipeStream reads or writes bytes from different processes.

CryptoStream: CryptoStream is for linking data streams to cryptographic transformations.

The following diagram shows the hierarchy of stream classes:

Stream Classes Hierarchy

Stream Readers and Writers

StreamReader: StreamReader is a helper class for reading characters from a Stream by converting
bytes into characters using an encoded value. It can be used to read strings (characters) from
different Streams like FileStream, MemoryStream, etc.

StreamWriter: StreamWriter is a helper class for writing a string to a Stream by converting


characters into bytes. It can be used to write strings to different Streams such as FileStream,
MemoryStream, etc.

BinaryReader: BinaryReader is a helper class for reading primitive datatype from bytes.

BinaryWriter: BinaryWriter writes primitive types in binary.


Stream IO

The above image shows that FileStream reads bytes from a physical file, and
then StreamReader reads strings by converting those bytes to strings. In the same way,
the StreamWriter takes a string and converts it into bytes and writes to the FileStream, and then
the FileStream writes the bytes to a physical file. So, the FileStream deals with bytes, where
as StreamReader and StreamWriter deals with strings.

Points to Remember :

1. Stream is an abstract class for transfering bytes from different sources. It is base class for all other
class that reads\writes bytes to different sources.
2. FileStream class provides reading and writing functionality of bytes to physical file.
3. Reader & writer classes provides functionality to read bytes from Stream classes (FileStream,
MemoryStream etc) and converts bytes into appropriate encoding.
4. StreamReader provides a helper method to read string from FileStream by converting bytes into
strings. StreamWriter provides a helper method to write string to FileStream by converting strings into
bytes.

Learn how to read/write to the File system in the next section.

Working with Files & Directories in C#

C# provides the following classes to work with the File system. They can be used to access
directories, access files, open files for reading or writing, create a new file or move existing files
from one location to another, etc.

Class Name Usage


File File is a static class that provides different functionalities like copy, create, move, delete, open
for reading or /writing, encrypt or decrypt, check if a file exists, append lines or text to a file�s
content, get last access time, etc.
FileInfo The FileInfo class provides the same functionality as a static File class. You have more control
on how you do read/write operations on a file by writing code manually for reading or writing
bytes from a file.
Directory Directory is a static class that provides functionality for creating, moving, deleting and accessing
subdirectories.
DirectoryInf DirectoryInfo provides instance methods for creating, moving, deleting and accessing
o subdirectories.
Path Path is a static class that provides functionality such as retrieving the extension of a file,
changing the extension of a file, retrieving the absolute physical path, and other path related
functionalities.

File

C# includes static File class to perform I/O operation on physical file system. The static File class
includes various utility method to interact with physical file of any type e.g. binary, text etc.
Use this static File class to perform some quick operation on physical file. It is not recommended to
use File class for multiple operations on multiple files at the same time due to performance reasons.
Use FileInfo class in that scenario.

Important Methods of Static File Class

Method Usage
AppendAllLines Appends lines to a file, and then closes the file. If the specified file does not exist, this
method creates a file, writes the specified lines to the file, and then closes the file.
AppendAllText Opens a file, appends the specified string to the file, and then closes the file. If the file does
not exist, this method creates a file, writes the specified string to the file, then closes the file.
AppendText Creates a StreamWriter that appends UTF-8 encoded text to an existing file, or to a new file
if the specified file does not exist.
Copy Copies an existing file to a new file. Overwriting a file of the same name is not allowed.
Create Creates or overwrites a file in the specified path.
CreateText Creates or opens a file for writing UTF-8 encoded text.
Decrypt Decrypts a file that was encrypted by the current account using the Encrypt method.
Delete Deletes the specified file.
Encrypt Encrypts a file so that only the account used to encrypt the file can decrypt it.
Exists Determines whether the specified file exists.
GetAccessControl Gets a FileSecurity object that encapsulates the access control list (ACL) entries for a
specified file.
Move Moves a specified file to a new location, providing the option to specify a new file name.
Open Opens a FileStream on the specified path with read/write access.
ReadAllBytes Opens a binary file, reads the contents of the file into a byte array, and then closes the file.
ReadAllLines Opens a text file, reads all lines of the file, and then closes the file.
ReadAllText Opens a text file, reads all lines of the file, and then closes the file.
Replace Replaces the contents of a specified file with the contents of another file, deleting the
original file, and creating a backup of the replaced file.
WriteAllBytes Creates a new file, writes the specified byte array to the file, and then closes the file. If the
target file already exists, it is overwritten.
WriteAllLines Creates a new file, writes a collection of strings to the file, and then closes the file.
WriteAllText Creates a new file, writes the specified string to the file, and then closes the file. If the target
file already exists, it is overwritten.

Append Text Lines

Use AppendAllLines() method to append multiple text lines to the specified file as shown below.

Example: Append all text lines to a file


string dummyLines = "This is first line." + Environment.NewLine +
"This is second line." + Environment.NewLine +
"This is third line.";

//Opens DummyFile.txt and append lines. If file is not exists then create and open.
File.AppendAllLines(@"C:\DummyFile.txt",
dummyLines.Split(Environment.NewLine.ToCharArray()).ToList<string>());

Append String

Use File.AppendAllText() method to append string to a file in single line of code as shown below.
Example: Append string to a file
//Opens DummyFile.txt and append Text. If file is not exists then create and open.
File.AppendAllText(@"C:\ DummyFile.txt", "This is File testing");

Overwrite Text

Use File.WriteAllText() method to write texts to the file. Please note that it will not append text but
overwrite existing texts.

Example: Overwrite existing texts


//Opens DummyFile.txt and write texts. If file is not exists then create and open.
File.WriteAllText(@"C:\DummyFile.txt", "This is dummy text");

The following example shows how to perform different operations using static File class.

Example: Multiple File operations


//Check whether file is exists or not at particular location
bool isFileExists = File.Exists(@"C:\ DummyFile.txt"); // returns false

//Copy DummyFile.txt as new file DummyFileNew.txt


File.Copy(@"C:\DummyFile.txt", @"D:\NewDummyFile.txt");

//Get when the file was accessed last time


DateTime lastAccessTime = File.GetLastAccessTime(@"C:\DummyFile.txt");

//get when the file was written last time


DateTime lastWriteTime = File.GetLastWriteTime(@"C:\DummyFile.txt");

// Move file to new location


File.Move(@"C:\DummyFile.txt", @"D:\DummyFile.txt");

//Open file and returns FileStream for reading bytes from the file
FileStream fs = File.Open(@"D:\DummyFile.txt", FileMode.OpenOrCreate);

//Open file and return StreamReader for reading string from the file
StreamReader sr = File.OpenText(@"D:\DummyFile.txt");

//Delete file
File.Delete(@"C:\DummyFile.txt");

Thus, it is easy to work with physical file using static File class. However, if you want more
flexibility then use FileInfo class. The same way, use static Directory class to work with physical
directories.

Points to Remember :

1. File is a static class to read\write from physical file with less coding.
2. Static File class provides functionalities such as create, read\write, copy, move, delete and others for
physical files.
3. Static Directory class provides functionalities such as create, copy, move, delete etc for physical
directories with less coding.
4. FileInfo and DirectoryInfo class provides same functionality as static File and Directory class.

C# - FileInfo
Here, you will learn how to use FileInfo class to perform read/write operation on physical files.

The FileInfo class provides the same functionality as the static File class but you have more control
on read/write operations on files by writing code manually for reading or writing bytes from a file.

Important Properties and Methods of FileInfo:

Property Usage

Directory Gets an instance of the parent directory.

DirectoryName Gets a string representing the directory's full path.

Exists Gets a value indicating whether a file exists.

Extension Gets the string representing the extension part of the file.

FullName Gets the full path of the directory or file.

IsReadOnly Gets or sets a value that determines if the current file is read only.

LastAccessTime Gets or sets the time the current file or directory was last accessed

LastWriteTime Gets or sets the time when the current file or directory was last written to

Length Gets the size, in bytes, of the current file.

Name Gets the name of the file.

Method Usage

AppendText Creates a StreamWriter that appends text to the file represented by this
instance of the FileInfo.

CopyTo Copies an existing file to a new file, disallowing the overwriting of an


existing file.

Create Creates a file.

CreateText Creates a StreamWriter that writes a new text file.

Decrypt Decrypts a file that was encrypted by the current account using the Encrypt
method.

Delete Deletes the specified file.

Encrypt Encrypts a file so that only the account used to encrypt the file can decrypt it.

GetAccessControl Gets a FileSecurity object that encapsulates the access control list (ACL)
entries for a specified file.

MoveTo Moves a specified file to a new location, providing the option to specify a
new file name.
Method Usage

Open Opens a in the specified FileMode.

OpenRead Creates a read-only FileStream.

OpenText Creates a StreamReader with UTF8 encoding that reads from an existing text
file.

OpenWrite Creates a write-only FileStream.

Replace Replaces the contents of a specified file with the file described by the current
FileInfo object, deleting the original file, and creating a backup of the
replaced file.

ToString Returns a path as string.

The following example shows how to read bytes from a file manually and then convert them to a
string using UTF8 encoding:

Example: Read file using FileInfo class


//Create object of FileInfo for specified path
FileInfo fi = new FileInfo(@"D:\DummyFile.txt");

//Open file for Read\Write


FileStream fs = fi.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);

//create byte array of same size as FileStream length


byte[] fileBytes = new byte[fs.Length];

//define counter to check how much bytes to read. Decrease the counter as you read each byte
int numBytesToRead = (int)fileBytes.Length;

//Counter to indicate number of bytes already read


int numBytesRead = 0;

//iterate till all the bytes read from FileStream


while (numBytesToRead > 0)
{
int n = fs.Read(fileBytes, numBytesRead, numBytesToRead);

if (n == 0)
break;

numBytesRead += n;
numBytesToRead -= n;
}

//Once you read all the bytes from FileStream, you can convert it into string using UTF8 encoding
string filestring = Encoding.UTF8.GetString(fileBytes);

As you have seen in the above code, you have to write lot of code for reading/writing a string from a
FileSream. The same read/write operation can be done easily using StreamReader and StreamWriter.

The following example shows how StreamReader makes it easy to read strings from a file:
Example: Read file using StreamReader
//Create object of FileInfo for specified path
FileInfo fi = new FileInfo(@"D:\DummyFile.txt");

//Open file for Read\Write


FileStream fs = fi.Open(FileMode.OpenOrCreate, FileAccess.Read , FileShare.Read);

//Create object of StreamReader by passing FileStream object on which it needs to operates on


StreamReader sr = new StreamReader(fs);

//Use ReadToEnd method to read all the content from file


string fileContent = sr.ReadToEnd();

//Close StreamReader object after operation


sr.Close();
fs.Close();

Notice that fi.Open() has three parameters: The first parameter is FileMode for creating and opening
a file if it does not exist; the second parameter, FileAccess, is to indicate a Read operation; and the
third parameter is to share the file for reading with other users while the file is open.

The following example shows how StreamWriter makes it easy to write strings to a File:

Example: Write texts to file using StreamWriter


//Create object of FileInfo for specified path
FileInfo fi = new FileInfo(@"D:\DummyFile.txt");

//Open file for Read\Write


FileStream fs = fi.Open(FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read );

//Create StreamWriter object to write string to FileSream


StreamWriter sw = new StreamWriter(fs);
sw.WriteLine("Another line from streamwriter");
sw.Close();

Read and Write operations are not possible on the same FileStream object simultaneously. If you are
already reading from a file, create a separate FileStream object to write to the same file, as shown
below:

Example: StreamReader & StreamWriter


//Create FileInfo object for DummyFile.txt
FileInfo fi = new FileInfo(@"D:\DummyFile.txt");

//open DummyFile.txt for read operation


FileStream fsToRead = fi.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite ,
FileShare.ReadWrite);

//open DummyFile.txt for write operation


FileStream fsToWrite = fi.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite,
FileShare.ReadWrite);

//get the StreamReader

StreamReader sr = new StreamReader(fsToRead);


//read all texts using StreamReader object
string fileContent = sr.ReadToEnd();
sr.Close();

//get the StreamWriter


StreamWriter sw = new StreamWriter(fsToWrite);
//write some text using StreamWriter
sw.WriteLine("Another line from streamwriter");
sw.Close();

//close all Stream objects


fsToRead.Close();
fsToWrite.Close();

Thus you can use FileInfo, StreamReader and StreamWriter class to read/write contents from
physical file.

C# - Object Initializer Syntax

C# 3.0 (.NET 3.5) introduced Object Initializer Syntax, a new way to initialize an object of a class or
collection. Object initializers allow you to assign values to the fields or properties at the time of
creating an object without invoking a constructor.

Example: Object Initializer Syntax


public class Student
{
public int StudentID { get; set; }
public string StudentName { get; set; }
public int Age { get; set; }
public string Address { get; set; }
}

class Program
{
static void Main(string[] args)
{
Student std = new Student() { StudentID = 1,
StudentName = "Bill",
Age = 20,
Address = "New York"
};
}
}
Try it

In the above example, Student class is defined without any constructors. In the Main() method, we
have created Student object and assigned values to all or some properties in the curly bracket at the
same time. This is called object initializer syntax.

The compiler compiles the above initializer into something like the following.

Example: Object Initializer Syntax at Compile time


Student __student = new Student();
__student.StudentID = 1;
__student.StudentName = "Bill";
__student.Age = 20;
__student.StandardID = 10;
__student.Address = "Test";
Student std = __student;

Collection Initializer Syntax

Collection can be initialized the same way as class objects using collection initializer syntax.

Example: Object initializer Syntax


var student1 = new Student() { StudentID = 1, StudentName = "John" };
var student2 = new Student() { StudentID = 2, StudentName = "Steve" };
var student3 = new Student() { StudentID = 3, StudentName = "Bill" } ;
var student4 = new Student() { StudentID = 3, StudentName = "Bill" };
var student5 = new Student() { StudentID = 5, StudentName = "Ron" };

IList<Student> studentList = new List<Student>() {


student1,
student2,
student3,
student4,
student5
};
Try it

You can also initialize collections and objects at the same time.

Example: Collection initializer Syntax


IList<Student> studentList = new List<Student>() {
new Student() { StudentID = 1, StudentName = "John"} ,
new Student() { StudentID = 2, StudentName = "Steve"} ,
new Student() { StudentID = 3, StudentName = "Bill"} ,
new Student() { StudentID = 3, StudentName = "Bill"} ,
new Student() { StudentID = 4, StudentName = "Ram" } ,
new Student() { StudentID = 5, StudentName = "Ron" }
};
Try it

You can also specify null as an element:

Example: Collection initializer Syntax


IList<Student> studentList = new List<Student>() {
new Student() { StudentID = 1, StudentName = "John"} ,
null
};

Advantages of Initializers

 Initializer syntax makes a code more readable, easy to add elements into the collection.
 Useful in multi-threading.

Further Reading

Beginning C# Object-Oriented Programming (Expert's Voice in .NET) 2nd ed. Edition

by Dan Clark (Author)


C# Design Pattern Essentials First Edition

by Tony Bevis (Author)

Head First C#: A Learner's Guide to Real-World Programming with C#, XAML, and .NET Third

Edition

by Jennifer Greene (Author), Andrew Stellman (Author)

You might also like