Powered by Blogger.

Knowledge Dojo

    • Home
    • JavaScript
    • _Concepts
    • Unity
    • C#
    • About
    • Contact

    !!!!!In C#, we have been using collections like IEnumerable, ICollection, IList interchangeably but do you really know what is it that separates each other.

    They all have specific characteristics that differentiate them and makes them adaptable to certain scenarios.

    All of the above holds a list maintaining the order of items but which one should we use and in which case, let's see.

    IEnumerable

    Namespace: System.Collections

    An IEnumerable is a list or a container which can hold some items. You can iterate through each element in the IEnumerable. You can not edit the items like adding, deleting, updating, etc. instead you just use a container to contain a list of items. It is the most basic type of list container.

    All you get in an IEnumerable is an enumerator that helps in iterating over the elements. An IEnumerable does not hold even the count of the items in the list, instead, you have to iterate over the elements to get the count of items.

    An IEnumerable supports filtering elements using where clause.

    ICollection

    Namespace: System.Collections

    ICollection is another type of collection, which derives from IEnumerable and extends its functionality to add, remove, update element in the list. ICollection also holds the count of elements in it and we do not need to iterate over all elements to get the total number of elements. 

    The count of total items can be retrieved in O(1) time.

    ICollection supports enumerating over the elements, filtering elements, adding new elements, deleting existing elements, updating existing elements and getting the count of available items on the list.

    IList

    Namespace: System.Collections

    IList extends ICollection. An IList can perform all operations combined from IEnumerable and ICollection, and some more operations like inserting or removing an element in the middle of a list.

    You can use a foreach loop or a for loop to iterate over the elements.

    IQueryable

    Namespace: System.Linq

    IQueryable extends ICollection. An IQueryable generates a LINQ to SQL expression that is executed over the database layer. Instead of the generating a Func<T, bool> like the ones above, IQueryable generates an expression tree and gives Expression<Func<T, bool>> that is executed over the database layer to get data set.

    DI (Dependency Injection) Container/IoC (Inversion of Control) Container

    DI Container or IoC container are the terms that are used interchangeably but have the same meaning.

    What is it?

    Consider using the following code to instantiate a class with multiple services:
    var instance = new Class1(new Service1(), new Service2(new Service3()), new Service4());


    nesting of dependencies in dependency injection


    Will you prefer using the code as the one above?
    The answer would be NO as this is really fussy and confusing code to find out what is actually going on here.

    To solve the above problem, we use the DI Container, that helps us simplify the above code to human readable and understandable extent.

    Definition

    A DI Container is a framework that automatically creates the objects and injects the dependencies when required.
    To simplify the fuss related to creating instances( sometimes nested ) and injecting them, we use the DI container.

    With a DI Container used, the code will look something like:
    var instance = container.Resolve<Class1>();

    But how to implement this?

    This can be well explained with this detailed example below.
    There are a lot of DI Container frameworks in the market like Unity, Castle Windsor, StructureMap, Ninject etc. I will be using the Unity DI Container for this example.

    Installing Unity DI Container

    We will install Unity DI Framework with the Unity's NuGet package. To install the NuGet package, follow these steps:
    Step 1: Right-click the project name in the solution explorer and Click on "Manage NuGet Packages"

    Step 2: With the browse option selected, search for "Unity" and click on the download icon against it. Click Ok if you are prompted for installation.


    Implementing the Unity DI Container
    Consider a class Class1 such that it needs a dependency Dependency1. The class Dependency1 needs another dependency class Dependency2.
    class Class1 
    {
        IDependency1 dependency1;
        public Class1(IDependency1 dependency)
        {
            dependency1 = dependency;
        }
    }
    
    class Dependency1 
    {
        IDependency2 dependency12
    
        public Dependency1(IDependency2 dependency)
        {
            dependency2 = dependency;
        }
    }
    
    So the class object instantiation would look like:
    Class1 instance = new Class1(new Dependency1(new Dependency2()));
    Thus creating a nested dependency in the instantiation of the Class1 object.
    But this object instantiation looks a bit confusing and we need to sort this out.

    Implementing the DI Container

    Let's start using Unity DI Container.
    In our C# console application, first we need to import the Unity Namespace by adding a following reference to the import statements:
    using Unity;

    Now we need to register the types that will be injected whenever we need a service/dependency like whenever we need a IDependency1 service, the DI container will automatically inject the Dependency1 class instance.

    The syntax for registering the mapping between the type of object to be received and the actually needed object is:
    var container = new UnityContainer();
    
    container.RegisterType<IClass1, Class1>();
    container.RegisterType<IDependency1, Dependency1>();
    container.RegisterType<IDependency2, Dependency2>();

    All statements look similar. So what do these statements mean?
    Let's look at it.

    The format is something like:
    container.RegisterType<RequiredType, SuppliedType>();
    i.e. whenever an object of a IClass1 is required, the instance of Class1 object will be automatically passed by the DI Container.

    Now instead of instantiating Class1 object as:
    var instance = new Class1( new Dependency1( new Dependency2() ) );

    With the use of DI Container, I will simply instantiate Class1 object as:
    var instance = container.Resolve<IClass1>();

    The Container instance provides a resolve method that will automatically resolve the dependency and will supply the instance of Class1. Since Class1 further have IDependency1 needed, the DI Container will automatically pass a new instance of Dependency1 and so on.

    The final Code for the C# Console application will look like this:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Unity;
    
    namespace ConsoleApp1
    {
        class Class1 : IClass1
        {
            IDependency1 dependency1;
    
            public Class1(IDependency1 dependency)
            {
                dependency1 = dependency;
            }
        }
    
        class Dependency1 : IDependency1
        {
            IDependency2 dependency2;
    
            public Dependency1(IDependency2 dependency)
            {
                dependency2 = dependency;
            }
        }
    
        class Dependency2 : IDependency2
        {
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                var container = new UnityContainer();
    
                container.RegisterType<IClass1, Class1>();
                container.RegisterType<IDependency1, Dependency1>();
                container.RegisterType<IDependency2, Dependency2>();
    
                var instance = container.Resolve<IClass1>();
    
                Console.ReadKey();
            }
        }
    }
    If you have been developing applications with C#, then you must have encountered a concept named delegates. Delegates in C# can be referred as a pointer to methods.
    Instead of calling a method directly with its name, we call the method with its reference. They can be used for events and callbacks.

    A Direct method call would look like:

    FindSquare(5) // to get the square of a number
    or, Factorial(5); //to find factorial of a number
    

    how a c# function call works


    A delegate call (pseudocode) would look something like:


    delegate numberChanger = FindSquare->Reference


    where numberChanger is the name is the delegate that holds the reference to the function.



    Implementing a simple numberChanger delegate

    Consider the following method:
    int FindSquare( int number )
    {
        return (number*number);
    }
    

    To create a delegate, we need to create a new delegate object using the new operator.

    The syntax for delegate declaration is:

    delegate <return-type> <delegate-name> (<parameters>)

    The actual implementation will look like:

    Step 1: Declaring the delegate
    delegate int ModifyNumber(int number);

    Step 2: Instantiating the delegate 
    var numberModifier = new ModifyNumber(FindSquare);

    Note that the parameter is the name of the method that we want to reference with the delegate.

    Step 3: Using the delegate
    int number = numberModifier(5);

    class Program {
     delegate int ModifyNumber(int number);
    
     static int FindSquare(int number)
     {
      return (number * number);
     }
    
     static void Main(string[] args)
     {
      var numberModifier = new ModifyNumber(FindSquare);
      int temp = numberModifier(5);
      Console.WriteLine(temp);
     }
    }

    C# Program
    delegate simple example to modify a number

    Output
     25                                      

    Delegate Chaining

    The benefit of using delegate is that it allows chaining of method calls in a single delegate reference.

    like, delegate "print" can point to two different methods
    1. printing the output to console
    2. ‎saving the output in a log file

    But how? Let's see this in action.


    Consider the following two methods:

    static void WriteToConsole(string name)
    {
        Console.WriteLine("Name is : " + name);
    }
    
    static void WriteToFile(string name)
    {
        //Code to write name to file
        Console.WriteLine("Written name to file : " + name);
    }

    Here, we will be creating a delegate such that calling the delegate will invoke these two methods one by one.

    Step 1: Declaring the delegate (Same as we did before)

    delegate void NameWriter(string str);

    Step 2: Creating new delegate objects pointing to these methods.

    var writeToConsole = new NameWriter(WriteToConsole);
    var writeToFile = new NameWriter(WriteToFile);
    

    Step 3: Create empty delegate variable.
    We will use this delegate to call the chained methods.

    NameWriter nameWriter;

    Step 4: Setting nameWriter reference to the first method.

    nameWriter = writeToConsole;
    Notice, how we assigned the variable writeToConsole to the nameWriter variable.

    Step 5: Chaining/Appending references of other methods to the delegate.

    New references are chained to a delegate in the following manner:

    nameWriter += writeToFile;
    Here we appended the writeToFile reference to the nameWriter.

    Step 6: Using the nameWriter delegate.

    nameWriter("Kunal");

    The following output will be produced when executing the above code:

    C# Program
    class Program
    {
     static void WriteToConsole(string name)
     {
      Console.WriteLine("Name is : " + name);
     }
    
     static void WriteToFile(string name)
     {
     //Code to write name to file
      Console.WriteLine("Written name to file : " + name);
     }
     
     /************* Step 1 *************/
     delegate void NameWriter(string str);
     /**********************************/
     
     static void Main(string[] args)
     {
      /************* Step 2 *************/
      var writeToConsole = new NameWriter(WriteToConsole);
      var writeToFile = new NameWriter(WriteToFile);
      /**********************************/
     
      /************* Step 3 *************/
      NameWriter nameWriter;
      /**********************************/
     
      /************* Step 4 *************/
      //appending functionalities to write name
      nameWriter = writeToConsole;
      /**********************************/
     
      /************* Step 5 *************/
      nameWriter += writeToFile;
      /**********************************/
     
      /************* Step 6 *************/
      //write names to console and to file in this single statement
      nameWriter("Kunal");
      /**********************************/
      
      //wait for keypress to exit
      Console.ReadKey();
     }
    }
    

    Output:


    And done. You just appended multiple references to a single delegate and calling this delegate will call all of the chained methods one by one.
    Older
    ARTICLES

    IEnumerable vs ICollection vs IList vs IQueryable in C#

    Popular Posts

    • Object Creation Patterns in Javascript
    • IEnumerable vs ICollection vs IList vs IQueryable in C#

    Created with by BeautyTemplates

    Back to top