Wednesday, September 2, 2020

Sealed Classes and Members

  • If "sealed" modifier applied to a class, prevents derivation from that class.
  • If "sealed" modifier applied to a method, prevents overriding of that method in a derived class.  
  • Sealed classes are slightly faster because of some run time optimization.  But sealed classes are hardly ever used. 
  • The string class is declared as sealed, and that’s why we cannot inherit from it


Abstract Classes and Members

  •  Abstract modifier used to indicate that a class or member is missing the implementation. 
  • The purpose of having a abstract class to provides a common definition of a base class that multiple derived classes can be shared.
  • We use abstract members when it doesn’t make sense to implement them in a base class. For example, the concept of drawing a shape is too abstract. We don’t know how to draw a shape. This needs to be implemented in the derived classes.
  •     public class Shape
        {
            public virtual void Draw()
            {
            }
        }
    
        public class Circle : Shape
        {
            public override void Draw()
            {
                Console.WriteLine("Drawing a circle");
            }
        }
    
    
  • In these situations, better approach is to use abstract modifier. In a derived class, we need to override all abstract members of the base class, otherwise that derived class is going to be abstract too.  
  •     public abstract class Shape
        {
            public abstract int Weight { get; set; }
            public abstract void Draw();
    		
            //Concrete Method
            public void Print()
            {
            }
    
        public class Circle : Shape
        {
            private int _weight;
            public override int Weight
            {
                get
                {
                    return _weight;
                }
    
                set
                {
                    Weight = _weight;
                }
            }
    
            public override void Draw()
            {
                Console.WriteLine("Drawing a circle");
            }
        }
    
  • When a class member is declared as abstract, that class needs to be declared as abstract as well. That means that class is not complete.
  • We can not define abstract variables and abstract class cannot be instantiated. 
  • In C#, "Stream" class is an abstract class and because it is too abstract. But FileStream is derived from System.IO.Stream and it is very specific. It allows to read and write data to file. 



Tuesday, September 1, 2020

Polymorphism

 Polymorphism means ability to have many forms. There are two types pf polymorphism. 

  1. Compile time polymorphism/Overloading
  2. Runtime polymorphism/Overriding
Overloading

  • Compile time polymorphism is method and operators overloading. It is also called early binding.
  • In method overloading method performs the different task at the different type and different no of input parameters with the same method name.
  • You should consider overloading a method when you need a couple of methods for some reason that take different parameters, but conceptually do the same thing.
  •     class Program  
        {  
            public class Shape  
            {  
                public void Area(float r)  
                {  
                    float a = (float)3.14 * r;  
                    // Function overload with 1 parameter.  
                    Console.WriteLine("Area of a circle: {0}",a);  
                }  
                public void Area(float l, float b)  
                {  
                    float x = (float)l* b;  
                    // Function overload with 2 parameters.  
    Console.WriteLine("Area of a rectangle: {0}",x); } public void Area(float a, float b, float c) { float s = (float)(a*b*c)/2;
    // Function overload with 3 parameters.
    Console.WriteLine("Area of a circle: {0}", s); } } static void Main(string[] args) { Shape shape= new Shape(); shape.Area(2.0f);
    shape.Area(20.0f,30.0f);
    shape.Area(2.0f,3.0f,4.0f);
    Console.ReadLine(); } }

Overriding
  • Method overriding means changing the implementation of an inherited method.
  • If a declare a method as virtual in the base class, we can override it in a derived class.
  • At run-time, when client code calls the method, the CLR looks up the run-time type of the object, and invokes that override of the virtual method. 
  • In the source code you can call a method on a base class, and cause a derived class's version of the method to be executed.
  • Virtual methods enable you to work with groups of related objects in a uniform way. For example, suppose you have a drawing application that enables a user to create various kinds of shapes on a drawing surface. Even though this can be  achieved by no of switch statements, it will be hard to maintenance. So you can achieve the same thing by using overriding a method.
  •     public class Shape
        {
            public int X { get; private set; }
            public int Y { get; private set; }
            public int Height { get; set; }
            public int Width { get; set; }
    
            // Virtual method
            public virtual void Draw()
            {
                Console.WriteLine("Performing base class drawing tasks");
            }
        }
    
        public class Circle : Shape
        {
            //Override Method
            public override void Draw()
            {
                // Code to draw a circle...
                Console.WriteLine("Drawing a circle");
            }
        }
        public class Rectangle : Shape
        {
            public override void Draw()
            {
                // Code to draw a rectangle...
                Console.WriteLine("Drawing a rectangle");
            }
        }
        public class Triangle : Shape
        {
            public override void Draw()
            {
                // Code to draw a triangle...
                Console.WriteLine("Drawing a triangle");
            }
        }
    
        public class Program
        {
            static void Main(string[] args)
            {
                var shapes = new List
                            {
                             new Rectangle(),
                             new Triangle(),
                             new Circle()
                            };
    
                // invoked Draw() on each of the derived classes, not the base class.
                foreach (var shape in shapes)
                {
                    shape.Draw();
                }
                Console.Read();
            }
        }
        
        Output
        Drawing a rectangle
        Drawing a triangle
        Drawing a circle
    	
    
  • A derived class is able to stop virtual inheritance by declaring an override member as "sealed".
  •     public class Triangle : Shape
        {
            public sealed void Draw()
            {
                // Code to draw a triangle...
                Console.WriteLine("Drawing a triangle");
            }
        }
    
  • Using the "base" keyword, the derived class is able to access the method.
  •     public class Triangle : Shape
        {
            public override void Draw()
            {
    	   base.Draw(); 
            }
        }

Saturday, August 29, 2020

Reference Types and Value Types

Value Types

  • Value type are the variables which are stored in its own memory location.
  • Value types are stored in stack according to the order it is created.
Only c will be changed to 7.


Reference Types 

  • Reference types does not stored its value within its own memory location. Instead of that , it stores a pointer/address/reference where the actual value is stored.
  • Reference types are stored in heap. But the variable is stored in stack and data is stored on the heap. 

Both d.hp and f.hp will be changed to 100.

 



Tuesday, August 25, 2020

Upcasting and Downcasting

  •  Upcasting: conversion from a derived class to a base class
  •  All objects can be implicitly converted to a base class reference.  
  •       Shape shape = circle;   // Shape is base class and circle is derived class	
    
  • Downcasting: conversion from a base class to a derived class 
  • Downcasting requires a cast.
  •       Circle circle= circle;   // Shape is base class and circle is derived class	
  • Casting can throw an exception if the conversion is not successful. We can use the as keyword to prevent this. If conversion is not successful, null is returned. 
  •       Circle circle = shape as Circle;
          if (circle != null)
  • We can also use the is keyword
  • if (shape is Circle) {
    var circle = (Circle) shape;
    }

Access Modifiers

  •  In C# we have 5 access modifiers: 
    • Public
    • Private
    • Protected
    • Internal
    • Protected Internal
  • A class member declared with public is accessible everywhere. 
  • A class member declared with private is accessible only from inside the class.
  • A class member declared with protected is accessible for containing class and the derived types of the containing class. 
  • A class member declared with internal is accessible only for current assembly.
  • A class member declared with protected internal is accessible for current assembly and derived types of the containing class.

Monday, August 24, 2020

Properties

  •  A property is a class member that encapsulate a getter/setter for accessing a filed.  
  • As a best practice, we must declare fields as private and create public properties to provide access to them. 
  • A property encapsulates a get and a set method.
  •     public class Customer
        {
            private string _name;
            public string Name
            {
                get { return _name; }
                set { _name = value; }
            }
        }
    
  • Inside the get/set methods we can have some logic.
  •     public class Person
        {
            public DateTime BirthDate { get; set; }
            public int Age
            {
                get
                {
                    var timespan = DateTime.Today - BirthDate;
                    var years = timespan.Days / 365;
                    return years;
                }
            }
        }
    
  • If you don’t need to write any specific logic in the get or set method, it’s more efficient to create an auto-implemented property. An auto-implemented property encapsulates a private field behind the scene. So you don’t need to manually create one. The compiler creates one for you.
  •     public class Person
        {
            public DateTime BirthDate { get; set; }
        }
    
  • Auto-implemented properties are required to specify both get and set, so if you want an auto-implemented property to be read-only, you must use private setters. 
  •     public class Person
        {
            public DateTime BirthDate { get; private set; }
        }