Tuesday, 31 January 2017

GENERICS IN C#

GENERICS IN C#



GENERICS

Generics are introduced in c# 2.0. Generics allow us to design classes and methods deoupled from the data types.

Generics classes are extresively used by collection classes available in System.Collections.Generic namespace.(Covered in the next session)

One way of making AreEqual() method resuable, is to use object type parameters. Since, every type in .NET directly onherit from System.Object type, AreEqual() method works with any data type, but the probelm is performance degradation due to boxing and unboxing happening.

Also, AreEqual() method is no longer type safe. It is now possible to pass integer for th first parameter, and string for the second parameter.It doesn't really make sense to compare strings with integers.

So, the problem with using System.Object.type is that
1. AreEqual() method is not type safe
2. Performance degradation due to boxing and unboxing.

--------------------------------------------------------------------------------------------------------------------------
using System;
using System.Reflection;

namespace ConsoleApplication4
{
    public class MainClass
    {
        private static void Main()
        {
            bool Equal = Calculator.AreEqual<int>(10,10);
            if (Equal)
            {
                Console.WriteLine("Equal");
                Console.ReadLine();
            }
            else
            {
                Console.WriteLine("Not Equal");
                Console.ReadLine();
            }
        }

    
    }


    public class Calculator
    {
        public static bool AreEqual<T>(T Value1, T Value2)
        {
            return Value1.Equals(Value2);
        }

    }
}

Monday, 30 January 2017

LATE BINDING USING REFLECTIONS IN C#

EARLY V/S LATE BINDING IN C#

Difference between early and late binding:


1.Early binding can flag errors at compile time. With late binding there is a risk of run time exceptions.

2. Early binding is much better for performance and should always be preferred over late binding. Use late binding only when working with an objects that are not available at compile time.

3. I think 95% of people use early binding over late binding because of late binding is going to be compiled properly at compile time but it will through exception at Runtime "if there is any errors", so early binding is better as it warns the programmer with "wiggly sign" at compile time itself, it does not allow to compile the program.



using System;
using System.Reflection;

namespace ConsoleApplication4
{
    public class MainClass
    {
        private static void Main()
        {
// LATE BINDING STARTS HERE
            Assembly executingAssembly = Assembly.GetExecutingAssembly();

            Type customerType = executingAssembly.GetType("ConsoleApplication4.Customer");


            object customerInstance = Activator.CreateInstance(customerType);


          MethodInfo getFullNameMethod =  customerType.GetMethod("GetFullName");


          string[] parameters = new string[2];

          parameters[0] = "Malla";
          parameters[1] = "Tech";

         string fullName = (string)getFullNameMethod.Invoke(customerInstance, parameters);

         Console.WriteLine("Full Name = {0}", fullName);
         Console.ReadLine();

// LATE BINDING ENDS HERE.

            ///     Early Binding 
        //    Customer C1 = new Customer();
        //    string fullname = C1.GetFullName("Malla", "Tech");
        //    Console.WriteLine("Full Name = {0}", fullname);
        //    Console.ReadLine();
        }
    }


    public class Customer
    {
        public string GetFullName(string FirstName, string LastName)
        {
            return FirstName + " " + LastName;
        }

    }
}

REFLECTIONS IN C#

REFLECTIONS IN C#


"is the ability of inspecting assemblies' metadata at runtime. it is used to find all types in an  assembly and /or dynamically invoke methods in an assembly."


Uses of reflection:

1. When you drag and drop a button on a win forms or asp.net application. The properties window uses reflection to show all the properties of the Button class. So, reflection is extensivley used by IDE or a UI designers.


2. Late binding can be achieved by using reflection. You can use reflection to dynamically create an instance of a type, about which we don't have any information at compile time. So, reflection enables you to use code that is not available at compile time.

3. Consider an example where we have two alternate implementations of an interface. You want to allow the user to pick one or the other using a config file. With reflection, you can simply read the name of the class whose implementation you want to use from the config file, and instantiate an instance of that class. This is another example for late binding using reflection.

--------------------------------------------------------------------------------------------------------------------------
using System;
using System.Reflection;

namespace ConsoleApplication4
{
    public class MainClass
    {
       
        private static void Main()
        {    
            Type T = Type.GetType("ConsoleApplication4.Customer");
            Console.WriteLine("Full Name = {0}", T.FullName);
            Console.ReadLine();
            Console.WriteLine("Just the Name = {0}", T.Name);
            Console.WriteLine("Just the Namespace = {0}", T.Namespace);

            Console.ReadLine();

            Console.WriteLine("Properties in Customer");
            PropertyInfo[] properties = T.GetProperties();
            foreach (PropertyInfo property in properties)
            {
                Console.WriteLine(property.PropertyType.Name + " " + property.Name);
                Console.ReadLine();
            }

            Console.ReadLine();

            Console.WriteLine("methods in Customer class");
            MethodInfo[] methods = T.GetMethods();
            foreach (MemberInfo method in methods)
            {
                Console.WriteLine(method.ReflectedType.Name + " " + method.Name);
                Console.ReadLine();
            }


            Console.ReadLine();

            Console.WriteLine("Constructor in Customer class");
            ConstructorInfo[] constructors = T.GetConstructors();
            foreach (ConstructorInfo constructor in constructors)
            {
                Console.WriteLine(constructor.Name);
                Console.ReadLine();
            }
        }
    }
}
    public class Customer
    {
        public int Id { get; set; }
        public string Name { get; set; }

        public Customer(int ID, string Name)
        {
            this.Id = ID;
            this.Name = Name;
        }
        public Customer()
        {
            this.Id = -1;
            this.Name = string.Empty;

        }
        public void PrintID()
        {
            Console.WriteLine("ID= {0}", Id);
            Console.ReadLine();
        }
        public void PrintName()
        {
            Console.WriteLine("Name ={0}", Name);
            Console.ReadLine();
        }
    }



==============================================























ATTRIBUTES IN C#

Attributes


Attributes allow you to add declarative information to your programs. This information can then be queried at runtime using reflection

There are several Pre-defined attributes provided by .NET.It is also possible to create your own Custom Attributes.

A few pre-defined attributes with in the .NET framework.
obsolete    - Marks types and type members outdated
WebMethod  - To expose a method as an XML Web service method
Serializable  - Indicates that a class can be serialized


It is possible to customize the attributes using parameters
An attributes is a class that inherits from SYSTEM.ATTRIBUTES base class.
--------------------------------------------------------------------------------------------------------------------------

using System;
using System.Collections.Generic;

namespace ConsoleApplication4
{
    public class MainClass
    {
        private static void Main()
        {
            Calculator.AddNumber(new List<int>() {10,20, 30});
           

        }
    }

    public class Calculator
    {
        [Obsolete("Use(List<int> Numbers)Method",true)]
        public static int AddNumber(int FirstNumber, int SecondNumber)
        {
            return FirstNumber + SecondNumber;
        }

        public static int AddNumber(List<int> Numbers)
        {
            int Sum = 0;
            foreach (int Number in Numbers)
            {
                Sum = Sum + Number;
            }
            return Sum;
        }
    }

}

ACCESS MODIFIERS FOR TYPES(CLASSES) IN C#

CLASSES, STRUCTURES, INTERFACES, DELEGATES WILL HAVE TYPES AND CAN ONLY USE INTERNAL OR PUBLIC ACCESS MODIFIERS

using System;

namespace ConsoleApplication4
{
    public class AssemblyOne
    {
        public void PrinID()
        {
            Console.WriteLine("print this is a types example");
        }
    }
}

// default  is internal for type classes like classes, structures, interfaces, delegates, etc..

// default  is private for type members like fields, properties, methods, etc 


using System;
using AssemblyOne;

namespace ConsoleApplication4
{
internal class AssemblyTwo 
    {
        AssemblyOne instance = new AssemblyOne();
        instance.xxxxxx     = xyz;
    }
}

ACCESS MODIFIERS IN C#

ACCESS MODIFIERS IN C#



Types Vs Type Members


In C# there are 5 different access modifiers in c#
1.Private
2.Protected
3.Internal
4. Protected Internal
5. Public

Private members are available only with in the containing type, where as public members are available any where. There is no restricction.

Protected Members are available, with in the containing type and to the types that derive from the containing type

Access Modifier                       Accessibility
Private ->                  Only with in the containing class
Public ->                  Any where, No Restrictions
Protected ->                 With in the containing types and the types derived from the
                                                 containing type.
-------------------------------------------------------------------------------------------------------------------------

using System;
using System.IO;

namespace ConsoleApplication4
{

    //public class Customer
    //{

    //    private int _id;

    //    public int Id
    //    {
    //        get { return _id; }
    //        set { _id = value; }

    //    }
    //}

    public class Customer
    {
        protected int _id;
    }

    public class corporateCustomer : Customer
    {
        public void printID()
        {
            corporateCustomer cc = new corporateCustomer();
            cc._id = 101;
        }
    }

   public  class Program
    {
        public static void Main()
    {
        Customer C1 = new Customer();
        Console.WriteLine(C1._id);
    }

    }
}
-------------------------------------------------------------------------------------------------------------------------

INTERNAL AND PROTECTED INTERNAL ACCESS MODIFIERS IN C#




INTERNAL AND PROTECTED INTERNAL

A member with internal access modifier is available anywhere with in the containing assembly. it's a compile time error to access, an internal member from outside the containing assembly.

Protected Internal members can be accessed by any code in the assembly in which it is declared, or from within a derived class in another assembly. It is a combination of protected and internal. If you have understood protected and internal, this should be very easy to follow. 



Access Modifier                       Accessibility
Private                    Only with in the containing class
Public                   Any where, No Restrictions
Protected                   With in the containing types and the types derived from the 
                                                 containing type.
Internal                  Anywhere with in the containing assembly
ProtectedInternal         Anywhere with in the containing assembly, and from within a 

                                                 derived class in any another assembly.





INTERNAL:- 
Internal fields are accessible within the assembly where it is defined not outside of the assembly.

PROTECTED INTERNAL:-
Protected Internal are accessible within the assembly and in the derived class through inheritance within another assembly(refering the base class in the derived class through reference or namespace declaration).

UNDERSTANDING DIFFERENCE BETWEEN TYPES AND TYPE MEMBERS IN C#

DIFFERENCE BETWEEN TYPES AND TYPE MEMBERS IN C#

Types Vs Type Members

In this example Customer is the Type and fields, properties and method are type members.

So, in general classes, structs, enums, interfaces, delegates are called as types and fields, properties, constructors, methods etc.. that normally reside in a type are called  as type members.

In C# there are 5 different access modifiers:
1.Private
2.Protected
3.Internal
4. Protected Internal
5. Public

Type members can have all the access modifiers, where as types can have only 2 (internal , public) of the 5 access modifiers

Note: Using regions you can expand and collapse sections of your code either manually, or using visual studio Edit>Outling > Toggle All Outlining


using System;
using System.IO;

namespace ConsoleApplication4
{
    class Program
    {
        public static void Main()
        {

        }

    }

    public class Customer
    { 
        #region fields
        private int _id;
        private string _firstName;
        private string _lastName;
        #endregion

        #region properties
        public int Id
        {
            get { return _id; }
            set { _id = value; }

        }
        public string FirstName
        {
            get { return _firstName; }
            set { _firstName = value; }

        }
        public string LastName
        {
            get { return _lastName;}
            set { _lastName = value; }
        }
        #endregion

        #region methods
        public string GetFullName()
        {
            return this.FirstName + " " + this.LastName;
        }
        #endregion


    }
}

ENUMS IN C#

WHY ENUMS


Enums are strongly typed constants

If a program uses set of integral numbers, consider replacing them with enums. otherwise the program becomes less
 > Readable
 > Maintainable

-----------------------------------------------------------------------------------------------------------------------

using System;
using System.IO;

namespace ConsoleApplication4
{
    class Program
    {
        public static void Main()
        {
            Customer[] customers = new Customer[3];

            customers[0] = new Customer
            {
                Name = "Malla",
                Gender = 1
            };
            customers[1] = new Customer
            {
                Name = "mary",
                Gender = 2

            };
            customers[2] = new Customer
            {
                Name = "hyyjjj",
                Gender = 0
            };

            foreach (Customer customer in customers)
            {
                Console.WriteLine("Name = {0} && Gender = {1}", customer.Name, GetGender(customer.Gender));
                Console.ReadLine();
            }

        }

        public static string GetGender(int gender)
        {
            switch(gender)
            {
//      INTEGRAL NUMBERS BESIDE CASES SHOULD BE REPLACES WITH ENUMS TO //BETTER READABLE
                case 0:
                    return "Unknown";
                case 1:
                    return "Male";
                case 2: 
                    return "Female";
                default:
                    return "Invalid data detected";
            }
    }
        //0 Unknown
        //1  Male
        //2 Female

        public class Customer
        {
            public string Name { get; set; }
            public int Gender { get; set; }
        }
    }
}
------------------------------------------------------------------------------------------------------------------------

USE ENUMS FOR THE ABOVE PROGRAM MORE READABLE


using System;
using System.IO;

namespace ConsoleApplication4
{
    class Program
    {
        public static void Main()
        {
            Customer[] customers = new Customer[3];

            customers[0] = new Customer
            {
                Name = "Malla",
                Gender = Gender.Male
            };
            customers[1] = new Customer
            {
                Name = "mary",
                Gender = Gender.Female

            };
            customers[2] = new Customer
            {
                Name = "hyyjjj",
                Gender = Gender.Unknown
            };

            foreach (Customer customer in customers)
            {
                Console.WriteLine("Name = {0} && Gender = {1}", customer.Name, GetGender(customer.Gender));
                Console.ReadLine();
            }

        }

        public static string GetGender(Gender gender)
        {
            switch(gender)
            {
                case Gender.Unknown:
                    return "Unknown";
                case Gender.Male:
                    return "Male";
                case Gender.Female: 
                    return "Female";
                default:
                    return "Invalid data detected";
            }
    }
        //0 Unknown
        //1  Male
        //2 Female
        public enum Gender
        {
            Unknown,
            Male,
            Female
        };

        public class Customer
        {
            public string Name { get; set; }
            public Gender Gender { get; set; }
        }
    }
}


 -------------------------------------------------------------------------------------------------------------------------
ENUMS USAGE


If a program uses set of integral numbers, consider replacing them with enums. otherwise the program becomes less
 > Readable
 > Maintainable

1.Enums are enumerations
2.Enums are strongly typed constants, Hence, an explicit cast is needed to convert from enum type to an integral type and vice versa.Also an enum of one type cannot be implicitly assigned to an enum of another type even though the underlying value of their members are the same.
3. The default underlying type of an enum is int.
4.The default value for firt element is zero and gets incremently by 1.
5 it is possible to customize the underlying type and values.
6. Enums are value types.

7. Enum keyword (all small letters) is used to create enumerations. where as Enum class, contains staticGetValues() and GetNames() methods which can be used to list Enum underlying type values and Names.

Enum(with capital Eis a class)

enum (with small e is to create enumerations)


using System;
using System.IO;

namespace ConsoleApplication4
{
    class Program
    {
        public static void Main()
        {
            short[] Values = (short[])Enum.GetValues(typeof(Gender));

            foreach (int value in Values)
            {
                Console.WriteLine(value);     
            }
            string[] Names = Enum.GetNames(typeof(Gender));

            foreach (string name in Names)
            {
                Console.WriteLine(name);
                Console.ReadLine();
            }
       
    }
        //0 Unknown
        //1  Male
        //2 Female
       
        public enum Gender : short
        {
            Unknown = 1,
            Male = 5,
            Female = 23
        };

        public class Customer
        {
            public string Name { get; set; }
            public Gender Gender { get; set; }
        }
    }
}

Saturday, 28 January 2017

EXCEPTION ABUSE AND HOW TO RESOLVE IN C#

Exception Handling abuse


Exceptions are unforseen errors that occur when a program is running. For example, when an application is executing a query, the database connection is lost, Exception is generally used to handle scenarios.


Using exception handling to implement program logical flow is bad and is termed as exception handling abuse.

------------------------------------------------------------------------------------------------------------------------
using System;
using System.IO;

namespace ConsoleApplication4
{
    class Program
    {
        public static void Main()
        {
            try
            {
                Console.WriteLine("Please enter Numarator");
                int Numarator = Convert.ToInt32(Console.ReadLine());

                Console.WriteLine("Please enter Denaminator");
                int Denaminator = Convert.ToInt32(Console.ReadLine());

                int Result = Numarator / Denaminator;

                Console.WriteLine("Result = {0}", Result);
                Console.ReadLine();
            }
            catch(FormatException)
            {
                Console.WriteLine("Please enter valid number ");
                Console.ReadLine();
            }
            catch(OverflowException)
            {
                Console.WriteLine("Only numbers beteen {0} && {1}", Int32.MinValue, Int32.MaxValue);
                Console.ReadLine();
            }
            catch(DivideByZeroException)
            {
                Console.WriteLine("Denominator cannot be Zero");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

        }
    }
}
=======================================================================

EXCEPTION HANDLING ABUSE RESOLVED..

CORRECT WAY TO USE EXCEPTION HANDLING AFTER VALIDATION


using System;
using System.IO;

namespace ConsoleApplication4
{
    class Program
    {
        public static void Main()
        {
            try
            {
                Console.WriteLine("Please enter Numarator");
                int Numarator;
                bool IsNumaratorConversionSuccessful = Int32.TryParse((Console.ReadLine()), out Numarator);

                if (IsNumaratorConversionSuccessful)
                {
                    Console.WriteLine("Please enter Denominator");
                    int Denominator;
                    bool IsDenominatorConversionSuccessful = Int32.TryParse((Console.ReadLine()), out Denominator);

                    if (IsDenominatorConversionSuccessful && Denominator != 0)
                    {
                        int Result = Numarator / Denominator;

                        Console.WriteLine("Result = {0}", Result);
                        Console.ReadLine();
                    }
                    else
                    {
                        if (Denominator == 0)
                        {
                            Console.WriteLine("Denominator cannot be Zero");
                            Console.ReadLine();
                        }
                        else
                        {
                            Console.WriteLine("Denominator should be valid number between {0} && {1}", Int32.MinValue, Int32.MaxValue);
                            Console.ReadLine();
                        }
                    }

                }
                else
                {
                    Console.WriteLine("Numarator should be valid number between {0} && {1}", Int32.MinValue, Int32.MaxValue);
                    Console.ReadLine();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.ReadLine();
            }
        }
    }
}



INNER EXCEPTIONS IN C#

INNER EXCEPTION


The InnerException property returns the Exception instance that caused the current exception.

To retain the original exception pass it as a parameter to the constructor, of the current exception.

Always check if inner exception is not null before accessing any property of the inner exception object, else, you may get Null Reference Exception.

To get the type of InnerException use GetType() method.
--------------------------------------------------------------------------------------------------------------------------

using System;
using System.IO;

namespace ConsoleApplication4
{
    class Program
    {
        public static void Main()
        {
            try
            {
                try
                {
                    Console.WriteLine("Please enter first number ");
                    int FN = Convert.ToInt32(Console.ReadLine());
                    Console.WriteLine("Please enter second number ");
                    int SN = Convert.ToInt32(Console.ReadLine());

                    int Result = FN / SN;
                    Console.WriteLine("Result = {0}", Result);
                    Console.ReadLine();
                }

                catch (Exception ex)
                {
                    String filePath = @"C:\some\log1.txt";
                    if (File.Exists(filePath))
                    {
                        StreamWriter sw = new StreamWriter(filePath);
                        sw.Write(ex.GetType().Name);
                        sw.Close();
                        Console.WriteLine("Please try later, there is a problem");
                        Console.ReadLine();
                    }
                    else
                    {
                        throw new FileNotFoundException(filePath + "is not present", ex);
                    }
                }

            }
            catch(Exception exception)
            {
                Console.WriteLine("Current Exception ={0} ", exception.GetType().Name);
                if (exception.InnerException != null)
                {
                    Console.WriteLine("Inner Exception = {0} ", exception.InnerException.GetType().Name);
                    Console.ReadLine();
                }
            }
        }
    }

}

EXCEPTION HANDLING IN C#

EXCEPTION HANDLING IN C#


using System;
using System.IO;

namespace ConsoleApplication4
{

    class Program
    {


        public static void Main()
        {
            try
            {
                StreamReader streamreader = new StreamReader(@"C:\Users\mallareddy\OneDrive\Documents1\Data.txt");
                Console.WriteLine(streamreader.ReadToEnd());
                streamreader.Close();
                Console.ReadLine();
            }

            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.ReadLine();
            }
                // More specific exception at first, if you place general exception  first then it throughs exception as 
                // a previous catch clause already catches all exceptions of this or of a super type('System.Exception')
            catch (FileNotFoundException ex)
            {
                //Console.WriteLine(ex.Message);
                //Console.WriteLine();
                //Console.WriteLine();
                //Console.WriteLine(ex.StackTrace);
                Console.WriteLine("Please check if the file exist = {0}", ex.FileName);
                Console.ReadLine();
            }
                // General exception at the bottom 
           
        }       
       
    }
}
===================================================================

CLASS HIERARCHY EXCEPTIONS
TRY , CATCH, CATCH..


using System;
using System.IO;

namespace ConsoleApplication4
{

    class Program
    {


        public static void Main()
        {
            try
            {
                StreamReader streamreader = new StreamReader(@"C:\Users\mallareddy\OneDrive\Documents1\Data.txt");
                Console.WriteLine(streamreader.ReadToEnd());
                streamreader.Close();
                Console.ReadLine();
            }

           
            catch (FileNotFoundException ex)
            {
                //Console.WriteLine(ex.Message);
                //Console.WriteLine();
                //Console.WriteLine();
                //Console.WriteLine(ex.StackTrace);
                Console.WriteLine("Please check if the file exist = {0}", ex.FileName);
                Console.ReadLine();
            }
                // General exception at the bottom 
            catch (Exception ex)
            {
                ConsolCe.WriteLine(ex.Message);
                Console.ReadLine();
            }
            // More specific exception at first, if you place general exception  first then it throughs exception as 
            // a previous catch clause already catches all exceptions of this or of a super type('System.Exception')
        }       
       
    }
}
=======================================================================

COMPLETE EXCEPTION HANDLING



using System;
using System.IO;

namespace ConsoleApplication4
{

    class Program
    {

       
        public static void Main()
        {
            StreamReader streamreader = null;
            try
            {
                streamreader = new StreamReader(@"C:\Users\mallareddy\OneDrive\Documents\Data.txt");
                Console.WriteLine(streamreader.ReadToEnd());

                Console.ReadLine();
            }


            catch (FileNotFoundException ex)
            {
                //Console.WriteLine(ex.Message);
                //Console.WriteLine();
                //Console.WriteLine();
                //Console.WriteLine(ex.StackTrace);
                Console.WriteLine("Please check if the file exist = {0}", ex.FileName);
                Console.ReadLine();
            }
            // General exception at the bottom 
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.ReadLine();
            }
            // More specific exception at first, if you place general exception  first then it throughs exception as 
            // a previous catch clause already catches all exceptions of this or of a super type('System.Exception')

            finally
            {
                if (streamreader != null)
                {
                    streamreader.Close();
                    Console.WriteLine("Finally Block");
                    Console.ReadLine();
                }
            }
        }

    }


}
}




















Thursday, 26 January 2017

DELEGATES IN C#


What is a delegate?


A delegate is a type safe function pointer. That is, it holds a reference (pointer) to a function.

The signature of the delegate must match the signature of the function,the delegate points to, otherwise you get a complier error. This is the reason delegates are called as type safe function pointers.

A Delegate is similar to a class. You can create an instance of it, and when you do so, you pass in the funstion name as a parameter to the delegate constructor, and it is to this function the delegate will point to.

Tip to remember delegate syntax: Delegates syntax look very much similar to a method with a delegate keyword. 

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

namespace ConsoleApplication4
{
    class Program
    {
        public delegate void HelloFunctionDelegate(string Message);

    
        public static void Main()
        {

            HelloFunctionDelegate del = new HelloFunctionDelegate(Hello);
            del("This is the delegate function");
           // A delegate is a type safe function pointer
        }

        public static void Hello(string strMessage)
        {
            Console.WriteLine(strMessage);
            Console.ReadLine();
        }
    }
}
=======================================================================
DEMO DEMO ON DELEGATE

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

namespace ConsoleApplication4
{
    class Program
    { 
        public static void Main()
        {

            List<Employee> empList = new List<Employee>();
            empList.Add(new Employee() { ID = 101, Name = "Malla", Salary = 5000, Experience = 5 });
            empList.Add(new Employee() { ID = 102, Name = "Reddy", Salary = 4000, Experience = 4 });
            empList.Add(new Employee() { ID = 103, Name = "Mathew", Salary = 3000, Experience = 3 });
            empList.Add(new Employee() { ID = 104, Name = "Sam", Salary = 6000, Experience = 7 });

            Employee.PromoteEmployee(empList);
            Console.ReadLine();
        } 
    }

    class Employee
    {
        public int ID{get;set;}
        public string Name { get; set; }
        public int Salary { get; set; }
        public int Experience { get; set; }

        public static void PromoteEmployee(List<Employee> employeeList)
        {
            foreach (Employee employee in employeeList)
            {
                if (employee.Experience >= 5)
                {
                    Console.WriteLine(employee.Name + " Promoted");
                    Console.ReadLine();
                }
            }
        }
    }
}


=======================================================================
USING DELEGATE THE ABOVE EXAMPLE IS MODIFIED 


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

namespace ConsoleApplication4
{
    class Program
    { 
        public static void Main()
        {

            List<Employee> empList = new List<Employee>();
            empList.Add(new Employee() { ID = 101, Name = "Malla", Salary = 5000, Experience = 5 });
            empList.Add(new Employee() { ID = 102, Name = "Reddy", Salary = 4000, Experience = 4 });
            empList.Add(new Employee() { ID = 103, Name = "Mathew", Salary = 3000, Experience = 3 });
            empList.Add(new Employee() { ID = 104, Name = "Sam", Salary = 6000, Experience = 7 });


            //IsPromotable ispromotable = new IsPromotable(Promote);

            //Employee.PromoteEmployee(empList, ispromotable);
                                             // Lamda expressions
            Employee.PromoteEmployee(empList,emp =>emp.Experience >=5);
            Console.ReadLine();
        } 
           //******** below commented section is to write shortcut code using lamda expression.*****//   
        //public static bool Promote(Employee emp)
        //{
        //    if (emp.Experience >= 5)
        //    {
        //        return true;

        //    }
        //    else
        //    {
        //        return false;
        //    }
        //}
    }
      delegate bool IsPromotable(Employee empl);

    class Employee
    {
        public int ID{get;set;}
        public string Name { get; set; }
        public int Salary { get; set; }
        public int Experience { get; set; }

        public static void PromoteEmployee(List<Employee> employeeList,IsPromotable isEligibleToPromote)
        {
            foreach (Employee employee in employeeList)
            {
                if (isEligibleToPromote(employee))
                {
                    Console.WriteLine(employee.Name + " Promoted");
                    Console.ReadLine();
                }
            }
        }
    }
}


===================================================================
MULTICAST DELEGATES

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

namespace ConsoleApplication4
{

    public delegate void SampleDelegate();
    class Program
    { 

        
        public static void Main()
        {

            //SampleDelegate del1, del2, del3, del4;
            //del1 = new SampleDelegate(SampleMethodOne);
            //del2 = new SampleDelegate(SampleMethodTwo);
            //del3 = new SampleDelegate(SampleMethodThree);
            //del4 = del1 + del2 + del3;
            //del4();
            //Console.ReadLine();
            SampleDelegate del = new SampleDelegate(SampleMethodOne);
            del += SampleMethodTwo;
            del += SampleMethodThree;
            del();
            Console.ReadLine();
        }


        public static void SampleMethodOne()
        {
            Console.WriteLine("Samplemethodone Invoked");
            Console.ReadLine();
        }
        public static void SampleMethodTwo()
        {
            Console.WriteLine("SamplemethodTwo Invoked");
            Console.ReadLine();
        }
        public static void SampleMethodThree()
        {
            Console.WriteLine("SamplemethodThree Invoked");
            Console.ReadLine();

        }
       
    }
}


=====================================================================

Multicast delegates


A multicast delegate is a delegate that has references to more than one function.when you invoke a multicast delegate, all the functions the delegate is pointing to, are invoked.

There are 2 approaches to create a multicast delegate . depending on the approach you use
+ or += to register a method with the delegate
- or -= to un-register a method with the delegate.

Note: A multicast delegate, invokes the methods in the invocation list, in the same order in which they are added.

If the delegate has a return type other than void and if the delegate is a multicast delegate,
only the value of the last invoked method will be returned. Along the same lines, if the delegate has an out paraameters, the value of the output parameters, will be the value assigned by the last method.

Common interview question- where do you use multicast delegates?
Multicast delegate makes implementation of observer design patterns very simple. Observer pattern is also called as publish/subscribe pattern.



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

namespace ConsoleApplication4
{

    public delegate int SampleDelegate();
    class Program
    { 

        
        public static void Main()
        {

            //SampleDelegate del1, del2, del3, del4;
            //del1 = new SampleDelegate(SampleMethodOne);
            //del2 = new SampleDelegate(SampleMethodTwo);
            //del3 = new SampleDelegate(SampleMethodThree);
            //del4 = del1 + del2 + del3;
            //del4();
            //Console.ReadLine();
            SampleDelegate del = new SampleDelegate(SampleMethodOne);
            del += SampleMethodTwo;
            int DelegateReturnedValue = del();
            Console.WriteLine("DelegateReturnedValue= {0}", DelegateReturnedValue);
           
            Console.ReadLine();
        }


        public static int SampleMethodOne()
        {
            return 1;
            Console.ReadLine();
        }
        public static int SampleMethodTwo()
        {
            return 2;
            Console.ReadLine();
        }
       
       
    }
}











MULITPLE CLASS INHERITANCE USING MULTIPLE INTERFACES

MULITPLE CLASS INHERITANCE USING MULTIPLE INTERFACES


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

namespace ConsoleApplication4
{
    interface IA
    {
        void AMethod();
    }
    class A : IA
    {
        public void AMethod()
        {
            Console.WriteLine("A");
        }
    }
    interface IB
    {
        void BMethod();
    }
    class B : IB
    {
        public void BMethod()
        {
            Console.WriteLine("B");
        }
    }
    class AB : IA,IB
    {
        A a = new A();
        B b = new B();
        public void AMethod()
        {
            a.AMethod();
        }
        public void BMethod()
        {
            b.BMethod();
        }
    }
    
    class Program
    {
        public static void Main()
        {
            AB ab = new AB();
            ab.AMethod();
            ab.BMethod();
            Console.ReadLine();
        }
    }
}

MULTIPLE CLASS INHERITANCE PROBLEM IN C#

MULTIPLE CLASS INHERITANCE PROBLEM IN C#


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

namespace ConsoleApplication4
{

    /// <summary>
    /// 
    /// PROBELMS WITH MULTIPLE CLASS INHERITANCE
    /// </summary>
    class A
    {
        public virtual void print()
        {
            Console.WriteLine("class A implemented");
        }

    }
    class B : A
    {

        public override void print()
        {
            Console.WriteLine("Class B overriding print() method");
        }

    }

    class C : A
    {
        public override void print()
        {
            Console.WriteLine("Class C overriding print() method");
        }
    }
    class D : B, C
    {


    }
    class Program
    {
        public static void Main()
        {
            D d = new D();
            d.print(); // AMBIGUITY HERE, WHICH METHOD WILL IT EXECUTE, SO A DIAMOND PROBLEM.
        }
    }
}

ABSTRACT CLASSES IN C#

ABSTRACT CLASSES IN C#

Abstract classes

The abstract keyword is used to create abstract classes

An abstract class is incomplete and hence cannot be instantiated

An abstract class can only be used as base class

An abstract class can not be sealed

An abstract class may contain abstract members(methods, properties,indexers,and events) but not mandatory.

A non- abstract class derived from an abstract class must provide implementations for all inherited abstract members.

If a class inherits an abstract class, there are 2 options available for that class

Option 1: Provide Implementation for all the abstract members inherited from the base abstract class.

Option 2: If the class does not wish to provide Implementation for all the abstract members inherited from the abstract class, then the class has to be marked as abstract.

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

namespace ConsoleApplication4
{
    public abstract class Customer
    {
        public abstract void print();

    }

    public class program : Customer
    {
        public override void print()
        {
            Console.WriteLine("Hello abstract method");
        }
        public static void Main()
        {
            program p = new program();
            p.print();
            Console.ReadLine();
        }
    }
}


INTERFACES IN C#

INTERFACE IN C#


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

namespace ConsoleApplication4
{
    interface  ICustomer1
    {
        void print1();
        
    }

    interface ICustomer2 : ICustomer1
    {
        void print2();

    }
  public  class Customer : ICustomer2
    {
        public void print1()
        {
            Console.WriteLine("INTERFACE METHOD IMPELMENTED");
            Console.ReadLine();
        }

        public void print2()
        {
            Console.WriteLine("INTERFACE I2METHOD IS IMPLEMENTED TOO");
            Console.ReadLine();
        }
    }
        

}
        public class Program 
        {
            static void Main()
            {
                Customer C1 = new Customer();
                C1.print1();
                C1.print2();
                Console.ReadLine();
            }       
}


===================================================================

EXPLICIT INTERFACE IMPLEMENTATION


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

namespace ConsoleApplication4
{
    interface I1
    {
        void INTERFACEMETHOD();

    }
    interface I2 : I1
    {
        void INTERFACEMETHOD();

    }
    public class Program : I1,I2
    {
//  PUBLIC VOID INTERFACEMETHOD()   DEFAULT INTERFACE METHOD
        void I1.INTERFACEMETHOD()
        {
            Console.WriteLine("INTERFACE I1");
            Console.ReadLine();
        }
        void I2.INTERFACEMETHOD()
        {
            Console.WriteLine("INTERFACE I2");
            Console.ReadLine();
        }

        static void Main()
        {
            Program P = new Program();
           // P.INTERFACEMETHOD(); DEFAULT INTERFACE CALLING
            ((I1)P).INTERFACEMETHOD();     
            ((I2)P).INTERFACEMETHOD();   // EXPLICIT INTERFACE METHOD CALLING
            Console.ReadLine();
        }

    }
}





STRUCTS IN C#


STRUCTS


Just like classes structs can have
1. Private Fields
2. Public Properties
3. Constructors
4.Methods


Object initializer syntax, intriduced in c# 3.0 can be used to initialize either a structor or a class
Note: There are several differences between classes and structs which we will be looking at in a later session.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ConsoleApplication4;
namespace ConsoleApplication4
{
    public struct Customer
    {
        private int _id;
        private string _Name;
        public string Name
        {
            get { return _Name; }
            set { _Name = value; }
        }
        public int ID
        {
            get { return this._id; }
            set { this._id = value; }
        }
        public Customer(int Id, string Name)
        {
            this._id = Id;
            this._Name = Name;
        }
        public void PrintDetails()
        {
            Console.WriteLine("id= {0}, name = {1}", this._id, this._Name);
        }
     
    }
        public class Program
        {
            static void Main()
            {
                Customer C1 = new Customer(101, "Mallareddy");
                C1.PrintDetails();
                Console.ReadLine();
                Customer C2 = new Customer();
                C2.ID = 102;
                C2.Name = "Mitali";
                C2.PrintDetails();
                Console.ReadLine();
                Customer C3 = new Customer
                {
                    ID = 103,
                    Name = "AYAN"
                 
                };
                C3.PrintDetails();
                Console.ReadLine();
            }

        }
    }


=====================================================================

A struct is a value type where as a class is a reference type.
All the differences that are applicable to value types and reference types are also applicable to classes and structs.


Structs are stored on stack, where as classes are stored on the heap.
Value types hold their value in memory where they are declared, but reference types hold a reference to an object in memory.


Value types are destroyed immediately after the scope is lost, where as for reference types only the reference variable is destroyed after the scope is lost. the object is later destroyed by garbage collector. (We will talk about this in the garbage collection session).


When you copy a struct into another struct ,  a new copy of that struct gets created and modification on one struct will not affect the values contained by the other struct.


When you copy a class into another class, we only get a copy of the reference variable. Both the reference variable point to the same object on the heap. so , operations on one variable will affect the values contained by the other reference variable.  

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

namespace ConsoleApplication4

{
    public class  Customer
    {
        public int ID{get; set;}
        public string Name{get;set;}
    }
        
}
        public class Program
        {
            static void Main()
            {
                int i = 0;
                
                if(i==10)
                {
                  int j = 20;
                    Customer C1 = new Customer();
                    C1.ID = 101;
                    C1.Name = "Mark";
                }
                Console.WriteLine("Hello");
                Console.ReadLine();
            
            }       
}

=======================

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

namespace ConsoleApplication4

{
    public class  Customer
    {
        public int ID{get; set;}
        public string Name{get;set;}
    }
        
}
        public class Program
        {
            static void Main()
            {
                int i = 10;
                int j = i;
                j = j + 1;

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


                Customer C1 = new Customer();

                C1.ID = 101;
                C1.Name = "malla";
                                                  // when we copy reference the memory is mapped to same location//
                Customer C2 = C1;
                C2.Name = "mark";
                Console.WriteLine("C1.Name = {0}, C2.Name = {1}", C1.Name, C2.Name);
                Console.ReadLine();              
                        }
}

> "classes" can have destructors but "struct" can not have destructors.


Classes vs Structs


> Structs can't have destructors, but classes can have destructors


> Structs cannot have explicit parameter less constructors where as a class can.


> Struct can't inherit from another class where as a class can, Both structs and classes can         inherit from an interface.



>Example of structs in the .NET Framework -int(System.int32), double(System.Double) etc..