Tuesday, 1 June 2021

Software Design Principles

 Introduction

In software design, there are many principles and practices which are followed. Few of them are listed below.

SOLID:    

In Object Oriented Programming, SOLID is mnemonic acronym for 5 design principles to make software design more understandable, extensible and maintainable. 

  Single Responsibility Principle: There should never be more than one reason for a class to change. In other words, every class should have only one responsibility. This means for other responsibility create separate class.

Open Closed Principle: Software entities (class, function, module etc.) should be open for extension but closed for modification. Using Inheritance and polymorphism we can achieve this.

Liskov Substitution Principle: Object of a superclass should be replaceable with object of its subclasses without breaking the functionality.

Interface Segregation Principle: No client should be forced to depend on a method if does not use. This means breaks a large interface into smaller and more specific interfaces so that clients will only have to know about the methods that are of interest to them.

Dependency Inversion PrincipleThe principle states

  1. High-level modules should not depend on low-level modules. Both should depend on abstractions (e.g., interfaces).
  2. Abstractions should not depend on details. Details (concrete implementations) should depend on abstractions.

IOC or Inversion of Control Principles
    also known as the Hollywood Principle - "Don't call us, we'll call you"

   IoC inverts the flow of control as compared to traditional control flow. In IoC, custom-written portions of a computer program receive the flow of control from a generic framework. 

A software architecture with this design inverts control as compared to traditional procedural programming: in traditional programming, the custom code that expresses the purpose of the program calls into reusable libraries to take care of generic tasks, but with inversion of control, it is the framework that calls into the custom, or task-specific, code.

Inversion of Control is a key part of what makes a framework different to a library. A library is essentially a set of functions that you can call, these days usually organized into classes. Each call does some work and returns control to the client.

 Dependency Injection: When an object of class X uses specific functionality of object of class Y to perform some action, it is called X depends on Y or X has a dependency on Y. 

Now definition of DI, "Process of creating and passing an object for some other object, it depends on is called Dependency Injection". It is a type of IOC principle.

Object who receives the reference is client. Object which is injected is service and injector, which is responsible for constructing the services and injecting them into the client.

KISS: Keep it simple stupid. The KISS principle states that most systems work best if they are kept simple rather than made complicated; therefore, simplicity should be a key goal in design, and unnecessary complexity should be avoided.

Law of Demeter: Don't talk to stranger. There should well defined interface or contract to talk to outside the library, framework etc. It should talk to friends(inside classes of module) not strangers (outside library, framework etc.)


 

Monday, 31 May 2021

Command Design Pattern in C#

    

 Introduction

    Command design pattern encapsulates request as an object which has all the information needed to perform an action or invoke a method or trigger an event at later time. It supports undoable action.

It is a behavior design pattern.

It  deals with below problems

1. Decouples the request receiver and request invoker.

2. Code is extensible as new Receiver and command be added in future.

UML Diagram


Example Basic structure program

using System;

public class Program
{
public static void Main()
{
var receiver = new Receiver();
var command = new ConcreteCommand(receiver);
var invoker = new Invoker(command);
invoker.DoAction();
}
}

public class Receiver
{
public void DoOperation()
{
    Console.WriteLine("Receiver is doing the operation");
}
}

public interface ICommand
{
    void Execute();
}

public class ConcreteCommand:ICommand
{
        private Receiver _receiver;
        public ConcreteCommand(Receiver receiver)
        {
            _receiver = receiver;
        }

public void Execute()
{
    _receiver.DoOperation();
}
}

public class Invoker
{
    private ICommand _command;
    public Invoker(ICommand command)
    {
        _command = command;
    }

    public void DoAction()
    {
        _command.Execute();
    }
}

In the above code, we can see Command and Invoker have been created separately. This means 
Invoker can execute the command at a later point of time or deferred execution of command.
Command can be queued and executed.
Command can be created on one server & can be executed on another server in distributed systems.
Waiter and Chef (cook) are very good example of command pattern. As Waiter takes the order from the customer, he passed it to chef. Chef prepares the food and waiter serves it to customer.  

Real World Example
    Write to me for real world example.










Wednesday, 26 May 2021

Observer Design Pattern in C#

 Introduction

    In Observer design pattern an object 'subject' maintains the list of its dependent objects , observers, and notify them whenever there is a change in its state. It is a behavior design pattern.

It deals with below problems

- Define One to many dependency between objects without making them tightly coupled.

- Whenever there is a change in one object, other objects should get notified or updated.

UML diagram



Basic code example


public class Subject

    private IList<IObserver> _observers;
    private int state;

    // On change of this property, observers will be notified
    public int State{
        get{return state;}
        set{state = value; this.Notify();}
    }

    public Subject()
    {
        _observers = new List<IObserver>();
    }

    // Register Observer to get notification
    public void RegisterObserver(IObserver observer)
    {
        _observers.Add(observer);
    }

    //Remove Observer to stop getting notification
    public void RemoveObserver(IObserver observer)
    {
        _observers.Remove(observer);
    }

    //Send notification
    private void Notify()
{
var eventArg = new EventArg(){Value=4};
foreach(var observer in _observers)
observer.Execute(eventArg);
}
}

//Observer interface
public interface IObserver
{
    void Execute(EventArg eventarg);
}

public sealed class EventArg
{
public int Value{get;set;}
}

//Concrete ObserverA implementation of IObserver
public class ObserverA:IObserver
{
    public void Execute(EventArg eventArg)
{
Console.WriteLine($"ObserverA is execute & eventArg : {eventArg.Value}");
}
}

//Concrete ObserverB implementation of IObserver
public class ObserverB:IObserver
{
    public void Execute(EventArg eventArg)
{
Console.WriteLine($"ObserverB is execute & eventArg: {eventArg.Value}");
}
}

Program 
using System;
using System.Collections.Generic;

public class Program
{
public static void Main()
{
var subject = new Subject();
subject.RegisterObserver(new ObserverA());
subject.RegisterObserver(new ObserverB());
subject.State = 4;
}
}

//Since subject State property is changed when it is assigned with value 4, Observers get notification
//Output
    ObserverA is execute & eventArg : 4
   ObserverB is execute & eventArg: 4

In DotNet for this purpose there is Delegate & Event Type to achieve the same.

FlagsAttributes in C#

 Introduction

    In C# enum is a named integer constant. But a type can have only one enum value. FlagsAttribute is used to assign multiple enum values.

Example

using System;

public class Program

{

public static void Main()

{

var rocky = new Person("Rock", Vehicle.BMWX5);

var peter = new Person("Peter Parker", Vehicle.Highlander);

rocky.PersonInfo();

            //Output: Rock owns BMWX5

peter.PersonInfo();

            //Output: Peter Parker owns Highlander

}

}

public class Person

{

public string Name{get;set;}

public Vehicle Vehicle{get;set;}

public Person(string name, Vehicle vehicle)

{

Name = name;

Vehicle=vehicle;

}

public void PersonInfo()

{

Console.WriteLine($"{Name} owns {Vehicle}");

}

}

public enum Vehicle

{

none=0,

BMWX5=1,

LandRover=2,

LincolnAviator=4,

Highlander=8

}

In the above program, one person can own one vehicle.

What if a person owns 2 or more vehicles. In this case FlagsAttribute is useful.

using System;

public class Program

{

public static void Main()

{

                //vehicle2 is now represents 2 vehicles BMWX5 and Highlander both.

var vehicle2 = Vehicle.BMWX5|Vehicle.Highlander;

     var rocky = new Person("Rock", Vehicle.BMWX5);

var peter = new Person("Peter Parker", Vehicle.Highlander);

                // John owns vehicle2 means he has 2 vehicles.

var john = new Person("John", vehicle2);

rocky.PersonInfo();

peter.PersonInfo();

john.PersonInfo();

                //Output: John owns BMWX5, Highlander

}

}


public class Person

{

public string Name{get;set;}

public Vehicle Vehicle{get;set;}

public Person(string name, Vehicle vehicle)

{

Name = name;

Vehicle=vehicle;

}

public void PersonInfo()

{

Console.WriteLine($"{Name} owns {Vehicle}");

}

}

[Flags]

public enum Vehicle

{

none=0,

BMWX5=1,

LandRover=2,

LincolnAviator=4,

Highlander=8

}  

Complete Code


Tuesday, 25 May 2021

Rest Principles

 Introduction

    Representational State Transfer (REST) is an architectural style that abstracts the architectural elements within a distributed hypermedia system. It was first presented by  Roy Fielding in 2000.

The REST architectural style describes six constraints applied to the architecture which are described below:


Client–Server

This princples is based on separation of concerns principles. It is about separating client interface from data storage concers. This means client (facing) application should not handle data storage or management activity while server should not handle user interface or user state or how user is interacting with the application.

Since both the client and server are independent of each other. They can be developed independently and will be more manageable and scalable.

Stateless

Server should not store any client context information. Each client request shuould contain all the necessary information to handle the request. Session state should be held in the client

Cacheable

Client can cache responses. Response can be, implicitly or explicitly, labeled as cacheable or non-cacheable. So that client can reuse the same response data in future for equivalent request.

Layered system

It allows to use multiple hierarchical layers to compose the application. e.g. API can be deployed to Server X, database on Server B etc.

A client cannot ordinarily tell whether it is connected directly to the end server, or to an intermediary along the way.

Intermediary servers may be useful in load-balancing, cache management, security etc.

Code on demand (optional)

Servers can temporarily extend or customize the functionality of a client by the transfer of executable code. Examples of this may include compiled components such as Java applets and client-side scripts such as JavaScript. "Code on demand" is the only optional constraint of the REST architecture.

 Uniform interface

The uniform interface between clients and servers, simplifies and decouples the architecture, which enables each part to evolve independently. The four guiding principles of this interface are detailed below.

    1. Identification of resources
    2. Resource manipulation through representations
    3. Self-descriptive messages
    4. Hypermedia as the engine of application state 


Tuesday, 18 May 2021

Strategy Design Pattern in C#

Introduction

    Strategy design pattern enables to select one of the algorithms at run time. It is a behavior design       pattern and is based on Inheritance principle.
    
It deals with
    1. Multiple possible algorithms for a problem. Or When there is a family of algorithm for a problem. 
    2. Dynamically any algorithm can be selected based on certain input.




   Example

  1. In eCommerce application online payment system, there are multiple payment options
    • Cash on delivery
    • CreditCard
    • UPI 
    • Internet Banking etc.
    2. String Sorting 
    • Bubble Sort
    • Merge Sort
    • Quick Sort etc.
   3. A manufacturing company pays its employee on weekly basis. If amount is less than 2000 dollor, it it is paid in cash and employee sign on voucher against cash received. If amount is more than or equal to 2000 dollor it is paid by cheque.  
    In this scenario, payment can be implmented as Cash and Cheque. Amount is the factor which drive which payment option will be selected.

This design pattern is one of the most frequently used one.

Implementation


  public interface IStrategy
 {
  void Execute();
 }

public class StrategyA: IStrategy
{
public void Execute()
{
Console.WriteLine("This is implementation of StrategyA::Execute");
}
}

public class StrategyB: IStrategy
{
public void Execute()
{
Console.WriteLine("This is implementation of StrategyB::Execute");
}
}

 public class Context
{
    private IStrategy _strategyA, _strategyB;

    public Context()
   {
     _strategyA = new StrategyA();

                _strategyB= new StrategyB(); 

    }

    public void OperationA()
    {
        Console.WriteLine("Context OperationA method");
        _strategyA.Execute();
       _strategyB.Execute();

    }
}



Note: Most of the time Strategy is used along with factory. For real world example please write to me.

 
        

Friday, 14 May 2021

State Design Pattern in C#

Introduction 

State Design Pattern is a behavior design pattern. It allows an object to change or alter its behavior on change of its internal state.

It deals with 2 main problems

a. The object should change its behavior when its internal state change.

b. State specific behavior should be defined (programmed) independently. This means on adding new behavior will not impact on existing behaviors.

UML Class Diagram



Examples:

            Below are some examples

1. In Banking System, based on Average Monthly balanced in a saving account, bank makes the saving account as Normal, Classic, Privilege category.

  When account is Normal,

  • user will be charged for Debit card
  • minimum balance is 5000/- monthly
  • 5 times free withdraw money from another bank ATM
  • Daily max withdraw limit is 10000
  • If 5balance is more than 15000 and less than 25000, account will be promoted to Classic.
  • If balance is more than 25000, account will be promoted to Privilege.

 When account is Classic

  • user will not be charged for Debit card
  • minimum balance is 15000/- monthly
  • 10 times free withdraw money from another bank ATM
  • daily max withdraw is 20000.
  • If balance is more than 25000, account will be promoted to Privilege.
  • If balance is less than 25000, account will become Normal.

When account is Privileged 

  • user will not be charged for Debit card
  • minimum balance is 25000/-
  • unlimited free withdraw from another bank ATM
  • daily max withdraw is 50000/-
  • free Cheque book
  • personalized banker for help
  • personal loan on 1% less interest rate
  • If balance is less than 25000 and more than 15000 account will become classic
  • If balance is less than 15000, account will become Normal.

2. Public transport e.g. Bus

When Bus is static at bus stop, 

  • Doors should be opened
  • Passengers can get on of the bus.
  • Passengers can get down of the bus.

When Bus is moving,

  • Doors should be closed
  • Passengers can’t get on or get down of the bus.      

3. Vending Machine

  • Ready State: It can accept payment for cash / online accepting
  • Item-Selection State: Customer can select an item
  • Balance-Dispense: Dispense the balance amount
  • Machine is in Item-Dispense State: Selected Item will be dispensed
  • Machine is in Cancel Item State: User cancelled the item; money will be returned.
  • Inventory-Replenishment State: Items are replenished in the vending machine      

Implementation:

 Context Class

Context class has reference of State.

By default when Context Class is created, it is in StateA.



State 


StateA and StateB


Based on ChangeState property, context is changing from StateA to StateB.

Sample program is 

State Design Pattern in C#


Real world example

subscribe to get real world example

 

 


Monday, 5 June 2017

Dotnet Core Web Api, Docker, Consul & Registrator

Introduction

       In this article I am going to provide step by step tutorial for creating docker image for docker web api, consul for service registry and discovery, registrator for registering the docker service.

Prerequisites

  • Sample Web api application is ready and available in working condition in dotnet core.
  • Docker installed on the system.

Steps:

  #1: Create a docker file Dockerfile. in bin /Release folder parallel to PublishOutput folder.
  

#2: Put the below text inside Dockerfile.
FROM microsoft/dotnet:onbuild
WORKDIR /app
Add PublishOutput /app/
ENV ASPNETCORE_URLS http://*:5001
EXPOSE 5001
RUN dotnet restore
ENTRYPOINT ["dotnet",".dll"]
#3: Open command prompt pointing to the same path as Dockerfile and then run the below command
 >docker build -t <servicename> .
 docker images will be created.
>docker images
will list your image

#4: run the docker run command to execute the service
>docker run -d -p 80:5001 servicename
Now browse the service 

#5: now stop the docker container

#6: pull the consul & registrator images from hub
>docker pull gliderlabs/consul-server:latest
>docker pull gliderlabs/registrator:latest

#7: run the container for consul
>docker run -d --name=consul -p 8300:8300 -p 8500:8500  gliderlabs/consul-server -bootstrap -advertise=127.0.0.1

#8:run the container for the registrator
>docker run -d --name=registrator  --volume=/var/run/docker.sock:/tmp/docker.sock gliderlabs/registrator:latest consul://localhost:8500

#9: Now run the docker container for the web api
>docker start <containerId for webapi>

#10: Browse localhost:8500/ui and click on the services, new service will be listed there.

#11. Now client application of web api service can use the consul nuget package to discover the service.

var _services =new List<Uri>();
            var consulClient = new ConsulClient(c => c.Address = new Uri("http://127.0.0.1:8500"));
            var services = consulClient.Agent.Services().Result.Response;
            foreach (var service in services)
            {
                
                var isServiceAvailable = service.Value.Service(
                if (isSchoolApi)
                {
                    var serviceUri = new Uri($"{service.Value.Address}:{service.Value.Port}");
                    _serverUrls.Add(serviceUri);
                }
            } 


Sunday, 26 March 2017

Creating DotNet Console application container with Docker

Introduction
In this article I am going to provide step by step tutorial how to create docker image for sample dotnet core console sample application.

Prerequisites
        Below framework needs to be installed on the dev machine
         Dotnet core & docker
   
Steps
   1. Create sample console application  in c# core as below

 
using System;
namespace ConsoleApp1
{
    public class Program
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("Test Program");
        }
    }
}
round-color: black; color: white; padding: 20pxdsfjfaskdjf

2. Compile and publish the application in a folder named PublishOutput.

3. Run Command Prompt Windows from PublishOutput directory/folder (cmd should point to PublishOutput folder) and type notepad Dockerfile.

4. Save the file.
5. Make the below entry in the file and save again
FROM microsoft/dotnet:onbuild
ENTRYPOINT ["dotnet", "ConsoleApp1.dll"]
6. Execute >docker build -t testapp .
7. >docker run testapp

Sunday, 12 March 2017

Bubble Sort

Bubble Sort 

Introduction



Bubble sort is a simple sorting algorithm that compares each pair of adjacent items and swaps them if they are in the wrong order.

The pass through the list is repeated until no swaps are required, which indicates that the list is sorted.


C code

#include <stdio.h>
void BubbleSort(int items[], int length);
void PrintArray(int items[],int length)
{
    printf("\n");
    for(int i=0; i < length; i++)
    {
        printf("%d ",items[i]);
    }
}
int main()
{
    int items[] = {1,4,5,-22,11,3};

    printf("Before sorting\n");
    PrintArray(items,6);
    printf("\n**********************\n");
    BubbleSort(items,6);
    printf("\n**********************\n");
    printf("after sorting\n");
    PrintArray(items,6);
 
    return 0;
}

void BubbleSort(int items[], int length)
{
    //iterate from first item (index 0) till 2nd last
   for(int i=0; i<length-1;i++)
   {
       //iterate from first item(index 0) till length-(i+1)
       for(int j=0; j<length-i-1;j++)
       {
           if(items[j] > items[j+1])
           {
               printf("\n swapping between %d and %d",j, j+1);
               items[j]= items[j] ^ items[j+1];
             
               items[j+1] = items[j] ^ items[j+1];
     
               items[j] = items[j] ^ items[j+1];
              PrintArray(items,6);
           }
       
       }
     
   }
 
}



 
 



http://onlinegdb.com/B1_F_nQsl



Complexity


Worst Case : О(n2)

Average Case : O(n2)

Best Case : O(n)  happens when the list is already sorted. But in this case insertion sort performs better than Bubble Sort.

Monday, 20 February 2017

Problem and Technical Approach


a. An array has N number of positive integers. All numbers occur even number of times exception one number which occurs odd number of times. Find the number.

void GetOddNumberInArray(int[] items)
        {
            var result = 0;
            foreach (var item in items)
            {
                result = result ^ item; //XOR

            }
            Console.WriteLine("Odd number in the list is {0}", result);
        }
b.  Check if 2 numbers are equal or not without equal operator.
   
     if(a XOR b)==0 then a & b are equal or Not.
c. Number is multiple of 4 Or Not
  public static void ValidateMultipleof4(int n)
        {
            var result = 1;
            for(int i=2; i<=n;i++)
            {
                result = result ^ i;
            }
            if (result == n)
                Console.WriteLine("Multiple of 4");
            else Console.WriteLine("Not multiple of 4");

        OR  (n>>2) is equivalent of division by 4 && again n<<2 is multiplication by 4. So if doing this 2 bit shift operation twice produces same result will be good enough to validate it is multiple of 4.

d. two same array with one missing number. find out missing one
    Do the XOR starting with 0. missing will come out.
e. Odd Number validation, do the & with 1, if output is 0 number is even.

Saturday, 18 February 2017

LinkedList DataStructure

Introduction: Linked List is a linear collection of data elements, called nodes, each pointing to next node. Each node has value (data) and reference to next node. The first head is called head.

Advantages

Unlike array it is dynamic in nature as it can grow by allocating more memory and can shrink or reduce by deallocating the memory while the application is running.
Insertion & deletion are easily implemented. Item can be added or removed from anywhere in the sequence.

Disadvantages

It consumes more memory compared to array. Sequential access of the nodes.

Types

Singly Linked List: It contains nodes which have a data field and a next field which points to the next node in line of nodes. Last node point to the null.

Doubly Linked List: Apart from data & next field, its node has one additional field which point to the previous node.

Circular Linked List: Last node, instead of pointing to null, points to first node.


using System;


namespace DataStructure
{
    public interface ILinkedList<T>
    {
        void AddLast(Node<T> element);
        void Print();
        void AddAfter(Node<T> element, T value);

        void Delete(T value);
        
    }

    public class Node<T>
    {
        public Node<T> Next;
        public T Value;
    }

    public class SinglyLinkedList<T> : ILinkedList<T>
    {
        private Node<T> _head;
        private Node<T> _current;
        
        /// <summary>
        /// Add the element at the last
        /// </summary>
        /// <param name="element"></param>
        public void AddLast(Node<T> element)
        {
            if (_head == null) //LinkedList is empty so made it head
            {
                _head = element;
            }
            else
            {
                _current.Next = element;
            }
            _current = element;

        }
        /// <summary>
        /// Display the linkedlist
        /// </summary>
        public void Print()
        {
           
            var tmpNode = _head;
            while (tmpNode != null)
            {
                Console.WriteLine("Value stored:{0}",tmpNode.Value);
                tmpNode = tmpNode.Next;
            }
        }
        /// <summary>
        /// Add the node after the given value
        /// </summary>
        /// <param name="element"></param>
        /// <param name="data"></param>
        public void AddAfter(Node<T> element, T data)
        {
            var tmpNode = _head;
            while (tmpNode != null)
            {
                if(data.Equals(tmpNode.Value)) break;
                tmpNode = tmpNode.Next;
            }
            if(tmpNode==null) throw new Exception("data does not exist in the Linked List");
            element.Next = tmpNode.Next;
            tmpNode.Next = element;
        }

        public void Delete(T data)
        {
            var tmpNode = _head;
            if (tmpNode.Value.Equals(data))
            {
                _head = _head.Next;
                return;
            }

            while (tmpNode.Next != null)
            {
                if (data.Equals(tmpNode.Next.Value)) break;
                tmpNode = tmpNode.Next;
            }
            if(tmpNode.Next != null && tmpNode.Next.Next != null)
            tmpNode.Next = tmpNode.Next.Next;
            else //Last Node updatae _current position
            {
                tmpNode.Next = null;
                _current = tmpNode;
            }
        }
    }
    public class Program
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("XXXX------Creating Linked List------XXX");
          
            var linkedList = new SinglyLinkedList<int>();
            linkedList.AddLast(new Node<int>() { Next = null, Value = 100 });
            linkedList.AddLast(new Node<int>() { Next = null, Value = 101 });
            linkedList.AddLast(new Node<int>() { Next = null, Value = 102 });
            linkedList.Print();
            Console.WriteLine("XXXX------Adding at the end------XXX");
            linkedList.AddLast(new Node<int>() { Next = null, Value = 103 });
          
            linkedList.AddLast(new Node<int>() { Next = null, Value = 105 });
            linkedList.AddLast(new Node<int>() { Next = null, Value = 109});
            linkedList.Print();
            Console.WriteLine("XXXX------Add after------XXX");
            linkedList.AddAfter(new Node<int>() { Next = null, Value = 106 },105);
            linkedList.Print();
            Console.WriteLine("XXXX------Deleting First Node------XXX");
            linkedList.Delete(100);
            linkedList.Print();
            Console.WriteLine("XXXX------Deleting Middle Node------XXX");
            linkedList.Delete(103);
            linkedList.Print();
            Console.WriteLine("XXXX------Deleting Last Node------XXX");
            linkedList.Delete(109);
            linkedList.Print();
            Console.WriteLine("XXXX------Adding after 105------XXX");
            linkedList.AddAfter(new Node<int>() { Next = null, Value = 111 }, 105);
            linkedList.Print();
           Console.WriteLine("XXXX------Adding at the Last------XXX");
            linkedList.AddLast(new Node<int>() { Next = null, Value = 120 });
            linkedList.Print();
            Console.WriteLine("XXXX------Adding at the Last------XXX");
            linkedList.AddLast(new Node<int>() { Next = null, Value = 121 });
            linkedList.Print();
            Console.ReadKey();
        }
    }
}




              

Stack DataStructure


Introduction:  
Stack is an abstract data type. It serves as a collection of elements and follow LIFO(last in first out) pattern. So every new added item goes on the top of the stack, and only top item can be removed first.
 It has main 2 operations
 push: This operation adds an element to the collection at the top
 pop: It removes the most recently added element that was not yet removed.


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



namespace Stack
{
    public interface IStack<T>
    {
       void Push(T element);
        T Pop();
        void Print();
    }



    public class Stack<T> : IStack<T>
    {
        private T[] _items = new T[10] ;
        private int _top = -1;
        public void Push(T element)
        {
            if (_top < 9)
            {



                _items[++_top] = element;
                
            }
            else
            {
                throw new Exception("Stack is full. Item can't be added.");
            }
        }



        public void Print()
        {
            for (int i = _top; i > -1; i--)
            {
                Console.WriteLine("index:{0} item:{1}",i,_items[i]);
            }
        }





        public T Pop()
        {
            if (_top == -1)
            {
                throw new Exception("Stack is empty.");
            }
            return _items[_top--];
        }



    }


    public class Program
    {
        public static void Main(string[] args)
        {
            var stack = new Stack<int>();
            stack.Push(110);
            stack.Push(101);
            stack.Push(111);
            stack.Print();
            var item = stack.Pop();
            Console.WriteLine("Poped item :: {0}",item);
            stack.Print();
            stack.Push(200);
            stack.Print();
            Console.ReadKey();
        }
    }  

}

Complexity Analysis
                                push,pop: O(1) & search: O(n)