Delegates in c# with example
·
Delegates are type-safe function pointers. It
holds a reference(pointer) to the function.
·
The signature of the delegate must match the
signature of the function, the delegates points to, otherwise, you get a
compiler error.
· A delegate is similar to a class. You can create an instance of it, and when you do so, you pass the function name as a parameter to the delegate constructor, and this function the delegate will point to.
A Delegate is a reference type variable that holds the reference to a method. The reference can be changed at runtime.
D Delegates are especially used for implementing events and call-back methods. All delegates are implicitly derived from the “System. Delegate” class.
·
Delegates allow methods to be passed as
parameters.
·
Delegates can be used to define callback methods.
·
Delegates can be chained together; for example,
multiple methods can be called on a single event.
There are three types
of delegates that can be used in C#.
·
Single Delegate
·
Multicast Delegate
·
Generic Delegate
Single Delegate: Single delegate can be used to invoke a
single method.
Multicast Delegate
The delegate can point to multiple methods. A
delegate that points multiple methods is called a multicast delegate. The
"+" or "+=" operator adds a function to the invocation
list, and the "-" and "-=" operator removes it.
Generic Delegate:
Generic Delegate was introduced
in .NET 3.5 that don't require to define the delegate instance
in order to invoke the methods.
There are three types of generic
delegates:
·
Func
·
Action
·
Predicate
Ex of delegate:
public delegate void Hellofunctiondelegate(string
message);
class Program
{
static void Main()
{
Hellofunctiondelegate del = new Hellofunctiondelegate(Hello);
del("Hello from delegate");
}
public static void Hello(string
strmsgg)
{
Console.WriteLine(strmsgg);
}
}
-----------------------------------------------------------------------------------------------------------------------------
What is
Multithreading in c#?
Multi-threading is a process that contains multiple threads within
a single process. Here each thread performs different activities.
Multitasking
is the simultaneous execution of multiple tasks or processes over a certain
time interval. Windows operating system is an example of multitasking because
it is capable of running more than one process at a time like running Google
Chrome, Notepad, VLC player, etc. at the same time. The operating system uses a
term known as a process to execute all these applications at
the same time. A process is a part of an operating system that is responsible
for executing an application. Every program that executes on your system is a
process and to run the code inside the application a process uses a term known
as a thread.
A thread is a
lightweight process, or in other words, a thread is a unit which executes the
code under the program. So every program has logic and a thread is responsible
for executing this logic. Every program by default carries one thread to
executes the logic of the program and the thread is known as the main thread. This single-threaded model has a drawback. The single thread runs all the process
present in the program in synchronizing manner, means one after another. So,
the second process waits until the first process completes its execution, it
consumes more time in processing.
Multi-tasking:
Multi-threading is
a process that contains multiple threads within a single process. Here each
thread performs different activities. For example, we have a class and this
call contains two different methods, now using multithreading each method is
executed by a separate thread. So the major advantage of multithreading is it
works simultaneously, which means multiple tasks execute at the same time. And
also maximizing the utilization of the CPU because multithreading works on
time-sharing concept mean each thread takes its own time for execution and does
not affect the execution of another thread, this time interval is given by the
operating system.’’
Ex:Multi-tasking:
Method 1(In-progress)->Method 2 (Resume after method1)
Ex:Multi-threading:
Method 1(In-progress) -> Method2(In-progress)
Following are the various states in the life cycle of a
thread −
·
The Unstarted State − It is the situation
when the instance of the thread is created but the Start method is not called.
·
The Ready State − It is the situation when
the thread is ready to run and waiting CPU cycle.
·
The Not Runnable State − A thread is not
executable, when
- Sleep method has been called
- Wait method has been called
- Blocked by I/O operations
·
The Dead State − It is the situation when
the thread completes execution or is aborted.
Properties/Methods:
CurrentContext, CurrentCulture, CurrentPrinciple, CurrentThread, CurrentUICulture, ExecutionContext, IsAlive, IsBackground, ManagedThreadId, Name, Priority, ThreadState
--------------------------------------------------------------------------------------------------------------------------
What are Events?
An event is a notification that some action has
occurred. Delegates and events are related because an event is built upon a
delegate. Both expand the set of programming tasks to which C# can be applied.
It is an important C# feature is built upon the foundation of delegates: the
event. An event is, essentially, an automatic notification that some action has
occurred. Events work like this:
An object that has an interest in an event registers
an event handler for that event. When the event occurs, all registered handlers
are called. Event handlers are represented by delegates.
Events are
members of a class and are declared using the event keyword. Its most commonly
used form is shown here:
event event-delegate event-name;
Here,
event-delegate is the name of the delegate used to support the event, and
event-name is the name of the specific event object being declared.
--------------------------------------------------------------------------------------------------------------------------
What is Reflection in C#?
Reflection objects are used for obtaining type
information at runtime. The classes that give access to the
metadata of a running program are in the System. Reflection namespace.
In C#, reflection is a process to get metadata of a type at runtime.
Reflection is when managed code can read its own
metadata to find assemblies. Essentially, it allows code to inspect other code
within the same system.
Reflection provides objects (of type
Type) that describe assemblies, modules, and types. You can
use reflection to dynamically create an instance of a type, bind the type to an
existing object, or get the type from an existing object and invoke its methods
or access its fields and properties
It contains classes that allow you to obtain
information about the application and to dynamically add types, values, and
objects to the application.
With reflection in C#, you can dynamically create
an instance of a type and bind that type to an existing object. Moreover, you
can get the type from an existing object and access its properties. When you
use attributes in your code, reflection gives you access as it provides objects of Type that describe modules, assemblies, and types.
To understand reflection, there are a few basics you should
understand about modules, types, and members:
·
Assemblies contain modules
·
Modules contain types
·
Types contain members
|
Class |
Description |
|
Assembly |
describes an assembly which is a reusable, versionable, and
self-describing building block of a common language runtime application |
|
AssemblyName |
Identifies an assembly ith a unique name |
|
ConstructorInfo |
Describes a class constructor and gives access to the
metadata |
|
MethodInfo |
Describes the class method and gives access to its metadata |
|
ParameterInfo |
Describes the parameters of a method and gives access to
its metadata |
|
EventInfo |
Describes the event info and gives accessto its metadata |
|
PropertyInfo |
Discovers the attributes of a property and provides access
to property metadata |
|
MemberInfo |
Obtains information about the attributes of a member and
provides access to member metadata |
// Using GetType to
obtain type information:
int i = 42;
System.Type type = i.GetType();
System.Console.WriteLine(type);
O/P:
System.Int32
// create instance of
class DateTime
DateTime dateTime = (DateTime)Activator.CreateInstance(typeof(DateTime));
The System.Type class is the main class for the
.NET Reflection functionality to access metadata. The System.Type class is an
abstract class and represents a type in the Common Type System (CLS). It
represents type declarations: class types, interface types, array types, value
types, enumeration types, type parameters, generic type definitions, and open
or closed constructed generic types.
The Type class and its members are used to get information about a type declaration and its members such as constructors, methods, fields, properties, and events of a class, as well as the module and the assembly in which the class is deployed.
----------------------------------------------------------------------------------------------------------------------
What is Anonymous
Types in C#?
·
Anonymous types in C# are the types which do not have a
name or you can say the creation of new types without defining them.
·
It is introduced in C# 3.0.
·
In C#, an anonymous type is a type (class) without any name
that can contain public read-only properties only. It cannot contain other
members, such as fields, methods, events, etc.
·
The "type" of the type is decided by the
compiler.
·
C# allows you to create an object with the new keyword
without defining its class.
·
Anonymous types are class type, directly derived
from “System. Object” so they are reference types.
·
If two or more Anonymous types have the same
properties in the same order in the same assembly then the compiler treats them as the same
type.
·
All properties of anonymous types are read-only.
·
LINQ query expressions, and lambdas commonly use anonmous
types. Anonymous types are used with the "Select" clause of LINQ
query expression to return records.
·
The scope
of the anonymous type is always limited to the method in which they are
defined. Due to their local scope, you are not allowed to pass an anonymous
type to another method, but you can pass it to those methods which can accept
dynamic type parameters.
Example: Anonymous Type
var student = new { Id = 1, FirstName =
"James", LastName = "Bond" };
The properties of anonymous types are
read-only and cannot be initialized with a null, anonymous function, or a
pointer type. The properties can be accessed using dot (.) notation, same as
object properties. However, you cannot change the values of properties as they
are read-only.
An anonymous type's property can include another anonymous
type.
You can create an array of anonymous types also.
Anonymous
types have nothing to do with the design of systems or even at the class level.
They're a tool for developers to use when coding. These are handy when you
create types for "use and throw" purposes. You would not
need to declare a class or a struct for every time you need a temporary type.
-----------------------------------------------------------------------------------------------------------------------------
What is
Serialization in C#?
Serialization
is the process of converting an object into a stream of bytes to store the
object or transmit it to memory, a database, or a file. Its main purpose is to
save the state of an object in order to be able to recreate it when needed. The
reverse process is called deserialization.
Following namespaces are involved in
serialization process,
- System.Runtime.Serialization
- System.Runtime.Serialization.Formatters.Binary
Types
- Binary Serialization
- XML Serialization
- JSON Serialization
Extension method
in c# example
Extension methods enable you to "add" methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. Extension methods are static methods, to define an extension method, first of all, define a static class.
(or)
Extension methods, as the name
suggests, are additional methods. Extension methods allow you to inject
additional methods without modifying, deriving or recompiling the original
class, struct, or interface. Extension methods can be added to your own custom class,
.NET framework classes, or third-party classes or interfaces.
C# extension method is a static
method of a static class, where the "this" modifier is applied to the
first parameter. The type of the first parameter will be the type that is
extended.
Extension methods are only in scope
when you explicitly import the namespace into your source code a using
directive.
int i = 10;
bool result = i.is greater than(100); //returns
false
·
Extension methods are always defined as static
methods, but when they are bound with any class or structure they will convert
into non-static methods. The extension method does not support method overriding
·
You can also add new methods in the sealed class also
using an extension method concept.
·
It cannot apply to fields, properties,
or events.
·
The only difference between a regular static
method and an extension method is that the first parameter of the extension
method specifies the type that it is going to the operator on, preceded by this keyword. Extension methods can be used anywhere
in the application by including the namespace of the extension method.
·
The main advantage of the extension method is to
add new methods in the existing class without using inheritance.
·
You can add new methods in the existing class
without modifying the source code of the existing class.
·
It can also work with the sealed classes.
----------------------------------------------------------------------------------------------------------------------------
SOLID design principles in C# are basic design
principles. SOLID stands for Single Responsibility Principle (SRP), Open closed
Principle (OSP), Liskov substitution Principle (LSP), Interface Segregation
Principle (ISP), and Dependency Inversion Principle (DIP).
SOLID
Principles
There are five SOLID principles:
Single Responsibility Principle (SRP)
Open-Closed Principle (OCP)
Liskov Substitution Principle (LSP)
Interface Segregation Principle (ISP)
Dependency Inversion Principle (DIP)
Single
Responsibility Principle (SRP)
A class should have only one reason to change.
(Or)
“Each software module or class should have only one reason
to change“. In other words, we can say that each module or class should
have only one responsibility to do.
So we need to design the
software in such a way that everything in a class or module should be related
to a single responsibility. That does not mean your class should contain only
one method or property, you can have multiple members (methods or properties)
as long as they are related to a single responsibility or functionality. So, with the help of SRP in
C#, the classes become smaller and cleaner and thus easier to maintain.
Let us understand the need
for the Single Responsibility Principle in C# with an example. Suppose we need
to design an Invoice class. As we know an Invoice class is basically used to
calculate various amounts based on its data. The Invoice class does not know
how to retrieve the data, or how to format the data for display, print,
logging, or sending an email, etc.
If we write the database logic, business logic as well as display logic
in a single class, then our class performing multiple responsibilities. Then it
becomes very difficult to change one responsibility without breaking the other
responsibilities. So, by mixing multiple responsibilities into a single class,
we are getting the following disadvantage,
- Difficult
to understand
- Difficult
to test
- Chance of
duplicating the logic of other parts of the application
Open-Closed
Principle:
The Open-Closed Principle states
that “software
entities such as modules, classes, functions, etc. should be open for
extension, but closed for modification“.
Let us understand the above definition in
simple words. Here we need to understand two things. The first thing is Open
for extension and the second thing is Closed for modification. The Open
for extension means we need to design the software modules/classes in such a
way that the new responsibilities or functionalities should be added easily
when new requirements come. On the other hand, Closed for modification
means, we should not modify the class/module until we find some bugs.
The reason for this is, we have
already developed a class/module and it has gone through the unit testing
phase. So we should not have to change this as it affects the existing
functionalities. In simple words, we can say that we should develop one
module/class in such a way that it should allow its behavior to be extended
without altering its source code.
Implementation
Guidelines for the Open-Closed Principle (OCP) in C#
- The easiest
way to implement the Open-Closed Principle in C# is to add the new
functionalities by creating new derived classes which should be inherited
from the original base class.
- Another way is
to allow the client to access the original class with an abstract
interface.
- So, at any
given point of time when there is a change in requirement or any new
requirement comes then instead of touching the existing functionality,
it’s always better and suggested to create new derived classes and leave
the original class implementation as it is.
Ex:
Without using Open-Closed Principles in c#
namespace SOLID_PRINCIPLES.OCP
{
public class Invoice
{
public double
GetInvoiceDiscount(double amount, InvoiceType invoiceType)
{
double finalAmount = 0;
if (invoiceType ==
InvoiceType.FinalInvoice)
{
finalAmount = amount - 100;
}
else if (invoiceType ==
InvoiceType.ProposedInvoice)
{
finalAmount = amount - 50;
}
return finalAmount;
}
}
public enum InvoiceType
{
FinalInvoice,
ProposedInvoice
};
}
Example: With Open-Closed Principle in
C#
namespace SOLID_PRINCIPLES.OCP
{
public class Invoice
{
public virtual double GetInvoiceDiscount(double amount)
{
return amount - 10;
}
}
public class FinalInvoice : Invoice
{
public override double GetInvoiceDiscount(double amount)
{
return base.GetInvoiceDiscount(amount) - 50;
}
}
public class ProposedInvoice : Invoice
{
public override double GetInvoiceDiscount(double amount)
{
return base.GetInvoiceDiscount(amount) - 40;
}
}
public class RecurringInvoice : Invoice
{
public
override double GetInvoiceDiscount(double amount)
{
return base.GetInvoiceDiscount(amount) - 30;
}
}
}
Modify the Main method of the Program
class as shown below to test the application.
using System;
namespace SOLID_PRINCIPLES.OCP
{
class
Program
{
static void Main(string[] args)
{
Invoice FInvoice = new FinalInvoice();
Invoice PInvoice = new ProposedInvoice();
Invoice RInvoice = new RecurringInvoice();
double FInvoiceAmount = FInvoice.GetInvoiceDiscount(10000);
double PInvoiceAmount = PInvoice.GetInvoiceDiscount(10000);
double RInvoiceAmount = RInvoice.GetInvoiceDiscount(10000);
Console.ReadKey();
}
}
}
Now, the Invoice class is closed for modification. But it is open for the extension as it allows creating new classes deriving from the Invoice class which clearly follows the Open-Closed Principle in C#.
The
Liskov Substitution Principle (LSP) states that "you should be able to use
any derived class instead of a parent class and have it behave in the same
manner without modification". It ensures that a derived class does not
affect the behavior of the parent class, in other words,, that a derived class
must be substitutable for its base class.
This principle is just an extension of the Open-Closed Principle and it means that we must ensure that new derived classes extend the base classes without changing their behavior. I will explain this with a real-world example that violates LSP.
A father is a doctor whereas his son wants to become a cricketer. So here the son can't replace his father even though they both belong to the same family hierarchy.
Example:
Without using the Liskov Substitution Principle in C#:
namespace SOLID_PRINCIPLES.LSP
{
class
Program
{
static void Main(string[] args)
{
Apple apple = new Orange();
Console.WriteLine(apple.GetColor());
}
}
public class Apple
{
public virtual string GetColor()
{
return "Red";
}
}
public class Orange : Apple
{
public override string GetColor()
{
return "Orange";
}
}
}
Let’s modify the previous example to follow the Liskov Substitution Principle. Here, first, we need a generic base class such as Fruit which is going to be the base class for both Apple and Orange. Now you can replace the Fruit class object with its subtypes either Apple and Orage and it will behave correctly. Now, you can see in the below code, we created the super Fruit class as an abstract class with the GetColor abstract method and then the Apple and Orange class inherited from the Fruit class and implement the GetColor method.
Example Using the Liskov Substitution Principle in C#
namespace
SOLID_PRINCIPLES.LSP
{
class Program
{
static void Main(string[] args)
{
Fruit fruit = new Orange();
Console.WriteLine(fruit.GetColor());
fruit = new Apple();
Console.WriteLine(fruit.GetColor());
}
}
public abstract class Fruit
{
public abstract string GetColor();
}
public class Apple: Fruit
{
public override string GetColor()
{
return "Red";
}
}
public class Orange : Fruit
{
public override string GetColor()
{
return "Orange";
}
}
}
Liskov Substitution
Principle (LSP):
The
Liskov Substitution Principle (LSP) states that "you should be able to use
any derived class instead of a parent class and have it behave in the same
manner without modification". It ensures that a derived class does not
affect the behavior of the parent class, in other words,, that a derived class
must be substitutable for its base class.
This principle is just an extension of the Open-Closed Principle and it means that we must ensure that new derived classes extend the base classes without changing their behavior. I will explain this with a real-world example that violates LSP.
A father is a doctor whereas his son wants to become a cricketer. So here the son can't replace his father even though they both belong to the same family hierarchy.
Example:
Without using the Liskov Substitution Principle in C#:
namespace SOLID_PRINCIPLES.LSP
{
class
Program
{
static void Main(string[] args)
{
Apple apple = new Orange();
Console.WriteLine(apple.GetColor());
}
}
public class Apple
{
public virtual string GetColor()
{
return "Red";
}
}
public class Orange: Apple
{
public override string GetColor()
{
return "Orange";
}
}
}
Example Using the Liskov Substitution Principle
in C#
Let’s modify the
previous example to follow the Liskov Substitution Principle. Here, first, we
need a generic base class such as Fruit which is going to be the base class for
both Apple and Orange. Now you can replace the Fruit class object with its
subtypes either Apple and Orage and it will behave correctly. Now, you can see
in the below code, we created the super Fruit class as an abstract class with
the GetColor abstract method and then the Apple and Orange class inherited from
the Fruit class and implement the GetColor method.
namespace
SOLID_PRINCIPLES.LSP
{
class Program
{
static void Main(string[] args)
{
Fruit fruit = new Orange();
Console.WriteLine(fruit.GetColor());
fruit = new Apple();
Console.WriteLine(fruit.GetColor());
}
}
public abstract class Fruit
{
public abstract string GetColor();
}
public class Apple : Fruit
{
public override string GetColor()
{
return "Red";
}
}
public class Orange: Fruit
{
public override string GetColor()
{
return "Orange";
}
}
}
Interface Segregation Principle
(ISP):
No client should be forced to
implement methods that it does not use, and the contracts should be broken
down into thin ones.
Clients should not be forced to implement any methods they don’t use. Rather than one fat interface, numerous little interfaces are preferred based on groups of methods with each interface serving one submodule“.
Let
us break down the above definition into two parts.
- First,
no class should be forced to implement any method(s) of an interface they
don’t use.
- Secondly,
instead of creating large or you can say fat interfaces, create multiple
smaller interfaces with the aim that the clients should only think about
the methods that are of interest to them.
As per the Single responsibility principle of SOLID, like classes, interfaces also should
have a single responsibility. That means we shouldn’t force any class to
implement any method(s) which they don’t require.
namespace
SOLID_PRINCIPLES.ISP
{
public interface IPrinterTasks
{
void Print(string PrintContent);
void Scan(string ScanContent);
}
interface IFaxTasks
{
void Fax(string content);
}
interface IPrintDuplexTasks
{
void PrintDuplex(string content);
}
}
namespace
SOLID_PRINCIPLES.ISP
{
public class HPLaserJetPrinter :
IPrinterTasks, IFaxTasks,
IPrintDuplexTasks
{
public void Print(string PrintContent)
{
Console.WriteLine("Print
Done");
}
public void Scan(string ScanContent)
{
Console.WriteLine("Scan
content");
}
public void Fax(string FaxContent)
{
Console.WriteLine("Fax
content");
}
public void PrintDuplex(string
PrintDuplexContent)
{
Console.WriteLine("Print
Duplex content");
}
}
}
namespace
SOLID_PRINCIPLES.ISP
{
class LiquidInkjetPrinter : IPrinterTasks
{
public void Print(string PrintContent)
{
Console.WriteLine("Print
Done");
}
public void Scan(string ScanContent)
{
Console.WriteLine("Scan content");
}
}
}
Dependency Inversion
Principle (DIP):
High-level
modules should not depend on low-level modules. Both should depend on
abstractions.
Abstractions
should not depend on details. Details should depend on abstractions.
The
principle says that high-level modules should depend on abstraction, not on the
details, of low-
level
modules. In simple words, the principle says that there should not be a tight
coupling among
components
of software and to avoid that, the components should depend on abstraction.
The terms Dependency Injection (DI) and Inversion of Control (IoC) are generally used interchangeably to express the same design pattern. The pattern was initially called IoC, but Martin
Fowler
(known for designing the enterprise software) anticipated the name as DI
because all frameworks or runtime invert
the control in some way and he wanted to know which aspect of control was
being inverted.
Inversion
of Control (IoC) is a technique to implement the Dependency Inversion Principle
in C#.
Inversion
of control can be implemented using either an abstract class or interface. The
rule is that
the
lower-level entities should join the contract to a single interface and the
higher-level entities
will
use only entities that are implementing the interface. This technique removes
the dependency
between
the entities.
The
most important point that you need to remember while developing real-time
applications, always to try to keep the High-level module and Low-level module
as loosely coupled as possible.
When
a class knows about the design and implementation of another class, it raises
the risk that if we
do
any changes to one class will break the other class. So we must keep these
high-level and low-level
modules/classes
loosely coupled as much as possible. To do that, we need to make both of them
dependent on abstractions instead of knowing each other.
namespace
SOLID_PRINCIPLES.DIP
{
public interface IEmployeeDataAccess
{
Employee GetEmployeeDetails(int id);
}
}
namespace
SOLID_PRINCIPLES.DIP
{
public class EmployeeDataAccess:
IEmployeeDataAccess
{
public Employee GetEmployeeDetails(int
id)
{
// In real time get the employee
details from DB
//but here we are hardcoded the
employee details
Employee emp = new Employee()
{
ID = id,
Name = "Pranaya",
Department = "IT",
Salary = 10000
};
return emp;
}
}
}
namespace
SOLID_PRINCIPLES.DIP
{
public class DataAccessFactory
{
public static IEmployeeDataAccess
GetEmployeeDataAccessObj()
{
return new EmployeeDataAccess();
}
}
}
namespace
SOLID_PRINCIPLES.DIP
{
public class EmployeeBusinessLogic
{
IEmployeeDataAccess
_EmployeeDataAccess;
public EmployeeBusinessLogic()
{
_EmployeeDataAccess =
DataAccessFactory.GetEmployeeDataAccessObj();
}
public Employee GetEmployeeDetails(int
id)
{
return
_EmployeeDataAccess.GetEmployeeDetails(id);
}
}
}
Advantages of
implementing the Dependency Inversion Principle in C#:
Now,
the EmployeeBusinessLogic and EmployeeDataAccess classes are loosely coupled
classes because EmployeeBusinessLogic does not depend on concrete
EmployeeDataAccess classes, instead, it includes a reference of the IEmployeeDataAccess interface. So now, we can easily use another class that
implements IEmployeeDataAccess with a different implementation.-----------------------------------------------------------------------------------------------------------------------------
Design
Patterns in C#?
There
are three basic classifications of patterns Creational, Structural, and
Behavioral patterns.
Creational
Patterns(object creation and initialization)
The
Creational Design Pattern deals with Object Creation and Initialization. The
Creational Design Pattern gives the programmer more flexibility in deciding
which objects need to be created for a given case. For example, if we have a
huge project, a huge project means we have a lot of classes, a lot of classes
mean we are dealing with a lot of objects. So we need to create different
objects (like new Customer(), new product(), new invoice(), etc.) based on some
conditions. If the object creations logic based on some condition is
implemented in the client code, then it leads to lots of complicated logic in
the client code. That means if the object creations and initialization logic
are not centralized then it leads to a very complicated code. The Creational Design
Pattern helps us to centralized the object creation logic and depending upon
the condition, it will create and initialize the appropriate object and returns
that object.
Abstract
Factory: Creates an instance of several families of classes
Builder: Separates object construction from its representation
Factory
Method: Creates an instance of several derived classes
Prototype: A fully initialized instance to be copied or cloned
Singleton: A class in which only a single instance can exist
Note
The
best way to remember the Creational pattern is by remembering ABFPS (Abraham Became the First President of the States).
Structural
Patterns(Structural Changes of class and interfaces, and the relationship
between classes)
The
Structural Design Pattern is basically used to manage the structure of classes
and interface as well as manage the relationship between the classes. For
example, if we have a Customer and Product class and the Product class is used
inside the Customer class making one to many relationships. Tomorrow, as the
project proceeds, now we want to keep away the product class from the Customer
class as we want to use the Product and Customer class independently. This is a
structural change and we don’t want this structural change to affect our
project. This is where the Structural Design Pattern helps us.
Adapter: Match interfaces of different classes.
Bridge: Separates an object's abstraction from its implementation.
Composite: A tree structure of simple and composite objects.
Decorator: Add responsibilities to objects dynamically.
Flyweight: A fine-grained instance used for efficient sharing.
Proxy: An object representing another object.
Note
To
remember structural pattern best is (ABCDFFP)
Behavioral
Patterns(Communication Between Objects)
The
Behavioral Design Patterns deal with the communication between Classes and
objects. That means if you want to change the behavior of a class and again you
want it to affect other classes of the project as well. For example, you have
an Invoice class that currently applying taxes as 18%. Tomorrow if you have to
add another extra tax. That means you are changing the behavior of a class. To
solve such types of Behavioral issues Behavioral Design Pattern comes into the
picture.
Mediator: Defines simplified communication between classes.
Memento: Capture and restore an object's internal state.
Interpreter: A way to include language elements in a program.
Iterator: Sequentially access the elements of a collection.
Chain
of Resp: A way of passing a request between a chain of objects.
Command: Encapsulate a command request as an object.
State: Alter an object's behavior when its state changes.
Strategy: Encapsulates an algorithm inside a class.
Observer: A way of notifying change to a number of classes.
Template
Method: Defer the exact steps of an algorithm to a subclass.
Visitor: Defines a new operation to a class without change.
Note: Just remember
Music....... 2 MICS On TV (MMIICCSSOTV).
-----------------------------------------------------------------------------------------------------------------------------
Why do we need the
Dependency Injection Design Pattern in C#?
The
Dependency Injection Design Pattern in C# allows us to develop loosely coupled
software components. In other words, we
can say that Dependency Injection Design Pattern is used to reduce the tight coupling
between the software components. As a result, we can easily manage future
changes and other complexity in our application. Before understanding the
Dependency Injection Design Pattern using C#, let us first understand what tight
coupling is and what loose coupling in software development is. So let’s
understand these two concepts first.
What is Tight Coupling
in Software Design?
Tight
coupling means two objects are dependent on each other. That means when a class
is dependent on another class, then it is said to be a tight coupling between
these two classes. In that case, if we
change
the dependent object, then we also need to change the classes where this
dependent object is
used.
If your application is a small one, then it is not that difficult to handle but
if you have a big
enterprise-level
application, then it’s really very difficult to handle to make these changes.
What is Loose Coupling
in Software Design?
Loosely
coupling means two objects are independent of each other. That means if we
change one object then it will not affect another object. The loosely coupled
nature of software development allows us to manage future changes easily and
also allows us to manage the complexity of the application.
What is Dependency
Injection Design Pattern in C#?
The
Dependency Injection Design Pattern in C# is a process in which we are
injecting the object of a class into a class that depends on that object. The
Dependency Injection design pattern is the most commonly used design pattern
nowadays to remove the dependencies between the objects.
Dependency
Injection (DI) is a design pattern used to implement IoC (Inversion of
Control). It allows the creation of dependency objects outside of a class and
provides those objects to a class in different ways. Using Dependency Injection
Design Pattern, we move the creation and binding of the dependent objects
outside of the class that depends on them.
Dependency
Injection pattern involves 3 types of classes:
Client Class: The Client class
(dependent class) is a class that depends on the service class.
Service Class: The Service class
(dependency) is a class that provides service to the client class.
Injector Class: The Injector class
injects the service class object into the client class.
Different
Types of Dependency Injection in C#?
The
injector class injects the dependency object into a class in three different
ways. They are as
follows.
Constructor Injection: When the Injector
injects the dependency object (i.e. service) through the
client
class constructor, then it is called Constructor Dependecy Injection.
The
Injection happens in the constructor, bypassing the Service that implements the
IService Interface. The dependencies are assembled by a "Builder" and
Builder responsibilities are as follows:Knowing the types of each IService
According to the request, feed the abstract IService to the Client.
Advantages of
Constructor Dependency Injection
The
Constructor Dependency Injection Design Pattern makes a strong dependency contract
This design pattern support testing as the dependencies are passed through the
constructor.
Property Injection: When the Injector
injects the dependency object (i.e. service) through the public
property
of the client class, then it is called Property Dependency Injection. This is
also called the Settler injection. In Property Dependency Injection, we need to
supply the dependency object through a public property of the client class
Method Injection: When the Injector
injects the dependency object (i.e. service) through a public method of the client class, then it is called
Method Dependency Injection. It could be useful, where the whole class does not
need the dependency, only one method having that dependency.
Constructor Injection
public
interface IService {
void Serve();
}
public
class Service1 : IService {
public void Serve() {
Console.WriteLine("Service1 Called"); }
}
public
class Service2 : IService {
public void Serve() {
Console.WriteLine("Service2 Called"); }
}
public
class Client {
private IService _service;
public Client(IService service) {
this._service = service;
}
public ServeMethod() { this._service.Serve();
}
}
class
Program
{
static void Main(string[] args)
{
//creating object
Service1 s1 = new Service1();
//passing dependency
Client c1 = new Client(s1);
//TO DO:
Service2 s2 = new Service2();
//passing dependency
c1 = new Client(s2);
//TO DO:
}
}
Ex: Property/Setter Injection
public
interface IService {
void Serve();
}
public
class Service1 : IService {
public void Serve() {
Console.WriteLine("Service1 Called"); }
}
public
class Service2 : IService {
public void Serve() {
Console.WriteLine("Service2 Called"); }
}
public
class Client {
private IService _service;
public IService Service {
set { this._service = value; }
}
public ServeMethod() { this._service.Serve();
}
}
class
Program
{
static void Main(string[] args)
{
//creating object
Service1 s1 = new Service1();
Client client = new Client();
client.Service = s1; //passing dependency
//TO DO:
Service2 s2 = new Service2();
client.Service = s2; //passing dependency
//TO DO:
}
}
Ex:Method Injection
public
interface IService {
void Serve();
}
public
class Service1 : IService {
public void Serve() {
Console.WriteLine("Service1 Called"); }
}
public
class Service2 : IService {
public void Serve() {
Console.WriteLine("Service2 Called"); }
}
public
class Client {
private IService _service;
public void Start(IService service) {
service.Serve();
}
}
class
Program
{
static void Main(string[] args)
{
//creating object
Service1 s1 = new Service1();
Client client = new Client();
client.Start(s1); //passing dependency
//TO DO:
Service2 s2 = new Service2();
client.Start(s2); //passing dependency
}
}
Advantages of
Dependency Injection
Reduces
class coupling
Increases
code reusability
Improves
code maintainability
Make
unit testing possible-----------------------------------------------------------------------------------------------------------------------------
Singleton Pattern versus Static Class
In simple words, Singleton is a pattern and not a keyword.
The Singleton pattern has several advantages over static classes. A singleton
allows a class for which there is just one, persistent instance across the
lifetime of an application. That means, it created a single instance and that
instance (a reference to that instance) can be passed as a parameter to other
methods and treated as a normal object. While a static class allows only
static methods and you cannot pass the static class as a parameter. A Singleton can
implement interfaces, inherit from other classes and allow inheritance. While a
static class cannot inherit its instance members. So Singleton is more
flexible than static classes and can maintain state.
A
Singleton can be initialized lazily or asynchronously and loaded automatically
by the .NET Framework CLR (common language runtime) when the program or
namespace containing the class is loaded. While a static class is generally
initialized when it is first loaded and it will lead to potential classloader
issues.
Singleton class follows the
Object-Oriented Principles so that singletons can be handled polymorphically
without forcing their users to assume that there is only one instance. While
static cannot.
Other differences:
- Singleton Objects are stored on the heap while static class is stored in the stack.
- Singleton Objects can have a constructor while Static Class cannot.
- Singleton Objects can dispose
but not a static class.
- Singleton Objects can clone but
not with a static class.
In
short, single means a single object across the application life cycle, so the
scope is at the application level. The static does not have any Object pointer, so
the scope is at the App Domain level. Moreover, both should be implemented to be
thread-safe.
|
Static |
Singleton |
|
We don’t need to
instantiate a static class and can access properties and methods with the class
names. |
Instance creation is
necessary to access methods and properties. We create instances using static
property defined for this purpose. |
|
Static class cannot
be passed a parameter in another class |
We can pass instances
of a singleton as a parameter to another class method. |
|
A static keyword is
required in all the methods defined in the Static class. |
The Singleton class
does not require you to use the static keyword everywhere. |
|
Static class does not
support interface inheritance. It throws the error “static classes cannot
implement interfaces” |
Singleton class can
implement the interface |
|
The static variable does
not reset until the server is restarted. |
|
|
It cannot have
instance members. We need to call all the static methods explicitly. |
This may have
instance members. |
Code example
//Static Class
public static class Stat{
static Stat(){
Console.WriteLine("static constr");
}
public static
void Get(){
Console.WriteLine("stat method
called");
}
}
//Singleton pattern
public class SingleTon{
private
static SingleTon obj = null;
private
static readonly Object locker = new Object();
private
SingleTon(){
}
public int
UserId {get;set;}
public static
SingleTon GetInstance {
get{
if(obj ==
null){
lock(locker){
if(obj ==
null){
obj = new
SingleTon();
}
}
}
return obj;
}
}
}
-----------------------------------------------------------------------------------------------------------------------------
Code-first vs
Model/Database-first
There are 3 approaches through which the Entity framework is implemented.
Database
First
Code
First
Model
First
Of
these Database first and Code First is the most used ones.
Code First Approach
In the code first approach, we will first create entity classes with properties defined
in them. The entity
framework
will create the database and tables based on the entity classes defined. So the database is
generated
from the code. When the dot net code is run database will get created.
Advantages
You
can create the database and tables from
your business objects.
You
can specify which related collections are to be eagerly loaded, or not be
serialized at all.
Database
version control.
Good
for small applications.
Disadvantages
You
have to write everything related to the database in the visual studio code.
For
stored procedures, you have to map stored procedures using Fluent API and write
Stored Procedure
inside
the code.
If
you want to change anything in the database tables you to make changes in the
entity classes in the
code
file and run the update database from the package manager console.
Not
preferred for Data-intensive applications.
Database First
Approach
In
this approach databases and tables are created first. Then you create an Entity
Data Model using the
created
database.
Advantages
Simple
to create the data model
Graphical user interface.
Mapping and creating keys and relationships
are easy as you need not have to write any code.
Preferred for data-intense and large
applications
Disadvantages
Using
an existing database to generate a .edmx model file and the associated code
models results in a
a giant
pile of auto-generated code.
When
you need to add any functionality to the generated model you have to extend the
model class generated.
Which Approach To Use?
If
you are starting a new project, with a new database, use EF Core Code First
If
you are starting a new project, but there is an existing database you want to
talk to, use EF Core
Database First.
C#
- Tuple
The Tuple<T> class was introduced in .NET
Framework 4.0. A tuple is a data structure that contains a sequence of elements
of different data types. It can be used where you want to have a data structure
to hold an object with properties, but you don't want to create a separate type
for it.
Tuple<T1, T2, T3, T4, T5, T6, T7, TRest>
Tuple<int, string, string> person =
new Tuple <int,
string, string>(1, "Steve", "Jobs")
var person = Tuple.Create(1, "Steve",
"Jobs");
var numbers = Tuple.Create(1, 2, 3, 4, 5, 6, 7, 8);
var person = Tuple.Create(1, "Steve",
"Jobs");
person.Item1; // returns 1
person.Item2; // returns "Steve"
person.Item3; // returns "Jobs"
var numbers = Tuple.Create("One", 2, 3,
"Four", 5, "Six", 7, 8);
numbers.Item1; // returns "One"
numbers.Item2; // returns 2
numbers.Item3; // returns 3
numbers.Item4; // returns "Four"
numbers.Item5; // returns 5
numbers.Item6; // returns "Six"
numbers.Item7; // returns 7
numbers.Rest; // returns (8)
numbers.Rest.Item1; // returns 8
Nested
Tuples
If you want to include more than eight elements in a
tuple, you can do that by nesting another tuple object as the eighth element.
The last nested tuple can be accessed using the Rest property. To access the
nested tuple's element, use the Rest.Item1.Item<elelementNumber>
property.
var numbers = Tuple.Create(1, 2, 3, 4, 5, 6, 7,
Tuple.Create(8, 9, 10, 11, 12, 13));
numbers.Item1; // returns 1
numbers.Item7; // returns 7
numbers.Rest.Item1; //returns (8, 9, 10, 11, 12, 13)
numbers.Rest.Item1.Item1; //returns 8
numbers.Rest.Item1.Item2; //returns 9
var numbers = Tuple.Create(1, 2, Tuple.Create(3, 4,
5, 6, 7, 8), 9, 10, 11, 12, 13 );
numbers.Item1; // returns 1
numbers.Item2; // returns 2
numbers.Item3; // returns (3, 4, 5, 6, 7, 8)
numbers.Item3.Item1; // returns 3
numbers.Item4; // returns 9
numbers.Rest.Item1; //returns 13
Tuple
as a Method Parameter
A method can have a tuple as a parameter.
static void Main(string[] args)
{
var person
= Tuple.Create(1, "Steve", "Jobs");
DisplayTuple(person);
}
static void
DisplayTuple(Tuple<int,string,string> person)
{
Console.WriteLine($"Id = { person.Item1}");
Console.WriteLine($"First Name = { person.Item2}");
Console.WriteLine($"Last
Name = { person.Item3}");
}
Tuple
as a Return Type
A Tuple can be returned from a method.
static void Main(string[] args)
{
var person
= GetPerson();
}
static Tuple<int, string, string> GetPerson()
{
return
Tuple.Create(1, "Bill", "Gates");
}
Usage
of Tuple
Tuples can be used in the following scenarios:
When you want to return multiple values from a
method without using ref or out parameters.
When you want to pass multiple values to a method
through a single parameter.
When you want to hold a database record or some
values temporarily without creating a separate class.
Tuple
Limitations:
The Tuple is a reference type and not a value type.
It allocates on the heap and could result in CPU-intensive operations.
The Tuple is limited to include eight elements. You
need to use nested tuples if you need to store more elements. However, this may
result in ambiguity.
The Tuple elements can be accessed using properties
with a name pattern Item<elementNumber>, which does not make sense.-----------------------------------------------------------------------------------------------------------------------------
MULTI-THREADING IN C#
Threads are lightweight processes that act as a path
through which a process can be executed. Every process/application runs by
default with a single thread. The entire code of the application gets executed
sequentially in a single thread.
Multithreaded applications introduced the capability
to process the independent code concurrently in more than one thread.
Multithreading helps to reduce the time of execution, and also makes use of the
CPU power at an optimum level.
System.threading namespace contains the classes and
interface which enables multithreading in an application.
LIFE CYCLE OF THREAD
Here’s the life cycle of a thread -
Unstarted State - State at which the instance of the
thread is created but hasn’t yet started to run. In other words, the Start() method
of the Thread is not being called.
Eg - var thread = new Thread();
Ready State - A thread that is ready to run is in a
runnable/ready state. This means an instance of the thread is created and it is
ready to run at any moment.
Running State - As the name implies, the thread that
is running is termed to be in a running state.
Non-Runnable State - State at which the thread is
not executable. Below are few states which are considered non-runnable when,
Sleep() method of the thread is active
Wait() method of the thread is active
Suspend() method of the thread is called
Waiting for I/O Operations
Dead State - When the thread completes the task
assigned to it, it is considered to be in a dead state.
FREQUENTLY ACCESSED MEMBER/PROPERTY OF A THREAD
Methods that are frequently accessed
public void Start() - This method is invoked to
start a thread.
public static void Sleep(int milliseconds timeout) -
This method is used to sleep the current thread for the defined millisecond
period. As the method is static, it is invoked with the class name directly
(Thread. Sleep(2000)).
public void Suspend() - Suspends the thread. It does
not affect if invoked when the thread is already suspended. Also, it throws an
exception when invoked before starting or after the thread is dead.
public void Resume() - Resumes the suspended thread.
It throws an exception when invoked and the thread has not started or when it
is not suspended.
public void Abort() - Terminated the calling thread.
Properties that are frequently accessed.
public string Name { get; set; } - Provides the name
of the thread object. Also, users can assign thread names at run time.
public bool IsAlive { get; } - Provides whether the
thread object is alive. It returns true or false. It is a read-only property.
public ThreadState ThreadState { get; } - Provides
the state of the thread. It returns the state with ThreadState as the return
type.
public ThreadPriority Priority { get; set; } - Users
can assign as well as read the priority of the thread instance using this
property. Priority can be set with the type ThreadPriority(enum).
-----------------------------------------------------------------------------------------------------------------------------
Q) What is the difference between Process and Thread?
A process is started when you start an Application.
A process is a collection of resources like virtual address space, code,
security contexts, etc. A process can start multiple threads. Every process is
start with a single thread called the primary thread. You can create n number of
threads in a process. Threads share the resources allocated to the process.
A process is the parent and threads are his
children.
-----------------------------------------------------------------------------------------------------------------------------
Q)How to start a Thread in C#?
We have to use the Thread class provided by
System. Threading namespace. In the constructor of the class, we have to pass
the method name which we want to run in a separate thread. After that we have to
call the start method of the Thread class.
using System;
using System. Threading;
namespace ConsoleApplication1
{
class
Program
{
static
void Main(string[] args)
{
Thread th = new Thread(ThreadMethod);
th.Start();
}
private static void ThreadMethod()
{
Console.WriteLine("Another Thread");
}
}
-----------------------------------------------------------------------------------------------------------------------------
Q)How to pass parameter in Thread?
In the constructor of Thread, we can pass the method
name which accepts only a single parameter. Then we have to pass the parameter into
the Start method. Below is the example.
static void Main(string[] args)
{
Thread th
= new Thread(ThreadMethod);
th.Start("Hello");
}
private static void ThreadMethod(object args)
{
Console.WriteLine(args.ToString());
}-----------------------------------------------------------------------------------------------------------------------------
Q)What is a volatile keyword?
Volatile is used for serializing the access of
variables without using the synchronization primitives. You can use volatile
with the below types:
References types
Pointer types
Values types
IntPtr
1
public volatile int number;-----------------------------------------------------------------------------------------------------------------------------
Q)How can you share data between multiple threads?
There are two ways to share data between multiple
threads:
Concurrent collection classes
Using Synchronization Primitives-----------------------------------------------------------------------------------------------------------------------------
Q) What are Concurrent Collection Classes?
.NET Framework class library comes with Concurrent collection classes so that multiple threads can share collection data between them without using synchronization primitives.
There are four types of Concurrent classes.
ConcurrentQueue
ConcurrentStack
ConcurrentDictionary
ConcurrentBag-----------------------------------------------------------------------------------------------------------------------------
Q)What is synchronization and why it is important?
We use multiple threads to improve the performance
of our application. When multiple threads shares data between there is a chance
of data corruption. When one thread is writing to the variable another thread
is reading the same variable at the same time there is a chance of reading
corrupt data.-----------------------------------------------------------------------------------------------------------------------------
Q)Can you count some names of Synchronization primitives?
Monitor
Mutex
SpinLock
ReaderWriterLock
Semaphore
AutoResetEvent
ManualResetEvent
InterLocked
CountDownEvent
Barrier-----------------------------------------------------------------------------------------------------------------------------
Q) What is Deadlock?
A deadlock is a situation in which two or more
processes cannot complete their work. They are blocked and each thread waiting
for other threads to release the resources they want.
For example, you have two threads T1 and T2 and you have two resources R1 and R2. Both threads want to work with both resources. But in the opposite fashion, T1 wants to work with R1 first and then with R2. T2 wants to work with R2 first and then with R1.
Both threads start at the same time. T1 locked R1
while at the same time T2 locked R2. Now T1 wants a lock on R2 which is already
locked by T2 and T2 wants a lock on R1 which is already locked by T1. Both
threads waiting for other threads to unlock the resources. Both threads are
waiting for infinite time and can't continue forever.
Types of necessary conditions for Deadlock
Mutual Exclusion: Resources involved must be unshareable between multiple threads.
Hold and Wait: Threads hold the resources they have
allocated and waiting for the resources they want.
No pre-emption: If the thread locks the resource, other
threads cannot take the resource until the thread releases it.
Circular Wait: A circular chain must exist in which
each thread waiting for other threads to release resources.-----------------------------------------------------------------------------------------------------------------------------
Q)What is LiveLock?
A livelock is very similar to deadlock except for involved threads states are continually changing their state but still, they
cannot complete their work.
A real-world example of livelock occurs when two people meet in a narrow corridor, and each tries to be polite by moving aside to let the other pass, but they end up swaying from side to side without making any progress because they both repeatedly move the same way at the same time.
Suppose one thread has odd numbers like 1,3,5 and the other thread has even numbers 2,4,6. How can you synchronize between them and print the numbers in order?
We have to take two AutoResetEvents which each
signal each other after they print one number. Below is the full code.
using System;
using System. Threading;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class
Program
{
static
AutoResetEvent auto1 = new AutoResetEvent(false);
static AutoResetEvent auto2 = new AutoResetEvent(false);
static
void Main(string[] args)
{
var t1 = Task.Factory.StartNew(() => PrintOddNumbers());
var t2 = Task.Factory.StartNew(() => PrintEvenNumbers());
Task.WaitAny(t1, t2);
Console.WriteLine("End");
Console.ReadLine();
}
static
void PrintOddNumbers()
{
int[] arr = new int[] { 1, 3, 5, 7, 9, 11, 13, 15 };
foreach (var item in arr)
{
Console.WriteLine(item);
auto2.Set();
auto1.WaitOne();
}
}
static
void PrintEvenNumbers()
{
int[] arr = new int[] { 2, 4, 6, 8, 10, 12, 14 };
foreach (var item in arr)
{
auto2.WaitOne();
Console.WriteLine(item);
auto1.Set();
}
auto1.Set();
}
}
}
-----------------------------------------------------------------------------------------------------------------------------
Q) What is an immutable object?
An immutable object is an object which states cannot be changed after creation. Immutable objects are useful in concurrent programming as they are thread-safe.
"String" objects are examples of immutable objects because we can not change the value of a string after it is created.
Below is the code in which we try to change the second index char of string
which gives us an error.
string str = "Hello";
str[0] = 'm'; //Doesn't work; Property or indexer 'string.this[int]' cannot be assigned to --it is read-only
Why are the keywords necessary for supporting immutable objects?
There are two keywords provided by CLR.
const
read-only
static void Main(string[] args)
{
Person p1 = new Person(1, "Name 1");
}
public class Person
{
private
readonly int id;
private readonly string name;
public
Person(int id, string name)
{
this.id = id;
this.name = name;
}
}-----------------------------------------------------------------------------------------------------------------------------
Q) What is AutoResetEvent?
AutoResetEvent is a synchronization mechanism that works on a bool variable. If the bool variable is false then the thread is blocked. If the bool variable is true then the thread is unblocked.
AutoResetEvent contains two main methods:
WaitOne() : Blocks the current thread
Set() : Unblock the current thread
Reset() : Sets the state of the event to non-signaled.
using System;
using System. Threading;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class
Program
{
static
AutoResetEvent autoEvent = new AutoResetEvent(false);
static
void Main(string[] args)
{
Task.Factory.StartNew(() =>
{
CalculateSum(50);
});
Thread.Sleep(3000);
autoEvent.Set();
Console.ReadLine();
}
public static void CalculateSum(int maxNumber)
{
int sum = 0;
for (int i = 0; i <= maxNumber; ++i)
{
sum += i;
}
Console.WriteLine("Sum Calculated. Waiting for Main thread to send
signal to unblock me");
autoEvent.WaitOne();
Console.WriteLine("Sum: " + sum);
}
}
}
}
-----------------------------------------------------------------------------------------------------------------------------
Synchronous execution: doing
things one after the other
The user
clicks a button and waits for the application to finish handling the click
event. Since only
one
thing can happen at a time, the UI stops responding until the event has been
completely handled. In
the same
way, the application can’t do anything in the background while UI is available
for user input.
Concurrent: doing multiple things at the same time
The user
clicks a button, and the application triggers a separate thread in the
background to execute
the task
needed to satisfy user’s request concurrently. The thread responsible for
handling UI events
becomes
available again immediately after starting the background thread, keeping the
UI responsive.
Parallel: doing multiple copies
of something at the same time
The user
instructs the application to process all the files in a folder. The application
triggers a
number
of threads with the processing logic and distributes the files among these
threads.
Asynchronous: not having to wait
for one task to finish before starting another
The
application starts a database query asynchronously. While the query is in
progress, it also starts
reading
a file asynchronously. While both tasks are in progress, it does some
calculation.
When all
these tasks are finished, it uses the results of all these three operations to
update the UI.
The
execution thread should not wait for an I/O-bound or CPU-bound task to finish.
Examples
of I/O-bound operations can be file system access, DB access, or an HTTP
request. Examples of CPU-bound operations can be resizing an image, converting
a document, or encrypting/decrypting data.
Benefits
Using
asynchronous programming has several benefits:
avoiding
thread pool starvation by “pausing” execution and releasing the thread back to
thread pool
during
asynchronous activities
keeping
the UI responsive
possible
performance gains from concurrency
Task-based
asynchronous pattern (TAP): RECOMMENDED
We have
only an OperationNameAsync method that returns a Task or a generic
Task<T> object:
public class MyClass {
public
Task<int> ReadAsync(byte [] buffer, int offset, int count) {...};
}
Task and
Task<T> classes model asynchronous operations in TAP. It’s important to
understand Task and
Task<T>
classes for understanding TAP, which is important for understanding and using
async/await
keywords,
so let’s talk about these two classes in more detail.
ask and
Task<T>
The Task
and Task<T> classes are the core of asynchronous programming in .NET.
They facilitate all
kinds of
interactions with the asynchronous operation they represent, such as:
adding
continuation tasks
blocking
the current thread to wait until the task is completed
signaling
cancellation (via CancellationTokens)
After
starting an asynchronous operation and getting a Task or Task<T> object,
you can keep using the
current
execution thread to asynchronously execute other instructions that don’t need
the result of the
task, or
interact with the task as needed.
Ex:
using System;
using System.Threading.Tasks;
public class Example {
public
static void Main() {
Task<DataType> getDataTask = Task.Factory.StartNew(() => {
return GetData(); } );
Task<ProcessedDataType> processDataTask =
getDataTask.ContinueWith((data) => { return
ProcessData(data);} );
Task
saveDataTask = processDataTask.ContinueWith((pData) => { SaveData(pData)} );
Task<string> displayDataTask =
processDataTask.ContinueWith((pData) => { return
CreateDisplayString(pData); } );
Console.WriteLine(displayDataTask.Result);
saveDataTask.Wait();
}
}
Almost Good
As
demonstrated above, TAP and Task/Task<T> classes are pretty powerful for
applying asynchronous
programming
techniques. But there’s still room for improvement:
Boilerplate
code needed for using tasks is quite verbose.
Assigning
continuations and making granular decisions about which task should run means a
lot of
details
should be handled by the programmer, increasing the complexity and making the
code error-prone.
(Verbosity,
combined with increased complexity, means the code will be difficult to
understand, thus
difficult
to maintain.)
Despite
all this power, there’s no way to wait for a task to complete without blocking
the execution
thread.
These
drawbacks can become significant challenges for teams to adopt TAP.
This is
where the async and await keywords come into play.
async
and await
These
keywords have been introduced in response to these challenges of using the Task
and Task<T>
classes.
They do not represent yet another way of asynchronous programming; they use
Task and Task<T>
classes
under the hood, simplifying the application of TAP while maintaining the power
Task classes
provide
to the programmer when needed.
Let’s
take a look at each one.
async
The
async keyword is added to the method signature to enable the usage of the await
keyword in the
method.
It also instructs the compiler to create a state machine to handle
asynchronicity, but that’s
out of
the scope of this article.
The
return type of an async method is always Task or Task<T>. It’s checked by
the compiler, so there’s
not much
room for making mistakes here.
await
The
await keyword is used to asynchronously wait for a Task or Task<T> to
complete. It pauses the
execution
of the current method until the asynchronous task that’s being awaited
completes. The
difference
from calling.Result or .Wait() is that the await keyword sends the current
thread back to
the thread pool,
instead of keeping it in a blocked state.-----------------------------------------------------------------------------------------------------------------------------
How to reverse a given number in C#?
using System;
namespace LogicalPrograms
{
public
class Program
{
static
void Main(string[] args)
{
Console.Write("Enter a Number : ");
int number = int.Parse(Console.ReadLine());
int reminder, reverse = 0;
while (number > 0)
{
//Get the remainder by dividing the number with 10
reminder = number % 10;
//multiply the sum with 10 and then add the reminder
reverse = (reverse * 10) + reminder;
//Get the quotient by dividing the number with 10
number = number / 10;
}
Console.WriteLine($"The Reverse order is : {reverse}");
Console.ReadKey();
}
}
}
Reverse a String in C# without using Built-in
method:
using System;
namespace LogicalPrograms
{
class
Program
{
static
void Main(string[] args)
{
Console.Write("Enter a String : ");
string originalString = Console.ReadLine();
string reverseString = string.Empty;
for (int i = originalString.Length - 1; i >= 0; i--)
{
reverseString += originalString[i];
}
Console.Write($"Reverse String is :
{reverseString} ");
Console.ReadLine();
}
}
}
Using
the for-each loop to reverse a string in C#:
using System;
namespace LogicalPrograms
{
class
Program
{
static
void Main(string[] args)
{
Console.Write("Enter a String : ");
string originalString = Console.ReadLine();
string reverseString = string.Empty;
foreach (char c in originalString)
{
reverseString = c + reverseString;
}
Console.Write($"Reverse String is : {reverseString} ");
Console.ReadLine();
}
}
}
///Need
one extra array for result, need to traverse full array.
public static stringReverseString1(string str)
{
char[]
chars = str.ToCharArray();
char[]
result = newchar[chars.Length];
for (int i
= 0, j = str.Length - 1; i < str.Length; i++, j--) {
result[i] = chars[j];
}
return new
string(result);
}
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
Swapping two numbers using a third variable in C#:
using System;
namespace LogicalPrograms
{
public
class Program
{
public
static void Main()
{
int number1 = 10, number2 = 20, temp = 0;
Console.WriteLine($"Before SWapping number1= {number1}, number2 =
{number2}");
temp = number1; //temp=10
number1 = number2; //number1=20
number2 = temp; //number2=10
Console.WriteLine($"After swapping number1= {number1}, number2 =
{number2}");
Console.ReadKey();
}
}
}
Swap two integers without using the third variable
in C#
There are two ways you can use to swap two numbers
without using the third variable:
By using * and /
By using + and –
using System;
namespace LogicalPrograms
{
public
class Program
{
public
static void Main()
{
int number1 = 10, number2 = 20;
Console.WriteLine($"Before SWapping number1= {number1}, number2 =
{number2}");
number1 = number1 * number2; //number1=200 (10*20)
number2 = number1 / number2; //number2=10 (200/20)
number1 = number1 / number2; //number1=20 (200/10)
Console.WriteLine($"After swapping number1= {number1}, number2 =
{number2}");
Console.ReadKey();
}
}
}
using System;
namespace LogicalPrograms
{
public
class Program
{
public
static void Main()
{
int number1 = 10, number2 = 20;
Console.WriteLine($"Before SWapping number1= {number1}, number2 =
{number2}");
number1 = number1 + number2; //number1=30 (10+20)
number2 = number1 - number2; //number2=10 (30-20)
number1 = number1 - number2; //number1=20 (30-10)
Console.WriteLine($"After swapping number1= {number1}, number2 =
{number2}");
Console.ReadKey();
}
}
}
The following program swaps two strings without using the third variable in C#.
using System;
namespace LogicalPrograms
{
public
class Program
{
public
static void Main()
{
string name1 = "Dotnet", name2 = "Tutorials";
Console.WriteLine($"Before SWapping name1= {name1}, name2 =
{name2}");
//
Step1: append 2nd string with the 1st string
name1 = name1 + name2;
//Step2: store intial string name1 in string name2
name2
= name1.Substring(0, name1.Length - name2.Length);
//Step3: store initial string
name2 in string name1
name1 = name1.Substring(name2.Length);
Console.WriteLine($"After swapping name1= {name1}, name2 =
{name2}");
Console.ReadKey();
}
}
}----------------------------------------------------------------------------------------------------------------------------------------------------------------------
How to check if a given number is prime or not in
C#?
The following example takes one input from the
console and then checks whether that number is a prime number or not.
using System;
namespace LogicalPrograms
{
public
class Program
{
static
void Main(string[] args)
{
Console.Write("Enter a Number : ");
int number = int.Parse(Console.ReadLine());
bool IsPrime = true;
for (int i = 2; i < number/2; i++)
{
if (number % i == 0)
{
IsPrime = false;
break;
}
}
if
(IsPrime)
{
Console.Write("Number is
Prime.");
}
else
{
Console.Write("Number is not Prime.");
}
Console.ReadKey();
}
}
}
How to display Prints the Prime Numbers between a
range of numbers in C#?
In the following example, we will take two numbers
from the console and then print the prime numbers present between those two
numbers.
using System;
namespace LogicalPrograms
{
public
class Program
{
static
void Main(string[] args)
{
Console.Write("Enter The Start Number: ");
int startNumber = int.Parse(Console.ReadLine());
Console.Write("Enter the End Number : ");
int endNumber = Convert.ToInt32(Console.ReadLine());
Console.WriteLine($"The Prime Numbers between {startNumber} and
{endNumber} are : ");
for (int i = startNumber; i <= endNumber; i++)
{
int counter = 0;
for (int j = 2; j <= i / 2; j++)
{
if (i % j == 0)
{
counter++;
break;
}
}
if (counter == 0 && i != 1)
{
Console.Write("{0} ", i);
}
}
Console.ReadKey();
}
}
}----------------------------------------------------------------------------------------------------------------------------------------------------------------------
How to check if a given number is Palindrome or not
in C#?
Algorithm to check Palindrome Number in C#:
First, get the number from the user which you want
to check
Hold that number in a temporary variable
Reverse that number
Compare the temporary number with the reversed
number
If both numbers are the same, then print it is a
palindrome number else print it is not a palindrome number
Example: Palindrome Number Program in C#
The following C# Program will allow the user to
input a number and then checks whether that number is a Palindrome Number or
not.
using System;
namespace LogicalPrograms
{
public
class Program
{
static
void Main(string[] args)
{
Console.Write("Enter a Number To Check Palindrome : ");
int number = int.Parse(Console.ReadLine());
int remineder, sum = 0;
int temp = number;
while (number > 0)
{
//Get the remainder by dividing the number with 10
remineder = number % 10;
//multiply the sum with 10 and then add the remainder
sum = (sum * 10) + remineder;
//Get the quotient by dividing the number with 10
number = number / 10;
}
if
(temp == sum)
{
Console.WriteLine($"Number {temp} is Palindrome.");
}
else
{
Console.WriteLine($"Number {temp} is not Palindrome");
}
Console.ReadKey();
}
}
}
Output:
How to check if a given number is Palindrome or not?
How to check if a given string is Palindrome or not
in C#?
In the following program, we take the string as an
input from the console. Then we reverse the string using for loop and storing
the reverse string value in the reverse variable. Finally, we check whether the
original and reverse values are the same or not. If both are the same then the
string is Palindrome else it is not Palindrome.
using System;
namespace LogicalPrograms
{
public
class Program
{
static
void Main(string[] args)
{
Console.Write("Enter a string to Check Palindrome : ");
string name = Console.ReadLine();
string reverse = string.Empty;
for (int i = name.Length - 1; i >= 0; i--)
{
reverse += name[i];
}
if
(name == reverse)
{
Console.WriteLine($"{name} is Palindrome.");
}
else
{
Console.WriteLine($"{name} is not Palindrome");
}
Console.ReadKey();
}
}
}
Using the for-each loop:
using System;
namespace LogicalPrograms
{
public
class Program
{
static void Main()
{
Console.Write("Enter a string to Check Palindrome : ");
string name = Console.ReadLine();
string reverse = string.Empty;
foreach (char c in name)
{
reverse = c + reverse;
}
if
(name.Equals(reverse, StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine($"{name} is Palindrome");
}
else
{
Console.WriteLine($"{name} is not
Palindrome");
}
Console.ReadKey();
}
}
}----------------------------------------------------------------------------------------------------------------------------------------------------------------------
Factorial Number Program in C# using for loop:
using System;
namespace LogicalPrograms
{
class
Program
{
static
void Main(string[] args)
{
Console.Write("Enter a Number : ");
int number = int.Parse(Console.ReadLine());
int factorial = 1;
for (int i = 1; i <= number; i++)
{
factorial = factorial * i;
}
Console.Write($"Factorial of {number} is: {factorial}");
Console.ReadLine();
}
}
}
Factorials of a number using while loop in C#:
using System;
namespace LogicalPrograms
{
class
Program
{
static
void Main(string[] args)
{
Console.Write("Enter a Number : ");
int number = int.Parse(Console.ReadLine());
long factorial = 1;
while (number != 1)
{
factorial = factorial * number;
number = number - 1;
}
Console.Write($"Factorial is: {factorial}");
Console.ReadLine();
}
}
}
Factorial of a number using Recursive Function in
C#:
using System;
namespace LogicalPrograms
{
class
Program
{
static
void Main(string[] args)
{
Console.Write("Enter a Number : ");
int number = int.Parse(Console.ReadLine());
long factorial = RecursiveFactorial(number);
Console.Write($"Factorial of {number} is: {factorial}");
Console.ReadLine();
}
static
long RecursiveFactorial(int number)
{
if
(number == 1)
{
return 1;
}
else
{
return number * RecursiveFactorial(number - 1);
}
}
}
}
Factorial of a number using the do-while loop in C#:
using System;
namespace LogicalPrograms
{
class
Program
{
static
void Main(string[] args)
{
Console.Write("Enter a Number : ");
int number = int.Parse(Console.ReadLine());
long factorial = 1;
do
{
factorial = factorial * number;
number--;
}
while (number > 0);
Console.Write($"The Factorial is: {factorial}");
Console.ReadLine();
}
}
}----------------------------------------------------------------------------------------------------------------------------------------------------------------------
Armstrong Number Program in C# with Examples
using System;
namespace LogicalPrograms
{
class
Program
{
static
void Main(string[] args)
{
int i = 0;
int digitCount = 0;
int[] digitArray = new int[10];
double sum = 0;
//Step1: Take the input
Console.Write("Enter the Number : ");
int number = int.Parse(Console.ReadLine());
//Step3: Store the number in a temporary variable
int temporaryNumber = number;
//Step3: Find the total number of digits in number as well as
//Store each each digit in the digit array
while (number > 0)
{
digitArray[i++] = number % 10;
number = number / 10;
digitCount++;
}
//Step4: Calculate the result
for (i = 0; i < digitCount; i++)
{
sum += Math.Pow(digitArray[i], digitCount);
}
//Step5: Check whether it is prime number or not
if
(sum == temporaryNumber)
{
Console.WriteLine($"The Number {temporaryNumber} is
armstrong");
}
else
{
Console.WriteLine($"The Number {temporaryNumber} is not
armstrong");
}
Console.ReadLine();
}
}
}
Output:
Armstrong Number in C#
Finding Armstrong number between ranges of numbers
in C#:
using System;
namespace LogicalPrograms
{
class
Program
{
static
void Main(string[] args)
{
Console.Write("Enter the Start Number : ");
int StartNumber = int.Parse(Console.ReadLine());
Console.Write("Enter the End Number : ");
int EndNumber = int.Parse(Console.ReadLine());
Console.WriteLine($"The Armstrong Numbers between {StartNumber} and
{EndNumber} are : ");
for (int i = StartNumber; i <= EndNumber; i++)
{
if (IsArmstrongNumber(i))
Console.WriteLine(i);
}
Console.ReadLine();
}
static
bool IsArmstrongNumber(int number)
{
int sum = 0;
int temporaryNumber = number;
int temp = 0;
int length = number.ToString().Length;
while (number != 0)
{
temp = number % 10;
number = number / 10;
sum += (int)Math.Pow(temp, length);
}
if
(sum == temporaryNumber)
{
return true;
}
else
{
return false;
}
}
}
}----------------------------------------------------------------------------------------------------------------------------------------------------------------------
Algorithm: Sum of Digits Program in C#
using System;
namespace LogicalPrograms
{
public class Program
{
static void Main(string[] args)
{
Console.Write("Enter the
Number : ");
int number =
int.Parse(Console.ReadLine());
int sum = 0, reminder;
while (number > 0)
{
reminder = number % 10;
sum = sum + reminder;
number = number / 10;
}
Console.WriteLine($"The Sum of
Digits is : {sum}");
Console.ReadKey();
}
}
}
Finding the sum of digits of a given
number using a loop in C#
using System;
namespace LogicalPrograms
{
public class Program
{
static void Main(string[] args)
{
Console.Write("Enter the
Number : ");
int number =
int.Parse(Console.ReadLine());
int sum = SumOfDigits(number);
Console.WriteLine($"The Sum of
Digits is : {sum}");
Console.ReadKey();
}
static int SumOfDigits(int number)
{
if (number != 0)
{
return (number % 10 +
SumOfDigits(number / 10));
}
else
{
return 0;
}
}
}
}
Using Linq to find the sum of digits of
a number in C#:
using System;
using System.Linq;
namespace LogicalPrograms
{
public class Program
{
static void Main(string[] args)
{
Console.Write("Enter the
Number : ");
int number =
int.Parse(Console.ReadLine());
int sum =
number.ToString().Select(digit =>
int.Parse(digit.ToString())).ToArray().Sum();
Console.WriteLine($"The Sum of
Digits is : {sum}");
Console.ReadKey();
}
}----------------------------------------------------------------------------------------------------------------------------------------------------------------------

No comments:
Post a Comment