Wednesday, September 2, 2020

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; }
        }
    

Friday, August 21, 2020

Read only and Constants Fields

Readonly
  • When a field is declared with readonly, it needs to be initialized either during declaration or in a constructor.
  •  
        public class Const_V_Readonly
        {
            public readonly int Readonly_Value;
    
            public Const_V_Readonly()
            {
                Readonly_Value = 3;  
            }
        }
    
  • A value can be assigned only once to readonly fileds.
  • We use the readonly modifier to improve the robustness of our code. It prevents from accidentally overwriting the value of a field, which can result in an unexpected state.
  • When use static modifier for the readonly fields, it needs to be initialized either during declaration or in a static constructor. 
  •  
        public class Const_V_Readonly
        {
            public static readonly int Readonly_Value;
    
    	//Access modifiers are not allowed on static constructors
            static Const_V_Readonly()
            {
                Readonly_Value = 3;
            }
        }
  • If consider "Const_V_Readonly" class in AssemblyA , AssemblyB references AssemblyA and uses these values in code. When AssemblyA is compiled, readonly values are like a ref to a memory location. The value is not baked into AssemblyB's IL. This means that if the memory location is updated, AssemblyB gets the new value without recompilation. So if "Readonly_Value" is updated to 30, you only need to build AssemblyA. All clients do not need to be recompiled. 
  • So if you have a constant that may change or when in doubt, use a readonly.


Constants 
  • A const keyword is used to declare constant fields and constant local.
  • The value of the constant field is the same throughout the program or in other words, once the constant field is assigned the value of this field is not be changed. 
        public class Const_V_Readonly
        {
            public const int Constant_Value = 2;
        }
  • The constant field should be initialized on the declaration. (Can not intialize it in a constructor or method)
  • If consider "Const_V_Readonly" class in AssemblyA and AssemblyB references AssemblyA and uses these values in code. When AssemblyA is compiled,  const value is like a find-replace, the value 2 is 'baked into' the AssemblyB's IL. This means that if we update Constant_Value to 20 in the future. AssemblyB would still have 2 till we recompile it.
  • So if you are confident that the value of the constant won't change use a const.