C-Sharp Tutorial

Table of Contents

  1. Introduction
  2. Variables and Data Types
  3. Operators in C#
  4. Conditional statements in C#
  5. Loop Statements in C#
  6. Arrays in C#
  7. Exception Handling in C#
  8. Text File Handling in C#
  9. Classes and Methods
  10. Working with Parameters
  11. Constructors and Destructors in C#
  12. Delegates and Events
  13. Inheritance in C#
  14. Encapsulation & Abstraction
  15. Polymorphism
  16. Generics in C#

Introduction

C# is one of the most popular programming languages of this era. Powered by Microsoft’s .NET framework, C# is used to build windows form and WPF based desktop applications, windows phone apps and ASP.NET web applications. This guide provides a brief introduction to core C# concept. This is a bird’s eye view of the most important C# concepts. This guide is for reference purposes and contains a summary of the most important C# concepts.

A Simple C# Program

Let’s write a very basic C# program.

        
            using System; 
            
            namespace SampleApplication 
            {            
                class Program    
                {                    
                    static void Main(string[] args)        
                    {            
                        Console.WriteLine("Welcome to C#");            
                        Console.ReadKey();        
                    }    
                } 
            }
        
    

In C#, everything is written inside a class which is inside a namespace. A namespace is a collection of classes with similar functionality. A class contains methods and member variables. In the above code, Program class contains a Main method. This is starting point of a C# program. Whenever a C# program executes, it starts from a static Main method.

Variables and Data Types

Variables are used to store data in C#. The type of variable depends upon the type of data stored in the variable.

Declaring a variable is simple; just write the data type of the data to be stored in the variable followed by variable name. Variable name should start with upper or lower case letter or number. Following are some of the most commonly used data types in C#.

Type Represents Range Default Value
bool Boolean value True or False False
byte 8-bit unsigned integer 0 to 255 0
char 16-bit Unicode character U +0000 to U +ffff '\0'
decimal 128-bit precise decimal values with 28-29 significant digits (-7.9 x 1028 to 7.9 x 1028) / 100 to 28 0.0M
double 64-bit double-precision floating point type (+/-)5.0 x 10-324 to (+/-)1.7 x 10308 0.0D
float 32-bit single-precision floating point type e -3.4 x 1038 to + 3.4 x 1038 0.0F
int 32-bit signed integer type -2,147,483,648 to 2,147,483,647 0
long 64-bit signed integer type -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 0L
sbyte 8-bit signed integer type -128 to 127 0
short 16-bit signed integer type -32,768 to 32,767 0
uint 32-bit unsigned integer type 0 to 4,294,967,295 0
ulong 64-bit unsigned integer type 0 to 18,446,744,073,709,551,615 0
ushort 16-bit unsigned integer type 0 to 65,535 0

Operators in C#

There are four major types of operators in C#.

  1. Logical Operators
  2. Arithmetic Operators
  3. Relational Operators
  4. Assignment Operators

1. Logical Operators

Given the Boolean variables A containing the value true and B containing the value false:

Operator What They Do Example
&& Called Logical AND operator. Returns true only if all of the operands are true (A && B) is false.
|| Called Logical OR Operator. Returns true only if at least one of the operands is true. (A || B) is true.
! Called Logical NOT Operator. Reverses the logical state of the operand. !(A && B) is true.

2. Arithmetic Operators

Given the numeric variables A containing the value 10 and B containing the value 20:

Operator What They Do Example
+ Performs addition A + B is 30
- Performs subtraction A - B is -10
* Performs multiplication A * B is 200
/ Performs division B / A is 2
% Takes modulus B % A is 0
++ Increment operand by one A++ is 11
-- Decrement operand by one. A-- is 9

3. Relational Operators

Operator What They Do Example
== Checks both operands for equality (A == B) is not true.
!= Checks both operands for inequality (A != B) is true.
> Checks if the left operand is greater than right operand (A > B) is not true.
< Checks if the left operand is less than right operand (A < B) is true.
>= Checks if the left operand is greater than or equal to right operand (A >= B) is not true.
<= Checks if the left operand is less than or equal to right operand (A <= B) is true.

4. Assignment Operators

Operator Description
= num1 = num2 + num3 assigns value of num2 + num3 into num1
+= num1 += num2 is equivalent to num1 = num1 + num2
-= num1 -= num2 is equivalent to num1 = num1 - num2
*= num1 *= num2 is equivalent to num1 = num1 * num2
/= num1 /= num2 is equivalent to num1 = num1 / num2
%= num1 %= num2 is equivalent to num1 = num1 % num2

There are also similar assignment operators that correspond with bitwise operators.

Conditional Statements in C#

Conditional statements in C# are used to control the flow of the execution of code. Based upon a particular condition, some specific piece of code is either executed or left unexecuted.

There are two types of conditional statements in C#: if/else statements and switch statements.

1. If/else Statement

The if/else statement is very simple. A certain condition is defined using the if keyword. If the statement evaluates to true, the code block followed by the if statement is executed otherwise, the code block is left unexecuted. For instance take a look at the following example.

        
        if (10 > 20)   
        {     
            Console.WriteLine("Number 10 is greater than 20");   
        }
        
    

If you try to run the above code, you will not see anything on the console, since the condition 10 > 20 evaluates to false. You can use else statement to execute the code, in case if the if statement evaluates to false. Check the following example.

        
        if (10 > 20)   
        {      
            Console.WriteLine("Number 10 is greater than 20");   
        }   
        else 
        {      
            Console.WriteLine("Number 10 is not greater than 20");   
        }
        
    

In the above case, since the if condition evaluates to false, the code block followed by else statement will execute. The output will be as follows:

Number 10 is not greater than 20

You can chain multiple “if/else” and “if/else if” statements to check as many conditions as you want. Have a look at the following example.

        
        if (10 > 10)    
        {        
            Console.WriteLine("Number 10 is greater than 10");    
        }    
        else if (10 < 10)    
        {        
            Console.WriteLine("Number 10 is less than 10");    
        }    
        else    
        {        
            Console.WriteLine("Number 10 is equal to 10");    
        }
        
    

The output of above code is:

Number 10 is equal to 10

2. Switch Statement

If there are too many conditions to evaluate, it is better to use switch statements instead of “if/ else” statements. Take a look at a simple example of switch statements.

        
        string color = "blue";

        switch (color)    
        {        
            case "red":        
                Console.WriteLine("China’s Flag has red color");        
                break;

            case "blue":        
                Console.WriteLine("USA’s flag has blue color in it");        
                break;  

            case "Green":       
                Console.WriteLine("Italy’s flag has green color");        
                break;       
            
            default:   
                Console.WriteLine("Sorry we can’t fetch country flag with this color");        
                break;    
        }            
        
    

Switch statement starts with switch keyword followed by opening and closing parentheses. The value to compare is passed inside these parentheses. The value is compared with each case condition. When the value passed matches with the value in the case statement, the statement(s) followed by that case statement executes. The remaining case statements are not checked. If none of the case statements match, the code followed by the default statement executes. The out of the above code is:

USA’s flag has blue color in it

Loop Statements in C#

Loop statements in C# are used to execute piece of code repeatedly for a specific number of times or until a condition is met. Loop statements are also known as iteration statements. There are three types of loop constructs in C#.

  1. For loop
  2. While loop
  3. Do While loop

1. For Loop

For loop executes a piece of code repeatedly for specific number of times. Take a look at the following example.

        
        for (int i = 1; i <= 10; i++)    
        {        
            Console.WriteLine(7 + " x " + i + " = " + 7 * i);    
        }
        
    

The above code prints the table of 7 on the console screen.

7 x 1 = 7
7 x 2 = 14
7 x 3 = 21
7 x 4 = 28
7 x 5 = 35
7 x 6 = 42
7 x 7 = 49
7 x 8 = 56
7 x 9 = 63
7 x 10 = 70

For loop consist of three parts: Initialization statement, test expression and increment statement. In the above code i=1 is initialization statement, i <= 10 is test expression and i++ is increment statement. Before the code in the loop executes, the test expression is evaluated, if it is true the code block of the loop is executed. After that the increment condition executes. Then again test expression is evaluated on the updated variable. This code keeps executing repeatedly until the test expression becomes false.

2. While Loop

The “while loop” is used to execute a piece of code repeatedly until some condition is satisfied.

        
        int i =1;            
        
        while (i <= 10)            
        {                
            Console.WriteLine(7 + " x " + i + " = " + 7 * i);                 
            
            i++;            
        }            
        
    

In “while loop”, the initialization statement is specified before the body of the loop. The test expression is specified inside the opening and closing body while the increment statement is contained by the body of the loop. The above piece of code also prints the table of 7 on console.

3. Do While Loop

Do while loop is similar to while loop with the exception that the test expression in do while loop is specified after the closing of loop body. This makes do while loop execute at least once. Take a look at the following example:

        
        int i =1;    
        
        do    
        {        
            Console.WriteLine(7 + " x " + i + " = " + 7 * i);        
            
            i++;    
        } while (i <= 10);
        
    

There is another type of loop called “for each” loop that iterates through collection of items. You will see “foreach” loop in action in next section.

Arrays in C#

Arrays are used to store collection of items of same data type. If you have a collection of integers, it is not wise to declare 100, or 200 variables to store such data. Rather you can declare an array of the size of collection and store your items in that array. Arrays store data at contiguous memory locations, thereby providing fast data access.

Declaring an Array

Declaring and defining an array is simple. Start with the type of array, followed by opening and closing square brackets and the name of the array. On the right side of the equals sign, use new keyword, followed by the type of array and opening and closing square brackets that contain size of an array. For instance, in the following code, we created a string type array “days” of size seven.

    
        string [] days = new string [7];
    

Array has zero based index which means first element gets stored at index zero and last element get stored at k-1 index where k is the size of the array

Storing and Retrieving Array Items

It is very easy to store and retrieve items from array. To store items write the name of the array followed by index number in square brackets and equate it to the item that you want to store in that index. Similarly, to retrieve or get an item from array, write the name of array and index number. Take a look at the following example.

    
        string [] days = new string [7];
        days[0] = "Monday"; // Storing first item
        days[1] = "Tuesday";
        days[2] = "Wednesday";
        days[3] = "Thursday";
        days[4] = "Friday";
        days[5] = "Saturday";
        days[6] = "Sunday";
        Console.WriteLine(days[4]); // Retrieving fifth item
    

Using For Loop to Iterate an Array

You can easily iterate through an array using for loop and for each loop. Take a look at the following example.

    
        string [] days = new string [7];
        days[0] = "Monday";
        days[1] = "Tuesday";
        days[2] = "Wednesday";
        days[3] = "Thursday";
        days[4] = "Friday";
        days[5] = "Saturday";
        days[6] = "Sunday";

        for (int i = 0; i < 7; i++) // Iterating via for loop
        {
            Console.WriteLine(days[i]);
        }

        foreach (String day in days) // Iterating via foreach loop
        {
            Console.WriteLine(day);
        }
    

Exception Handling in C#

Exceptions are breaks that occur during the program execution, most commonly because if errors that are not handled at compiled time. There are two types of errors: compile-time errors and run-time errors, run-time errors will generate exceptions if not handled. Compile-time errors are caught at compile time. For instance if you miss a semicolon, the compiler tells you at compile time that there is an error in the program and it can’t be compiled. On the other hand, run-time errors are not caught at compile time. For instance, if you divide a number by zero, your compile will compile the code. However, when you run the code, the program will through exception unless you write special code to handle that case.

There is a mechanism to catch these runtime errors. To do so try and catch blocks are used. Wrap the piece of code that is likely to throw an exception inside a try block and follow that by a a catch block containing the code you want to execute when exception occurs or use another code block known as finally. This code block executes whether or not the exception occurs, you can have try-catch, try-finally or try-catch-finally blocks.

One common use of the try-catch-finally statement is to manage resource allocation, such as closing any open connections and destroing objects even if a run-time error occurred after opening connections or allocating objects.

Take a look at the simple example of exception handling in C#.

        
        int a = 10;
        int b = 0;

        try
        {
            int result = a / b;
        }
        catch (Exception e)
        {
            Console.WriteLine("Exception " + e.Message);
        }
        finally
        {
            Console.WriteLine("Caution: Division by zero is not allowed");
        }
        
    

In the above code we are dividing a number by 0 inside the try block. In the output the messages inside the catch block and finally block will be printed. Even if the try block doesn’t throw an exception, the message inside the finally block will still be printed. The output looks like this:

Exception Attempted to divide by zero. Caution: Division by zero is not allowed.

Text File Handling in C#

File handling refers to the processes of creating, reading and writing data from and to a text file.

Reading Data From a Text File.

To read data from a text file, we use StreamReader class. The path of the file to read is passed in the constructor of the class. Next, inside the while loop, the ReadLine method of the StreamReader is repeatedly called. This method returns the read text as long as there is a line of text that is not yet read. Once the entire file has been read, this method returns null and the loop execution discontinues. Take a look at the following example.

            
                try
                {

                    using (StreamReader reader = new StreamReader("d:/countries.txt"))
                    {
                        string linestoread;

                        while ((linestoread = reader.ReadLine()) != null)
                        {
                            Console.WriteLine(linestoread);
                        }
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine("There is an error readin the file.");
                    Console.WriteLine(e.Message);
                }

                Console.ReadKey();
            
        

It is always a good practice to wrap file reading and writing code inside try and catch block since file is an external resource and interacting with it may throw errors.

Writing Data to a text File

To write data to a text file, StreamWriter class is used. The StreamWriter’s WriteLine method is used to write a new line of data into the file. Take a look at the following example.

        
            string[] colors = new string[] { "Red", "Green", "Blue", "Yellow", "Orange" };

            using (StreamWriter writer = new StreamWriter("colors.txt"))
            {
                foreach (string color in colors)
                {
                    writer.WriteLine(color);
                }
            }

            string linetoread = "";

            using (StreamReader reader = new StreamReader("colors.txt"))
            {
                while ((linetoread = reader.ReadLine()) != null)
                {
                    Console.WriteLine(linetoread);
                }
            }

            Console.ReadKey();
        
    

In the above code a file named “colors.txt” is being created and the items in the “colors” array are being written into this file via WriteLine method of the StreamWriter class. Next, to see whether the file has actually been created and data has been written to it, we read the file using the StreamReader class

Classes and Methods

C# is oriented pure object-oriented programming language, that is all code is implemented in terms of classes and objects. In programming, anything that has some properties and can perform some functions can be considered as an object. A class is simply a blue print for an object; it has no physical existence on system’s memory. An object, on the other hand is physical implementation of a class.

Namespaces

In C#, a namespace is like a container of classes. Every class must belong to a namespace. This allows to have multiple classes using the same name as long as they belong to different namespaces.

Creating a Class

It is very simple to create a class in C#. Start with an access modifier which can be either public or internal for classes, an internal class can only be accessed within classes in the same namespace while public classes can be accessed anywhere. The access modifier is then followed by keyword class and the class name. The body of a class starts and ends with opening and closing curly braces respectively. Let’s create a class Phone, by default a class is internal.

        
        namespace Examples
        {
            class Phone
            {
                public string Memory = "4mb";
                public string Camera = "13mp";
                public int Price = 20000;

                public void StartPhone ()
                {
                    Console.WriteLine("Phone has started");
                }

                public void PickCall()
                {
                    Console.WriteLine("Call has been picked");
                }

                public void TerminateCall()
                {
                    Console.WriteLine("Call has been terminated");
                }
            }
        }
        
    

The above class has three member variables: memory, camera and price. The class also contains three methods: StartPhone, PickCall and TerminateCall. This is close to real world. A cell phone has a camera, memory and some price. Also, cell phone has functionalities like starting the phone, picking a call and terminating a call. Here we have encapsulated those real world properties and methods in a class.

Methods

A method is used to implement functionality and is also known as a function. It is very easy to create methods in C#. Start with an access modifier: public, private or protected, followed by return type, the name of the method then opening and closing parentheses and optionally parameters in between them. For instance in the phone class we have a public method StartPhone which returns nothing (void). Parameters are defined in a comma-separated list of parameter types followed by names. Like class, method body is also enclosed in opening and closing curly braces.

Method Overloading

Method overloading refers to defining multiple methods with same name but different set of parameters and optionally different return type. The method that will be executed depends upon the call to the method. The method whose type, order and number of parameters match with the parameters in the call is executed. Take a look at the following example.

            
                class Messages
                {
                    public void DisplayMessage(int a, int b, int c)
                    {
                        Console.WriteLine("This is overloaded method with three parameters.");
                    }
                    public void DisplayMessage(int a, int b)
                    {
                        Console.WriteLine("This is overloaded method with two parameters.");
                    }
                    public void DisplayMessage(int a)
                    {
                        Console.WriteLine("This is overloaded method with one parameter.");
                    }
                }
            
        

In the above code, we created a class Messages. It contains three overloaded methods DisplayMessages with three different sets of parameters.

The method called will depend upon the number and order of parameters in the call. Take a look at the following code:

        
            Messages m = new Messages();
            m.DisplayMessage(10, 20, 30);
            m.DisplayMessage(10, 20);
            m.DisplayMessage(10);            
        
    

The output of the above code will be:

This is overloaded method with three parameters.
This is overloaded method with two parameters.
This is overloaded method with one parameter.

Creating an Object

        
            Phone p = new Phone();
            Console.WriteLine("The price of phone is " + p.Price);
            p.PickCall();
        
    

It is easy to create an object of a class. Simply define a variable of the class type by typing the class name then the variable name, then the new keyword followed by the class name and open and closed parentheses. In the above example we created an object of Phone class and stored it in Phone type varable p.

To access class members and methods of a variable, type the variable name followed by a dot . and the name of the member or method. For instance, to call PickCall method via p object of class Phone, type p.PickCall(). Calling methods requires open and closed parentheses even if it doesn’t have parameters.

Working with Parameters

As mentioned earlier, you can also have parameterized methods or methods with parameters. The parameters are defined inside the opening and closing parentheses, each separated by a comma.

Creating a Parameterized Method

Let’s modify our phone class and create a parameterized method SetTime, the method will take three parameters minutes, second and meridiem. Take a look at the following code:

        
        class Phone
        {
            public int Hour = 00;
            public int Minute= 00;
            public string Meridiem = "am";

            public void SetTime (int h, int m, string mr)
            {
                Hour = h;
                Minute = m;
                Meridiem = mr;
            }

            public void ShowTime()
            {
                Console.WriteLine("Current Time is " + Hour + ":" + Minute + ":" + Meridiem);
            }
        }
        
    

In the above Phone class, there are three datamember Hour, Minute and Meridiem and two methods ShowTime and SetTime. The ShowTime function displays values of hour, minute and meridiem variables. The SetTime function accepts three parameters h, m and mr. The value passed to these parameters are stored in Hour, Minute and Meridiem datamembersof the class.

Now, whenever, you call the SetTime method, you will have to pass values for these parameters in the same order. Otherwise, the compiler will generate an error. Take a look at the following code to see how parameterized methods are called.

        
            Phone p = new Phone();
            p.ShowTime();
            p.SetTime(4, 50, "pm");
            p.ShowTime();
        
    

In the above example we first call the ShowTime method that will display the default values of hour, minute and meridiem member variables. Next, we called SetTime method and pass values for the parameters. This will update values for Hour, Minute and Meridiem datamembers. Finally we again display the updated time via ShowTime method. The output will look like this:

Current Time is 0:0:am
Current Time is 4:50:pm

Constructors and Destructors in C#

Constructors

A constructor is a special method that is called whenever you create object of a class. A constructor has no return type and its name is the same as the name of the class. Constructors are usually used to initialize datamembers at the time of creating an object.

Destructors

Destructors are also special methods with the name similar to the name of the class in which they exist. However, destructor name starts with a ~ tilde sign. Destructors are called when the object of a class is destroyed or removed from the memory. Usually .NET framework performs automatic garbage collection, however destructors can be used to free any resources occupied by the object. A class can have one constructor at most

Take a look at the following example of a constructor and a destructor

        
            class Phone
            {
                public int Price = 0;
                public string Color = "Black";

                public Phone(int p, string c) // Constructor
                {
                    Price = p;
                    Color = c;
                    Console.WriteLine("Constructor Executed");
                }
                ~Phone()
                {
                    Console.WriteLine("Destructor Executed");
                }
            }
        
    

In the above code, the phone class has a constructor that takes two parameters and initializes Price and Color datamembers of the class. The above class also contains a destructor which simply prints message on console screen. The following code creates object of Phone class.

        
            Phone p = new Phone(1000, "blue");
        
    

The output of the above code will be:

Constructor Executed
Destructor Executed

Delegates and Events

Delegates

Delegates store references to methods. Delegates are reference type variables and are typically used to implement events and callback functions.

Working with delegaes is simple. The first step is to declare a delegate. The next step is to instantiate the delegate using new keyword and pass the function to refer as parameter to the delegate constructor. Finally call the function using delegate variable. Let us see a simple example of delegates.

        
            delegate int SquareNum(int num);

            class Math
            {
                public int TakeSquare(int number)
                {
                    return number * number;
                }
            }
        
    

In the above code a delegate named SquareNum has been defined. To define a delegate, simply type keyword delegate followed by return type, name of the delegate and parameters. This delegate can refer to any function that has same signature i.e. return type and number, types and order of parameters. We create Math class that contains a function TakeSquare. It has return type of integer and can accept one integer type parameter. This function matches the SquareNum delegate’s signature.

Now, let’s have a look at how we can instantiate a variable of the delegate type and call the method through it:

        
            Math m = new Math();
            SquareNum sn = new SquareNum(m.TakeSquare);
            Console.WriteLine("The square root of 4 is: " + sn(4));
            Console.ReadKey();
        
    

It can be seen that the method TakeSquare is being passed as parameter to the delegate constructor. Now when the delegate function is called, the TakeSquare function executes and squares the number passed to it as parameter. The output of above code shall look like this:

The square root of 4 is: 16

Events

Events are actions performed by the user such as a key press, a mouse click or double click. Events can also be raised when a network error occurs, or a file download is completed. In C#, events raised in one class can be handled by event handlers in the same class or some other class. The class that raises an event is called publisher class while the class that handles that event is called subscriber. A class can be publisher and subscriber simultaneously. An event is bound to its handler via delegate. Take a look at the following simple example.

        
            delegate void ShowMessage(String str);

            class EventGenerator
            {
                event ShowMessage Showmessageevent;

                public void GenerateEvent()
                {
                    EventSubscriber es = new EventSubscriber();
                    ShowMessage sm = new ShowMessage(es.PrintWelcome);
                    Showmessageevent += sm;
                    Showmessageevent("Jones");
                }
            }

            class EventSubscriber
            {
                public void PrintWelcome(string user)
                {
                    Console.WriteLine("Welcome to C# " + user);
                }
            }
        
    

In the above code we define a delegate, a class that fires an event and a class that handles the event. The event is bound to its handler via the delegate. The syntax to bind event to its handler is by using += symbols. Let’s fire the event in main function and see the output.

        
            EventGenerator eg = new EventGenerator();
            eg.GenerateEvent();
            Console.ReadKey();
        
    

The output of the above code will look like this:

Welcome to C# Jones

Inheritance in C#

Inheritance in C# is quite similar to inheritance in real world. Just like a child inherits property of its parents, in C# a class that inherits another class inherits its properties. A class that is inherited by another class is called base class or parent class while class that inherits another class is called child or derived class. In C#, a class can only inherit from one class where as one class can be inherited by multiple classes. Let’s have a look at a simple example of inheritance.

        
        class Phone
        {
            public int Price;
            public string Color;

            public void PickCall()
            {
                Console.WriteLine("Call has been picked");
            }
        }

        class Mobile : Phone
        {

            public void GetInfo()
            {
                Console.WriteLine("This is mobile phone. Samsung Brand");
            }
        }

        class Program
        {
            static void Main(string[] args)
            {
                Mobile m = new Mobile();
                m.Price = 10000;
                m.Color = "Black";
                m.PickCall();
                m.GetInfo();
                Console.ReadKey();
            }
        }
        
    

In the above code, there are three classes Phone, Mobile and Program. Phone class has two member variables and a function. Mobile class inherits phone, class. To inherit from a class, simply type colon followed by the name of the class to inherit. Now, since Mobile class inherits the Phone class, it will also inherit the datamembers and methods of Phone class. To see if Mobile class has actually inherited the datamembers and methods of Phone class we tried to access the datamembers and methods of Phone class using Mobile class object. The output of the above code shall look like this.

Call has been picked.
This is mobile phone. Samsung Brand

Encapsulation & Abstraction

Polymorphism, inheritance and encapsulation are considered the three pillars of any object oriented programming language. In this section we shall see Encapsulation and a related concept: Abstraction.

Encapsulation

Encapsulation refers to hiding the internal details of a class by making datamembers private or protected. These datamembers can then be accessed via getters and setters. Encapsulation can be best explained with the help of a simple example.

        
            class Phone
            {
                int _price = 100;
                string _color = "Black";

                public int Price
                {
                    get
                    {
                        return this._price;
                    }

                    set
                    {
                        if (value < 100)
                            this._price = 100;
                        else
                            this._price = value;
                    }
                }


                public string Color
                {
                    get
                    {
                        return this._color;
                    }

                    set
                    {
                        if (value != "Black" && value != "White" && value != "Blue" )
                            this._color = "Black";
                        else
                            this._color = value;
                    }
                }
            }
        
    

In the above code Phone class has two datamembers: _price and _color. Corresponding to these members we create two properties Price and Color respectively. Properties have getters and setters to get values from member variables and store values inside a datamember. The get and set methods are used for this purpose.

Notice that inside the setter for price, we have specified a condition that if the price is less than 100, set the price value to 100, otherwise set the price value to the actual value being passed. Similarly for Color property, we have specified that if the value being set is “Black” or “White” or “Blue” set that value otherwise set color as “Black”.

This is encapsulation, the internal functioning of the datamembers is not known to the user. The user can only set and get the value for price and color variables. The user cannot directly access color and price variable. Rather he has to make use of Color and Price properties. And these properties are adding an extra layer of protection to the actual data which is hidden from user. The following code sets and gets values for Price and Color properties.

        
            Phone p = new Phone();
            p.Price = 10;
            p.Color = "White";
            Console.WriteLine(p.Color + " " + p.Price);
            Console.ReadKey();
        
    

Abstraction

Abstraction refers to an abstract entity which has no physical existence. It is only an idea or thought which does not exist physically. In C#, abstraction is implemented via abstract classes and interfaces. An abstract class is a class that doesn’t and cannot have any physical existence in the form of object. Abstract class is used to provide a blue print for classes that derive it. An abstract can contain abstract as well as non-abstract (concrete) methods. Abstract methods do not have any implementation. A class that implemented or inherits an abstract class provides the implementation for the abstract methods of base abstract class or chooses to stay abstract and let classes inherited from it provide the implementation.

Consider example of a vehicle, a vehicle starts and stops. It has a price, color, weight. However vehicle itself is nothing. A car can be a vehicle; a motor bike can be a vehicle. But vehicle itself is nothing. Vehicle exists in the form of car, truck, or cycle etc. Therefore, vehicle is an abstract entity while car, truck and motor bikes are concrete entities. An abstract class starts with access modifier, followed by keywords abstract class and the name of the class. The abstract methods also contain keyword abstract.

        
            abstract class Vehicle
            {
                public int Price;
                public string Color;
                public abstract void GetInfo();
            }

            class Car : Vehicle
            {
                public override void GetInfo()
                {
                    Console.WriteLine("This is a car");
                }

            }

            class Bike : Vehicle
            {
                public override void GetInfo()
                {
                    Console.WriteLine("This is a Motor Bike");
                }
            }
        
    

In the above code we create an abstract class Vehicle. This class contains an abstract method GetInfo. The Vehicle class is inherited by two derived classes Car and Bike. These classes have to provide the implementation for the GetInfo method or be declared as a abstract class, otherwise the compiler will generate an error. To provide implementation of base class’s abstract methods, keyword override is used.

Therefore, Car and Bike class override the GetInfo method and provide their own implementation.

Now, if you try to create object of the Vehicle class, you will not be able to do so. This is because an abstract class cannot be instantiated. You can only create objects of child classes. The following code creates objects of Car and Bike class and then calls GetInfo method on both of them.

        
            Car c = new Car();
            Bike b = new Bike();
            c.GetInfo();
            b.GetInfo();
        
    
This is a car
This is a Motor Bike

Polymorphism

Polymorphism refers to multiple forms. In terms of programming, it is defined as single interface providing multiple functionalities. In C# and other object-oriented languages polymorphism is implemented via method overriding.

Method Overriding

Method overriding refers to re-implementing parent class method in child class by providing different definition in child class. In the Abstraction section we saw how Car and Bike classes provided implementations for parent class’s GetInfo method.

However, it is not necessary for a parent class and its method to be abstract in order to be overridden. You can also create virtual method in the parent class. This method has its own implementation and it can be also be overridden by child classes. In child class we can have same method with different implementation. Let’s modify our abstraction example by making Vehicle class concrete.

        
            class Vehicle
            {
                public virtual void GetInfo()
                {
                    Console.WriteLine("This is a vehicle");
                }
            }

            class Car : Vehicle
            {
                public override void GetInfo()
                {
                    Console.WriteLine("This is a car");
                }
            }

            class Bike : Vehicle
            {
                public override void GetInfo()
                {
                    Console.WriteLine("This is a Motor Bike");
                }
            }
        
    

In the above code, Vehicle, Car and Bike classes have their own implementation of GetInfo method. The GetInfo method in parent class is virtual which means that this method can be overridden by the child classes. Also We can store the object of child class in parent class variables. Therefore, we shall create three Vehicle type variables and will store objects of Vehicle, Car and Bike classes in these variables. We will then call the GetInfo method on each of these objects. You will see that though we will call GetInfo method from same Vehicle type variables, the output will be different depending upon the object stored in the variable. This is dynamic polymorphism. Take a look at the following code:

        
            Vehicle v1 = new Vehicle();
            Vehicle v2 = new Car();
            Vehicle v3 = new Bike();
            v1.GetInfo();
            v2.GetInfo();
            v3.GetInfo();
        
    

In the output, you will see that the GetInfo method of objects stored in Vehicle variables will be called.

This is a vehicle
This is a car
This is a Motor Bike

Generics in C#

Generics allow you to create classes and variables without specifying their types. The type can be specified at runtime. Generic types contain type parameter which is specified by a type parameter. Take a look at a simple example to see generics in action.

        
            class GenericTest<T>
            {
                T GenericValue;

                public GenericTest(T value)
                {
                    this.GenericValue = value;
                }
                public void DisplayVal()
                {
                    Console.WriteLine(this.GenericValue);
                }
            }
        
    

In the above code we create a generic class GenericTest with a type parameter T. The constructor of the class accepts value of type T and assigns this value to GenericValue datamember.

Now, we will create two objects of this class, one using integer type and the other using string type. We shall also pass integer and string type values for the constructor of the class.

        
            GenericTest<int> gen = new GenericTest<int>(10);
            gen.DisplayVal();
            GenericTest<String> gen2 = new GenericTest<String>("Welcome to C#");
            gen2.DisplayVal();
        
    

The DisplayVal method will display the value of GenericValue variable on the console. The output will look like this:

10
Welcome to C#