Pages

Tuesday, 2 February 2021

Top C# -OOPs Concepts

 

1.  Internal Vs Private 

internal is for assembly scope (i.e. only accessible from code in the same .exe or .dll)

private is for class scope (i.e. accessible only from code in the same class). 


enter image description here


Private: - Private members are only accessible within the own type (Own class).

Internal: - Internal member are accessible only within the assembly by inheritance (its derived type) or by instance of class.


2.

Value Parameters /. Reference Parameters / Output Parameters

Value parameters : This method copies the actual value of an argument into the formal parameter of the function. In this case, changes made to the parameter inside the function have no effect on the argument.


Reference parameters : This method copies the reference to the memory location of an argument into the formal parameter. This means that changes made to the parameter affect the argument.


Output parameters : This method helps in returning more than one value.

An argument passed as ref must be initialized before passing to the method whereas out parameter needs not to be initialised before passing to a method.

The in, ref, and out Modifiers

class ReferenceTypeExample
{
static void IncrementExample(ref int num)
{
num = num + 1;
}
static void Main()
{
int num = 1;
IncrementExample(ref num);
// num is now 2
}
}
A return statement can be used for returning only one value from a function. However, using output parameters, you can return two values from a function. Output parameters are similar to reference parameters, except that they transfer data out of the method rather than into it.


using System;
namespace CalculatorApplication {
class NumberManipulator {
public void getValue(out int x ) {
int temp = 5;
x = temp;
}
static void Main(string[] args) {
NumberManipulator n = new NumberManipulator();
/* local variable definition */
int a = 100;
Console.WriteLine("Before method call, value of a : {0}", a);
/* calling a function to get the value */
n.getValue(out a);
Console.WriteLine("After method call, value of a : {0}", a);
Console.ReadLine();
}
}
}
Output :
Before method call, value of a : 100
After method call, value of a : 5

Method parameters have modifiers available to change the desired outcome of how the parameter is treated. Each method has a specific use case:

  • ref is used to state that the parameter passed may be modified by the method.

  • in is used to state that the parameter passed cannot be modified by the method.

  • out is used to state that the parameter passed must be modified by the method.

Both the ref and in require the parameter to have been initialized before being passed to a method. The out modifier does not require this and is typically not initialized prior to being used in a method.   

3. 

Finally and Finalize

Finally Block is called after the execution of try and catch blocks.

Finalize method is called just before garbage collection. [ Clean Up Operation for Unmanaged Code] 

Dispose() is called when we want for an object to release any unmanaged resources with them. On the other hand, Finalize() is used for the same purpose, but it doesn't assure the garbage collection of an object.


4. Managed Code / UnManaged Code

Managed Code :  Executed by CLR - Common Language Runtime.

All the application code is dependent on .NET Platform.


UnManaged Code : 

It is executed by runtime application of some other structure.

The Runtime application deals with memory, security and other execution activities.



5. OBJECT : An Object is an instance of a class , Created by New Keyword in C#.

Methods of Objects Class : Clone(), Equals(),finalize() , getClass(), hasCode()


HasCode()

(A hash table is a data structure that associates a value with a key. It enables looking up the value for a given key, and does so with an average time complexity of O(1); in other words, the time to find an entry by key doesn’t depend on the number of entries in the hash table. The general principle is to place entries in a fixed number of “buckets”, according to the hash code of the key.) 

A hash code is not an id, and it doesn’t return a unique value. This is kind of obvious, when you think about it: GetHashCode returns an Int32, which has “only” about 4.2 billion possible values, and there’s potentially an infinity of different objects, so some of them are bound to have the same hash code.

And no, it can’t be used to test if two objects are equal. Two objects that have the same hash code are not necessarily equal, for the reason mentioned above. It works the other way, though: two objects that are equal have the same hash code (or at least they should, if Equals and GetHashCode are correctly implemented).

This method is used to return the hash code for this instance. A hash code is a numeric value which is used to insert and identify an object in a hash-based collection. The GetHashCode method provides this hash code for algorithms that need quick checks of object equality.

/ declaring an object
        Object obj = new Object();
  
        // taking Type type and assigning
        // the value as type of above
        // defined types using GetType
        // method
        Type t = obj.GetType();
  
        // Display type and hash code
        Console.WriteLine("Type is :{0}", t);
        Console.WriteLine("Hash Code is :{0}",
                             t.GetHashCode());

Output:
Type is :System.Object
Hash Code is :37162120
  • Two objects that return different hash codes means objects are not equal but the reverse is not true. Means, equal hash codes do not imply object equality, because different (unequal) objects can have identical hash codes.
  • The .NET Framework does not guarantee the default implementation of the GetHashCode method, and the value this method returns may differ between .NET Framework versions and platforms, such as 32-bit and 64-bit platforms.
  • A hash code is not a permanent value so do not serialize, store the hash values in databases etc. 
  • Do not test for equality of hash codes to determine whether two objects are equal.

6. CLASS : BluePrint of Object , Defines different platforms for Object.  = Immutable Class ( Objects that cannot be changed after initialization) 

Immutable Class means a class which once created, its state cannot be changed later by any means internally or externally.

Based on the virtue of being unchangeable in the future, we can use immutable classes in the following situations,

  1. To replace struct (Value type) with class (reference type)
  2. General purpose classes
  3. Class with Constant fields
  4. Class with Configuration related information
  5. Class with Master data
  6. Class with Cached data in singleton classes.

Mutable and immutable are English words that mean "can change" and "cannot change" respectively. The meaning of these words is the same in C# programming language; that means the mutable types are those whose data members can be changed after the instance is created but Immutable types are those whose data members can not be changed after the instance is created.

When we change the value of mutable objects, value is changed in same memory. But in immutable type, the new memory is created and the modified value is stored in new memory.

  • System.String is immutable. When we modify the value of a string variable, then a new memory is allocated to the new value and the previous memory allocation released. System.StringBuilder was designed to have a concept of a mutable string where a variety of operations can be performed without allocation separate memory location for the modified string.

String

Strings are immutable, which means we are creating new memory everytime instead of working on existing memory.

So, whenever we are modifying a value of the existing string, i.e., we are creating a new object which refers to that modified string and the old one becomes unreferenced. Hence, if we are modifying the existing string continuously, then numbers of the unreferenced object will be increased and it will wait for the garbage collector to free the unreferenced object and our application performance will be decreased.

Example 

  1.             string str = string.Empty;  
  2.   
  3.             for (int i = 0; i < 1000; i++)  
  4.             {  
  5.                 str += "Modified ";  
  6.             }   

In the code given above, string str will update 1000 times inside the loop and every time it will create new instance so all old values will be collected by garbage collector after some time.

It is not a good approach for this solution so, it’s better to go for mutable type. So in C#, we have StringBuilder which is a mutable type. We have some advantages of immutable classes like immutable objects are simpler to construct, test, and use. immutable objects are always thread-safe and etc.

StringBuilder 

StringBuilder is a mutable type, that means we are using the same memory location and keep on appending/modifying the stuff to one instance. It will not create any further instances hence it will not decrease the performance of the application.

Example 

  1.             StringBuilder strB = new StringBuilder();  
  2.   
  3.             for (int i = 0; i < 10000; i++)  
  4.             {  
  5.                 strB.Append("Modified ");  
  6.             }   

In the code given above, It has the huge impact of allocated memory because it will not create instance each time.

We have many methods for modifying the StringBuilder String as below,

  • Append - Appends information to the end of the current StringBuilder.
  • AppendFormat - Replaces a format specifier passed in a string with formatted text.
  • Insert - Inserts a string or object into the specified index of the current StringBuilder.
  • Remove - Removes a specified number of characters from the current StringBuilder.
  • Replace - Replaces a specified character at a specified index.

Creating an Immutable Class

For creating an immutable class, we have to think about their properties or variables which will never change the value(s) after assigning the first time. So, we are going to follow some simple steps for creating the immutable class in C#.

Step 1

Make the variables read-only so we can not modify the variable after assigning the first time. 

  1. class MyClass  
  2.     {  
  3.         private readonly string myStr;          
  4. }   

Step 2

Use parameterized constructor for assigning the myStr value for the class while creating the object of the class as below 

  1. class MyClass  
  2.     {  
  3.         private readonly string myStr;  
  4.   
  5.         public MyClass(string str)  
  6.         {  
  7.             myStr = str;  
  8.         }  
  9.     }   

Step 3

Use properties for getting the variables of the class and remove the setters of the property, use only getters as below. 

  1. class MyClass  
  2.     {  
  3.         private readonly string myStr;  
  4.   
  5.         public MyClass(string str)  
  6.         {  
  7.             myStr = str;  
  8.         }  
  9.   
  10.         public string GetStr  
  11.         {  
  12.             get { return myStr; }  
  13.         }  
  14.     }   

In this easy way, we can create the immutable class in C#.

It is purely based on our project requirement which says it is better to use Mutable or Immutable class.


7. Abstract Class : Objects Can't be Instantiated , Follows a Single Approach . 

You can declare a class as abstract class, if it is incomplete class or you don’t know the complete functionality of class. The abstract modifier can be used with classes, methods, properties, indexers, and events. You cannot provide implementation if class member is abstract. Also you cannot create the object of abstract class.

Key things about the abstract class:

  • You cannot create the object of abstract class (cannot be instantiated).
    Sealed modifier cannot be used with abstract class because sealed prevents the class from being inherited.
  • A non-abstract class which is derived from an abstract class must provide implementations of all inherited abstract methods.
  • You can create abstract property in base class and override it in derived class. Base class must be abstract class.
Key things about the abstract methods:
   
  • An abstract method is by default a virtual method.
  • Abstract methods cannot be declared as static, or virtual.
  • Abstract method must be written in abstract classes.
  • Abstract methods has no implementation (no method body)

Virtual methods:

The main objective of virtual method is that, you can redefine it in one or more derived classes. You can use virtual keyword with method, property, indexer, or event. It allows these members to be overridden in a derived class. The implementation of a virtual member can be changed in a derived class by overriding these members (method, property, indexer, event). The process of redefining a virtual method in a derived class is called method overriding. 

Ex: 

abstract class Car
{
    public virtual void speed()
    {
        Console.WriteLine("120 kmph");
    }
    //Force derived classes to implement
    public abstract void mileage();   
}
class Zen : Car
{
    // This function implementation is optional and 
    //depend upon need if a derived class want to 
    //implement it or else base class implementaion will be used.
    //public override void speed()
    //{
    //    Console.WriteLine("Zen Speed:70 kmph");
    //}

    //This class must implement this function.
    public override void mileage()
    {
        Console.WriteLine("Zen mileage:1200cc");
    }
}

class Program
{
    static void Main(string[] args)
    {
        Car c = new Zen();
        c.speed();
        c.mileage();        
    }   
}


In C#, by default, all methods are non-virtual. You cannot override a non-virtual method. 
You cannot use the virtual modifier with the static, abstract, private, or override modifiers.

public class Base
    {
        public virtual void Test()
        {
            Console.WriteLine("This is the method from virtual method");
        }
    }
    public class Direved : Base
    {
        public override void Test()
        {
            Console.WriteLine("This is the deviced version for the virtual method");
        }
    }
in Main :

            Base baseclass;
            Direved obj = new Direved();
            obj.Test();
            baseclass = obj;
            baseclass.Test();

Abstract classes, unlike interfaces, are classes. They are more expensive to use, because there is a look-up to do when you inherit from them.

Abstract classes look a lot like interfaces, but they have something more: You can define a behavior for them. It's more about a person saying, "these classes should look like that, and they have that in common, so fill in the blanks!".

ex: 

// I say all motor vehicles should look like this:
abstract class MotorVehicle
{

    int fuel;

    // They ALL have fuel, so lets implement this for everybody.
    int getFuel()
    {
         return this.fuel;
    }

    // That can be very different, force them to provide their
    // own implementation.
    abstract void run();
}

// My teammate complies and writes vehicle looking that way
class Car extends MotorVehicle
{
    void run()
    {
        print("Wrroooooooom");
    }
}

8. Interface : An interface is a contract: The person writing the interface says, "hey, I accept things looking that way", and the person using the interface says "OK, the class I write looks that way".

An interface is an empty shell. There are only the signatures of the methods, which implies that the methods do not have a body. The interface can't do anything. It's just a pattern.

An Interface is an abstract class which has only public abstract methods, and the methods only have the declaration and not the definition. 

// I say all motor vehicles should look like this:
interface MotorVehicle
{
    void run();

    int getFuel();
}

// My team mate complies and writes vehicle looking that way
class Car implements MotorVehicle
{

    int fuel;

    void run()
    {
        print("Wrroooooooom");
    }


    int getFuel()
    {
        return this.fuel;
    }
}

Implementing an interface consumes very little CPU, because it's not a class, just a bunch of names, and therefore there isn't any expensive look-up to do. It's great when it matters, such as in embedded devices.

9. Sealed Class :  Created When you want to restrict the class being inherited. 

Sealed classes are used to restrict the inheritance feature of object oriented programming. Once a class is defined as a sealed class, this class cannot be inherited. 

A sealed class cannot be used as a base class. Sealed classes are primarily used to prevent derivation. Because they can never be used as a base class, some run-time optimizations can make calling sealed class members slightly faster.

You can let a sealed class inherit from another class, but you cannot inherit from a sealed class:

sealed class MySealedClass : BaseClass // is ok
class MyOtherClass : MySealedClass     // won't compile

The main purpose of a sealed class is to take away the inheritance feature from the class users so they cannot derive a class from it. One of the best usage of sealed classes is when you have a class with static members. For example, the Pens and Brushes classes of the System.Drawing namespace. 

The Pens class represents the pens with standard colors. This class has only static members. For example, Pens.Blue represents a pen with blue color. Similarly, the Brushes class represents standard brushes. The Brushes.Blue represents a brush with blue color. 
 
So when you're designing a class library and want to restrict your classes not to be derived by developers, you may want to use sealed classes.

       Sealed Class       |        Static Class
--------------------------|-------------------------
it can inherit From other | it cannot inherit From other
classes but cannot be     | classes as well as cannot be
inherited                 | inherited

Sealed classes: 

  1. Can create instances, but cannot inherit
  2. Can contain static as well as non-static members.

Static classes:

  • Can neither create their instances, nor inherit them
  • Can have static members only.


10. Partial Class : Makes use of split Function

  • It Spilts the definition of the class into multiple classes in either same source code files or multiple code files.
  • One can create a class definition in multiple files but it is compiled as one class at run-time.
  • When an instance of such class is created a user can access all the methods from every source file.
11.OOPs Concepts (Fundamental) - Inheritance , Polymorphism , Abstraction ,Encapsulation.

12. Static : A class can be declared static, indicating that it contains only static members. It is not possible to create instances of a static class using the new keyword. Static classes are loaded automatically by the .NET Framework common language runtime (CLR) when the program or namespace containing the class is loaded.

We can't use 'This' in a static method because we can only use static variables/methods in a static method.

Define static methods in the following scenarios only:

  1. If you are writing utility classes and they are not supposed to be changed.
  2. If the method is not using any instance variable.
  3. If any operation is not dependent on instance creation. 
  4. If there is some code that can easily be shared by all the instance methods, extract that code into a static method.
  5. If you are sure that the definition of the method will never be changed or overridden. As static methods can not be overridden.

A static class is like a normal class but:

  1. We can't create any objects of it.
  2. We can't even create subclasses of it (it is sealed).
  3. It must contain only static members.
  4. It can't contain instance constructors.

Use static when you want to provide class level access to a method, i.e. where the method should be callable without an instance of the class.

A static method has two main purposes:

  • For utility or helper methods that don't require any object state. Since there is no need to access instance variables, having static methods eliminates the need for the caller to instantiate the object just to call the method. 
  • For the state that is shared by all instances of the class, like a counter. All instance must share the same state. Methods that merely use that state should be static as well.
  1. If a method doesn't modify state of object, or not using any instance variables.

  2. You want to call method without creating instance of that class.

  3. A method is good candidate of being static, if it only work on arguments provided to it e.g. public int factorial(int number){}, this method only operate on number provided as argument.

  4. Utility methods are also good candidate of being static e.g. StringUtils.isEmpty(String text), this a utility method to check if a String is empty or not.

  5. If function of method will remain static across class hierarchy e.g. equals() method is not a good candidate of making static because every Class can redefine equality.


    13. Methods Overriding / Overloading


    Polymorphism means “Many Forms”. In Polymorphism, poly means “Many” and morph means “Forms.” Polymorphism is one of the main pillars in Object Oriented Programming.


    There are two types of Polymorphism,

    1. Method Overloading
    2. Method Overriding

    Method Overloading

    Method Overloading is a type of polymorphism. It has several names like “Compile Time Polymorphism” or “Static Polymorphism” and sometimes it is called “Early Binding”.
     
    Method Overloading means creating multiple methods in a class with same names but different signatures (Parameters). It permits a class, struct, or interface to declare multiple methods with the same name with unique signatures.
class Demo
{
public int Sum(int x, int y)
{
int value = x + y;
return value;
}
public int Sum(int x, int y, int z)
{
int value = x + y + z;
return value;
}

Method Overriding is a type of polymorphism. It has several names like “Run Time Polymorphism” or “Dynamic Polymorphism” and sometime it is called “Late Binding”. 

Method Overriding means having two methods with same name and same signatures [parameters], one should be in the base class and other method should be in a derived class [child class]. You can override the functionality of a base class method to create a same name method with same signature in a derived class. You can achieve method overriding using inheritance. Virtual and Override keywords are used to achieve method overriding.

using System;

class Animal
{
public virtual void Sound()
{
  Console.WriteLine("This is parent class");
}
}

class Dog: Animal
{
public override void Sound()
{
  Console.WriteLine("Dogs bark");
}
}

class Test
{
static void Main(string[] args)
{
  Dog d = new Dog();
  d.Sound();
}
}

To prevent a method from being overridden, we use sealed keyword. Let's look at an example.

namespace testProject
{
    using System;

    class Animal
    {
        public virtual void Sound()
        {
            Console.WriteLine("This is parent class");
        }
    }

    class Dog : Animal
    {
        public sealed override void Sound()
        {
            Console.WriteLine("Dogs bark");
        }
    }
    class test : Dog
    {
        public override void Sound()
        {
            Console.WriteLine("Dogs bark");
        }
    }

    class Test
    {
        static void Main(string[] args)
        {
            Animal d = new Animal();
            d.Sound();
            d = new Dog();
            d.Sound();
            Console.ReadKey();
        }
    }
}

Gives Error : 

CS0239: 'test.Sound()': cannot override inherited member 'Dog.Sound()' because it is sealed


Points to be remembered,
  1. Method cannot be private.
  2. Only abstract or virtual method can be overridden.
  3. Which method should be called is decided at run time.
14. Class & Struct(For Small Model)

Class Supports Inheritance - Struct does not support inheritance
Class - It is pass by Reference Type /. It is Pass by Value Type
Members are default private in Class /. Members are public by Default.


15.  Virtual and Abstract 

Interfaces have all the methods having only declaration but no definition. In an abstract class, we can have some concrete methods. In an interface class, all the methods are public. An abstract class may have private methods.

Virtual methods have an implementation and provide the derived classes with the option of overriding it. Abstract methods do not provide an implementation and force the derived classes to override the method. 

So, abstract methods have no actual code in them, and subclasses HAVE TO override the method. Virtual methods can have code, which is usually a default implementation of something, and any subclasses CAN override the method using the override modifier and provide a custom implementation.


public abstract class E
{
    public abstract void AbstractMethod(int i);

    public virtual void VirtualMethod(int i)
    {
        // Default implementation which can be overridden by subclasses.
    }
}

public class D : E
{
    public override void AbstractMethod(int i)
    {
        // You HAVE to override this method
    }
    public override void VirtualMethod(int i)
    {
        // You are allowed to override this method.
    }
}

Abstract Method

  • Abstract Method resides in abstract class and it has no body.
  • Abstract Method must be overridden in non-abstract child class.

Virtual Method

  • Virtual Method can reside in abstract and non-abstract class.
  • It is not necessary to override virtual method in derived but it can be.
  • Virtual method must have body ....can be overridden by "override keyword".....

A Class can extend single abstract class whereas it can implement multiple interfaces.



16. Boxing & UnBoxing

Converting a Value Type to Reference Type is called boxing.

int value=10

// Boxing -----//
object boxedvalue=value1;

Explicit conversion of the same Reference type is called UnBoxing.

int unboxing=int(boxedvalue);

Boxing and unboxing is an important concept in C#. C# Type System contains three data typesValue Types (int, char, etc)Reference Types (object) and Pointer Types. Basically it convert a Value Type to a Reference Type, and vice versa. Boxing and Unboxing enables a unified view of the type system in which a value of any type can be treated as an object.
int num = 23; // 23 will assigned to num
Object Obj = num; // Boxing
Boxing
int num = 23;         // value type is int and assigned value 23
Object Obj = num;    // Boxing
int i = (int)Obj;    // Unboxing
Unboxing
17. Preprocessor Directives in C#

  • Suppose, you are writing a code which is going to run on both 32-bit and 64-bit machines. We can define a value which will be used for 32 bit and a different value for 64 bit. A preprocessor is the best tool to provide this kind of functionality to our code.
  • A preprocessor preprocesses information before compilation. We know that after defining a variable, memory is allocated to that variable during compilation. Unlike this, a preprocessor processes information before starting the compilation.
#define is used to define a symbol. For example, #define DEBUG would define the symbol DEBUG in our program.
#undef is used to undefine a defined symbol in our code. For example, #undef DEBUG would undefine the already defined symbol DEBUGin our program.

#if is used to check a preprocessor expression. A preprocessor expression can only contain symbols (defined using #define) and &&||!=! and == operators. We can use #if for conditional execution of preporcessors.

#if is ended with a #endif.

#if (DEBUG)
      Console.WriteLine("Debug mode is defined");
    #endif
#waring is used to display a warning message on the screen
#if (DEBUG)
      #warning DEBUG IS ON
    #endif
We can specify a block of code using #region and #endregion which can be expanded or collapsed using Visual Studio Code Editor.
Similar to a warning, we can also display and error.
#if (DEBUG)
      #error Turn off Debug
    #endif

18. Nullable in C#

Reference types like array, strings, etc. are by default null if not initialized. However, value types like int, char, short, etc. can't take null value in C#.

So, if we try to assign a null value to an int (int x = null), we will get a compilation error.

But C# provides nullable type which can be used to hold null values.

We use ? operator to declare any data type as nullable type. For example, to declare int as nullable type, we need to write int?. Now, we can store null values to int. For example, int? x = null;.

int? x = null;
    int? y = 5;

    Console.WriteLine(x);
    Console.WriteLine(y);

5


In the above example, the value of x is null, so nothing was printed when we tried to print the value of x.

double? x = null;
    double? y = 5.5;

    Console.WriteLine(x.GetValueOrDefault());
    Console.WriteLine(y.GetValueOrDefault());

We can use GetValueOrDefault method to get the value of any nullable type and if the value is null, we will get 0.

0
5.5

19. Constructor

constructor is a special member method of a class which is called automatically when an object of that class is made. It has the same name as that of the class and has no return type.

We can also have constructors with parameters.

Destructors are methods which are just the opposite of constructors. Destructors destroy the object whenever the object goes out of scope.

It has the same name as that of the class with a tilde (~) sign before it.

A destructor gets automatically called when the object goes out of scope. We know that a non-parameterized constructor gets automatically called when an object of the class is created. Exactly opposite to it, a destructor gets called when the object goes out of scope and destroys the object.

We can also have a static constructor. A static constructor can't have any parameters or modifier. It is invoked only once during the creation of the first instance of the class. We use a static constructor to set data to static members.

If a data is static, we will use it without the creation of any object. So, it doesn't vary with different objects. So, we use a static constructor to set its value because a static constructor is only executed during the creation of the first object. We can also use a static constructor to perform a task which is required to perform only once.



using System;

class Circle
{
  public static double pi;
  private int radius;

  public Circle(int r)
  {
    radius = r;
  }

  static Circle()
  {
    pi = 3.14;
    Console.WriteLine("Static Constructor");
  }

  public void PrintArea()
  {
    Console.WriteLine(pi*radius*radius);
  }
}

class Test
{
  static void Main(string[] args)
  {
    Circle a = new Circle(2);
    Circle b = new Circle(3);

    a.PrintArea();
    b.PrintArea();
  }
}



Static Constructor
12.56
28.26

Constructor Overloading


Suppose we have a Student class and while making its object, we want to pass a name to it and if nothing is passed then the name should be "unknown". And yes! we can do this by having two constructors. Let's look at an example.


using System;

class Student
{
  public string name;

  public Student()
  {
    name = "unknown";
  }

  public Student(string name)
  {
    this.name = name;
  }

  public void PrintName()
  {
    Console.WriteLine(this.name);
  }
}

class Test
{
  static void Main(string[] args)
  {
    Student a, b;
    a = new Student("xyz");
    b = new Student();

    a.PrintName();
    b.PrintName();
  }
}



Conditions for Constructor Overloading


The conditions for constructor overloading is:

  • Either all constructor have a different number of parameters
  • or all constructors have different types of parameters
  • or the order of parameters is different for all constructors

20 . THINGS TO BE REMEMBER 

Difference between const and readonly

const

Must be initialized at the time of declaration of the field.

By default const fields are static

You cannot reassign a const variable.

It is called as compile time constant

Can be declared in function.

readonly

Initialized at the time of declaration or the constructor of the class

By default readonly fields are not static. It can use with static modifier.

You can reassign a const variable in constructor.

It is called as run time constant

Cannot declare in function.

Ex:

using System;
namespace ConsoleApplication1
{    
    class constDemo
    {
        public const  int  x = 25;
        // cannot mark as static, by default const is static
        //public static const int b=50; 
    }
    class Program
    {               
        static void Main(string[] args)
        {                      
            const  int intVar=10;                  
            //Cannot reassigns the value.
            //Error:The left-hand side of an assignment must be a variable, property or indexer
            //intVar = 40; 
            Console.WriteLine(intVar);
            // x variable is by default constant. Therefore called by the class name.
            Console.WriteLine("x = " + constDemo.x);
            // Error: The expression being assigned to 'value' must be constant
            // Here length is not constant.
            int length = 5;
            //const int value = 10 + length;
            Console.ReadLine();
        }
    }
}

ReadOnly : 

const field is a compile-time constant but the readonly field is runtime constants.


using System;
namespace ConsoleApplication1
{
    class MyClass
    {
        readonly int intVar = 25; // initialized at the time of declaration
        readonly int readOnlyVar;       
        public MyClass(int x)
        {
            readOnlyVar = x; // initialized at run time
            Console.WriteLine("readOnlyVar = " + readOnlyVar);
        }
        public void SetData()
        {
            // It will give the compile time error.
            // You cannot set the value in function.
            //readOnlyVar = 100;
            // intVar has already initialized.
            Console.WriteLine("intVar = " + intVar);
        }
    }    
    class Program
    {              
         static void Main(string[] args)
         {
             MyClass obj = new MyClass(30);
             obj.SetData();
             Console.ReadLine();
         }
    }
}

Singleton Class Vs Sealed Class Vs Static Class

Signleton is not a language class or class specific attribute. It is a design pattern by which can can maintain a object lifetime of a class object for the whole application life.
Sealed class is a class that you can not extended/inherit.
Static Class is a class you need to create all member under that class should be static. You can not create instance of that class.


Singleton is Design Pattern in which you make the constructor private so that its object cannot be declare directly, you will need to create Instance of the class and than you can use it.

public class Singleton {
   private static final Singleton instance;   
 
   private Singleton(){}
 
   public static Singleton getInstance() {
     if (instance == null)
       instance = new Singleton();
     return instance;
   }
 }
Sealed Class:

1. A class, which restricts inheritance for security reason is declared, sealed class.
2. Sealed class is the last class in the hierarchy.
3. Sealed class can be a derived class but can't be a base class.
4. A sealed class cannot also be an abstract class. Because abstract class has to provide functionality and here we are restricting it to inherit.

Static Class:
Static class is used where you have some utilities lib in you project and you can create common class and can set as Static class
Static classes only contain static members.
Static classes can not be instantiated. They cannot contain Instance Constructors

Delegates:
  • Delegates are same are function pointers in C++, but the only difference is that they are type safe, unlike function pointers. Delegates are required because they can be used to write much more generic type-safe functions.
  • Its's a type safe function pointer.
  • A Delegate holds the reference of a method and then calls the method for execution.
  • To Call a method by using a delegate we have 3 steps

1. Define a delegate

<modifier> delegate void|type <Name>(Paramer List)
public delegate void AddDelegate(int a, int b)

Return Type and Parameter types need to same. 

Delegate is a type so it need to create Under namespace , we can also create under class [ type inside type]

2. Instantiating the delegate

AddDelegate ad=new AddDelegate(p.AddNums);

3. Step 3 : Call the delegate passing required parameter value - internally the method which is bound with the delegate gets executed.
ad.
ex :

            ad(3, 4);
            ad.Invoke(100, 50);
            string d = sayDelegate.Invoke("amit");
            string str = sayDelegate("hello");
            Console.WriteLine(str);
            Console.WriteLine(d);

Full Example :
namespace testProject
{
    using System;

    // Step 1 Defining a Delegate

    public delegate void AddDelegate(int x, int y);
    public delegate string SayDelegate(string str);
    class Test

    {
        public void addnumes(int a, int b)
        {
            Console.WriteLine(a + b);
        }
        public static string sayHello(string name)
        {
            return "Hello " + name;
        }

        static void Main(string[] args)
        {
            Test test = new Test();

            AddDelegate ad = new AddDelegate(test.addnumes);
            SayDelegate sayDelegate = new SayDelegate(Test.sayHello);

            ad(3, 4);
            ad.Invoke(100, 50);
            string d = sayDelegate.Invoke("amit");
            string str = sayDelegate("hello");
            Console.WriteLine(str);
            Console.WriteLine(d);
            Console.ReadKey();
        }
    }
}

A delegate is an object which refers to a method or you can say it is a reference type variable that can hold a reference to the methods. Delegates in C# are similar to the function pointer in C/C++. It provides a way which tells which method is to be called when an event is triggered.


For example, if you click an Button on a form (Windows Form application), the program would call a specific method. In simple words, it is a type that represents references to methods with a particular parameter list and return type and then calls the method in a program for execution when it is needed.

Important Points About Delegates:

  • Provides a good way to encapsulate the methods.
  • Delegates are the library class in System namespace.
  • These are the type-safe pointer of any method.
  • Delegates are mainly used in implementing the call-back methods and events.
  • Delegates can be chained together as two or more methods can be called on a single event.
  • It doesn’t care about the class of the object that it references.
  • Delegates can also be used in “anonymous methods” invocation.
  • Anonymous Methods(C# 2.0) and Lambda expressions(C# 3.0) are compiled to delegate types in certain contexts. Sometimes, these features together are known as anonymous functions.

What are value types and reference types?

  • A value type holds a data value within its own memory space. Example 
  • int a = 30;
  • string b = "Hello Guru99!!";
  • Reference type stores the address of the Object where the value is being stored. It is a pointer to another memory location. 

  • In an array, we can have items of the same type only. The size of the array is fixed when compared. To an arraylist is similar to an array, but it doesn't have a fixed size. 


  • Constant variables are declared and initialized at compile time. The value can't be changed afterward. Read-only is used only when we want to assign the value at run time.
  • StreamWriter class is used to write character-based data in a file and StreamReader is used to read character-based data from a file. We create an object of StreamWriter and pass the object of FileStream while creating it. For example, we will pass the object f of FileStream class created above to make an object of StreamWriter i.e., StreamWriter s = new StreamWriter(f);.

  • We use try and catch to handle errors in C#. The code which we want to execute is written inside try. If the statements inside the try have any error, then the statement inside the catch block is executed.

  • When we have codes which we want to get executed in any case i.e., regardless of the execution of try or catch block, we write those codes in the finally block. 

We can also throw an exception anytime we want using the throw keyword.
if(b == 0)
    throw new DivideByZeroException("Dividing by 0 not allowed");
  else
    Console.WriteLine(Divide(a, b));

We can also derive the Exception class to create our own custom exceptions. 
using System;

class NegativeNumberNotAllowed: Exception
{
public NegativeNumberNotAllowed(string message): base(message)
{

}
}

class Test
{

static void CheckForNegative(int number)
{
  if(number < 0)
  {
    throw new NegativeNumberNotAllowed("Negative number is not allowed");
  }
}

static void Main(string[] args)
{
  try
  {
    CheckForNegative(-10);
  }
  catch(NegativeNumberNotAllowed e)
  {
    Console.WriteLine(e);
  }
}
}

  • checked and unchecked are two keywords used to handle arithmetic overflow. Think of a case when you are trying to add 1 to the maximum value of an integer i.e., int.MaxValue + 1. Normally, we will get a negative value because int wraps around from MaxValue to MinValue i.e., if it is exceeding the maximum value, it will become the minimum value.

checked
  {
    int x = int.MaxValue + 1;
    Console.WriteLine(x);
  }
file.cs(8,19): error CS0220: The operation overflows at compile time in checked mode
We use checked to throw an error in the case of overflow. So, we will get an error instead of getting the integer to wrapping around the negative value.

using System;
class Test
{
static void Main(string[] args)
{
  unchecked
  {
    int x = int.MaxValue + 1;
    Console.WriteLine(x);
  }
}
}

-2147483648

unchecked allows the overflow and won't raise any errors.


Generics are used to make reusable code classes to decrease the code redundancy, increase type safety, and performance. Using generics, we can create collection classes. To create generic collection, System.Collections.Generic namespace should be used instead of classes such as ArrayList in the System.Collections namespace. Generics promotes the usage of parameterized types.

In C#, we can also have generic classes and generic methods i.e., classes and methods not made for a specific type but can be used with any general type.

We use <> brackets for this purpose. Suppose, we have defined a class or method with <T> and performed each operation on T inside the method or the class. And we passed an integer while calling it - <int>, then the T inside the class or the method will be changed to take int during the time of compilation.

sing System;

class Generic<T>
{
  private T genericVariable;

  public Generic(T genericValue)
  {
    this.genericVariable = genericValue;
  }

  public void Display()
  {
    Console.WriteLine(this.genericVariable);
  }
}

class Test
{
  static void Main(string[] args)
  {
    Generic<int> g = new Generic<int>(5);

    Generic<string> g1 = new Generic<string>("CodesDope");

    g.Display();
    g1.Display();
  }
}

5
CodesDope


We used a placeholder T in the above examples and this placeholder can be of any type. In C#, we can also constraint the type of placeholder using the where keyword. Suppose, we have defined a class as:

class ClassName<T> where T: class

In this case, T can only be reference type like class, string, etc. If we try with something else, we will get an error.

Here, class in where T: class means T can be a reference type. Let's look at the table given below for another type of constraints.

ConstraintDescription
classMust be reference type
structMust be value type
new()Must have public parameterless constructor.
BaseClassNameMust be derivied from BaseClassName class.
InterfaceNameMust implement InterfaceName interface.
UMust be or derive from the argument supplied for U.

Let's take an example.


using System;
class Generic<T> where T: class
{
  public T GenericVariable
  {
    get;
    set;
  }
}

class Test
{
  static void Main(string[] args)
  {
    Generic<int> g = new Generic<int>();

    g.GenericVariable = 10;

    Console.WriteLine(g.GenericVariable);
  }
}


hello.cs(16,5): error CS0452: The type 'int' must be a reference type in order to use it as type parameter 'T' in the generic type or method 'Generic<T>'
hello.cs(16,26): error CS0452: The type 'int' must be a reference type in order to use it as type parameter 'T' in the generic type or method 'Generic<T>'


In this example, we constrained the placeholder to take only reference type using class and we tried to make an object with an integer for the placeholder. Since int is a value type, we got errors during compiling the code.

Let's try with a reference type.

using System;

class Generic<T> where T: class

{
  public T GenericVariable
  {
    get;
    set;
  }
}

class Test
{
  static void Main(string[] args)
  {
    Generic<string> g = new Generic<string>();

    g.GenericVariable = "CodesDope";

    Console.WriteLine(g.GenericVariable);
  }
}

Output : CodesDope

4 comments: