You are on page 1of 19

DataReader

DataReader as the name suggests reads data. DataReader is used for fetching records from the SQL Query
or Stored Procedure i.e. SELECT Operation.
DataReader is the fastest technique to fetch records from database and it works only in Forward direction
meaning a row read once cannot be read again.
DataReader is ReadOnly and it fetches one row at a time in memory and hence it has less load on memory.
The Read function of the DataReader reads one row at a time in memory and if a row is read then the
function returns True else False.
DataReader requires an open connection in order to execute the SQL statement.
Example would be fetching Name City for all records in the Person Table using DataReader.
C#
string constring = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;
using (SqlConnection con = new SqlConnection(constring))
{
using (SqlCommand cmd = new SqlCommand("SELECT Name, City FROM Persons", con))
{
cmd.CommandType = CommandType.Text;
con.Open();
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
string name = dr["Name"].ToString();
string city = dr["City"].ToString();
Response.Write("Name: " + name);
Response.Write("City: " + city);
}
con.Close();
}
}

DataAdapter
DataAdapter is used to execute SQL statements and is used to populate the results of SQL Query into a
DataSet or DataTable.
DataAdapter gets all the rows of the executed SQL statement at once and populates into DataSet or
DataTable in memory and hence DataAdapter is bit slower compared to DataReader.
Since the DataAdapter populates all rows in DataSet or DataTable it can be traversed in both Forward and
Backward directions.
DataAdapter makes use of the Fill function to populate the rows of SQL statement into a DataSet or
DataTable.
DataAdapter manages the connection internally and does not require to open or close connections
explicitly and this feature is termed as Disconnected Architecture.
Example would be fetching Name City for all records in the Person Table using DataAdapter.
C#
string constring = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;
using (SqlConnection con = new SqlConnection(constring))
{
using (SqlCommand cmd = new SqlCommand("SELECT Name, City FROM Persons", con))
{
cmd.CommandType = CommandType.Text;
using (SqlDataAdapter sda = new SqlDataAdapter(cmd))
{
DataSet ds = new DataSet();
sda.Fill(ds);
foreach (DataRow row in ds.Tables[0].Rows)
{
string name = row["Name"].ToString();
string city = row["City"].ToString();
Response.Write("Name: " + name);
Response.Write("City: " + city);
}
}
}
}

DataSet
DataSet is in simple terms set of Data i.e. set of DataTables or collection of DataTables i.e. it can hold one
or multiple DataTables.
DataSet is mainly used to fetch and hold the records for one or more tables into memory.
A DataAdapter is used to populate DataSet from records returned from an SQL statement and also a
DataSet can be created in memory and tables and data can be added to it.
DataSet can also be converted and saved as XML file.
Example would be fetching Name City for all records in the Person Table into a DataSet.
string constring = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;
using (SqlConnection con = new SqlConnection(constring))
{
using (SqlCommand cmd = new SqlCommand("SELECT Name, City FROM Persons", con))
{
cmd.CommandType = CommandType.Text;
using (SqlDataAdapter sda = new SqlDataAdapter(cmd))
{
DataSet ds = new DataSet();
sda.Fill(ds);
foreach (DataRow row in ds.Tables[0].Rows)
{
string name = row["Name"].ToString();
string city = row["City"].ToString();
Response.Write("Name: " + name);
Response.Write("City: " + city);
}
}
}
}

DataTable
A DataTable can hold records of a single Table consisting of rows and columns. A DataTable can be reside
within a DataSet.
DataTable is mainly used to fetch and hold the records of one single table into memory.
A DataAdapter is used to populate DataTable from records returned from an SQL statement and also a
DataTable can be created in memory and data can be added to it.
Example would be fetching Name City for all records in the Person Table into a DataTable.
C#
string constring = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;
using (SqlConnection con = new SqlConnection(constring))
{
using (SqlCommand cmd = new SqlCommand("SELECT Name, City FROM Persons", con))
{
cmd.CommandType = CommandType.Text;
using (SqlDataAdapter sda = new SqlDataAdapter(cmd))
{
DataTable dt = new DataTable();
sda.Fill(dt);
foreach (DataRow row in dt.Rows)
{
string name = row["Name"].ToString();
string city = row["City"].ToString();
Response.Write("Name: " + name);
Response.Write("City: " + city);
}
}
}
}

Asp.net developer uses DataSet and DataReader to fetch data from the data source while
developing asp.net application. But most of them dont know exactly what are the main
difference between DataSet and DataReader and what to use and when to use out of these
two.

Both DataSet and DataReader are widely used in asp.net applications for the same
purpose i.e. to get/fetch the data from the database. But one has to know the best
practices in developing fast, reliable and scalable application. So I have tried to list some
main differences between the DataSet and DataReader which are as follows:

DataSet Vs DataReader

1. DataReader is used to retrieve read-only (cannot update/manipulate data back to


datasource) and forward-only (cannot read backward/random) data from a database. It
provides the ability to expose the data from database while DataSet is a collection of in-
memory tables.

2. DataReader fetches the records from database and stores in the network buffer and
gives whenever requests. It releases the records as query executes and do not
wait for the entire query to execute. Hence very fast as compare to the DataSet which
releases the data after loading all the data in memory.

3. DataReader is like a forward only recordset. It fetches one row at a time so very less
network cost compare to DataSet which fetches all the rows at a time i.e. it fetches all data
from the datasource at a time to its memory area.

4. As one row at a time is stored in memory in DataReader it increases application


performance and reduces system overheads while there is more system overheads in
DataSet as it fetches all the data from the datasource at a time in memory.

5. As DataReader is forward only, we cant fetch random records as we cant move


back and forth .While in DataSet we can move back and forth and fetch records randomly
as per requirement.

6. DataReader fetches data from a single table while DataSet can fetch data from
multiple tables.

7. As DataReader can have data from a single table so no relationship can be maintained
while relationship between multiple tables can be maintained in DataSet.

8. DataReader is read only so no transaction like insert, update and delete is possible
while these transactions are possible in DataSet.

9. DataSet is a bulky object that requires lot of memory space as compared to


DataReader .

10. DataReader is a connected architecture: The data is available as long as the


connection with database exists while DataSet is a disconnected architecture that
automatically opens the connection, fetches the data into memory and closes the
connection when done.
11. DataReader requires connection to be open and close manually in code while DataSet
automatically handles it.
12. DataSet can be serialized and represented in XML so easily passed around to other
tiers but DataReader can't be serialized.

13. DataReader will be the best choice where we need to show the data to the user which
requires no manipulation while DataSet is best suited where there is possibility of
manipulation on the data.

14. Since DataSet can be serialized it, can be used in wcf services and web service that
will return retrieved data. But DataReader cant be serialized so cant be used in wcf
services and web services.

15. When you need to navigate through the data multiple times then DataSet is better
choice e.g. we can fill data in multiple controls But DataReader can only be read once so
it can be bound to a single control and requires data to be retrieved for each control.
C# supports two types of constructor, a class constructor (static constructor) and an
instance constructor (non-static constructor).

Static constructor is used to initialize static data members as soon as the class is
referenced first time, whereas an instance constructor is used to create an instance of
that class with <new> keyword. A static constructor does not take access modifiers or
have parameters and can't access any non-static data member of a class.

Since static constructor is a class constructor, they are guaranteed to be called as soon
as we refer to that class or by creating an instance of that class.

You may say, why not initialize static data members where we declare them in the code.
Like this :

private static int id = 10;


private static string name = "jack";

Static data members can certainly be initialized at the time of their declaration but there
are times when value of one static member may depend upon the value of another static
member. In such cases we definitely need some mechanism to handle conditional
initialization of static members. To handlesuch situation, C# provides static constructor.

Let me explain you with examples :

//File Name : Test.cs


using System;
namespace Constructor
{
class Test
{
//Declaration and initialization of static data member
private static int id = 5;
public static int Id
{
get
{
return id;
}
}

static void Main(string[] args)


{
//Print the value of id
Test.print();
}
}
}

In the above example, static data member <id> is declared and initialized in same
line. So if you compile and run this program your output would look similar to
this :

Test.id = 5
Lets create one more class similar to class Test but this time the value of its static
data member would depend on the value of static data member <id> of class
Test.id.

//File Name : Test1.cs


using System;
namespace Constructor
{
class Test1
{
private static int id ;
//Static constructor, value of data member id is set conditionally here.
//This type of initialization is not possible at the time of declaration.
static Test1()
{
if( Test.Id < 10 )
{
id = 20;
}
else
{
id = 100;
}
Console.WriteLine("Static<Class> Constructor for Class Test1
Called..");
}
public static void print()
{
Console.WriteLine("Test1.id = " + id);
}
static void Main(string[] args)
{
//Print the value of id
Test1.print();
}
}
}

As you can see in the above static constructor, static data member <id> is initialized
conditionally. This type of initialization is not possible at the time of declaration. This is
where static constructor comes in picture. So if you compile and run this program your
output would look similar to this :

Static<Class> Constructor for Class Test1 Called..


id = 20

Since <id> in class Test was initialized with a value of 5, therefore <id> in class Test1 got
initialized to a value of 20.

Some important point regarding static constructor from C# Language Specification and
C# Programmer's Reference :

1) The static constructor for a class executes before any instance of the class is created.
2) The static constructor for a class executes before any of the static members for the
class are referenced.
3) The static constructor for a class executes after the static field initializers (if any) for
the class.
4) The static constructor for a class executes at most one time during a single program
instantiation
5) A static constructor does not take access modifiers or have parameters.
6) A static constructor is called automatically to initialize the class before the first
instance is created or any static members are referenced.
7) A static constructor cannot be called directly.
8) The user has no control on when the static constructor is executed in the program.
9) A typical use of static constructors is when the class is using a log file and the
constructor is used to write entries to this file.
--------------------------------------------------------------------------------------------------------------
You can redefine or overload most of the built-in operators available in C#.
Thus a programmer can use operators with user-defined types as well.
Overloaded operators are functions with special names the
keyword operatorfollowed by the symbol for the operator being defined.
similar to any other function, an overloaded operator has a return type
and a parameter list.
For example, go through the following function
public static Box operator+ (Box b, Box c) {
Box box = new Box();
box.length = b.length + c.length;
box.breadth = b.breadth + c.breadth;
box.height = b.height + c.height;
return box;
}
The above function implements the addition operator (+) for a user-
defined class Box. It adds the attributes of two Box objects and returns
the resultant Box object.
Implementing the Operator Overloading
The following program shows the complete implementation
using System;
namespace OperatorOvlApplication {
class Box {
private double length; // Length of a box
private double breadth; // Breadth of a box
private double height; // Height of a box

public double getVolume() {


return length * breadth * height;
}
public void setLength( double len ) {
length = len;
}
public void setBreadth( double bre ) {
breadth = bre;
}
public void setHeight( double hei ) {
height = hei;
}

// Overload + operator to add two Box objects.


public static Box operator+ (Box b, Box c) {
Box box = new Box();
box.length = b.length + c.length;
box.breadth = b.breadth + c.breadth;
box.height = b.height + c.height;
return box;
}
}

class Tester {
static void Main(string[] args) {
Box Box1 = new Box(); // Declare Box1 of type Box
Box Box2 = new Box(); // Declare Box2 of type Box
Box Box3 = new Box(); // Declare Box3 of type Box
double volume = 0.0; // Store the volume of a box here

// box 1 specification
Box1.setLength(6.0);
Box1.setBreadth(7.0);
Box1.setHeight(5.0);

// box 2 specification
Box2.setLength(12.0);
Box2.setBreadth(13.0);
Box2.setHeight(10.0);

// volume of box 1
volume = Box1.getVolume();
Console.WriteLine("Volume of Box1 : {0}", volume);

// volume of box 2
volume = Box2.getVolume();
Console.WriteLine("Volume of Box2 : {0}", volume);

// Add two object as follows:


Box3 = Box1 + Box2;

// volume of box 3
volume = Box3.getVolume();
Console.WriteLine("Volume of Box3 : {0}", volume);
Console.ReadKey();
}
}
}
When the above code is compiled and executed, it produces the following
result
Volume of Box1 : 210
Volume of Box2 : 1560
Volume of Box3 : 5400

Overloadable and Non-Overloadable


Operators
The following table describes the overload ability of the operators in C#
Sr.No. Operators & Description

1 +, -, !, ~, ++, --
These unary operators take one operand and can be overloaded.

2 +, -, *, /, %
These binary operators take one operand and can be overloaded.

3 ==, !=, <, >, <=, >=


The comparison operators can be overloaded.

4 &&, ||
The conditional logical operators cannot be overloaded directly.

5 +=, -=, *=, /=, %=


The assignment operators cannot be overloaded.

6 =, ., ?:, ->, new, is, sizeof, typeof


These operators cannot be overloaded.
Generics allow you to delay the specification of the data type of programming
elements in a class or a method, until it is actually used in the program. In other
words, generics allow you to write a class or method that can work with any data
type.
You write the specifications for the class or the method, with substitute parameters
for data types. When the compiler encounters a constructor for the class or a
function call for the method, it generates code to handle the specific data type. A
simple example would help understanding the concept
using System;
using System.Collections.Generic;

namespace GenericApplication {

public class MyGenericArray<T> {


private T[] array;

public MyGenericArray(int size) {


array = new T[size + 1];
}

public T getItem(int index) {


return array[index];
}

public void setItem(int index, T value) {


array[index] = value;
}
}

class Tester {
static void Main(string[] args) {

//declaring an int array


MyGenericArray<int> intArray = new MyGenericArray<int>(5);

//setting values
for (int c = 0; c < 5; c++) {
intArray.setItem(c, c*5);
}

//retrieving the values


for (int c = 0; c < 5; c++) {
Console.Write(intArray.getItem(c) + " ");
}

Console.WriteLine();

//declaring a character array


MyGenericArray<char> charArray = new MyGenericArray<char>(5);

//setting values
for (int c = 0; c < 5; c++) {
charArray.setItem(c, (char)(c+97));
}

//retrieving the values


for (int c = 0; c< 5; c++) {
Console.Write(charArray.getItem(c) + " ");
}
Console.WriteLine();

Console.ReadKey();
}
}
}
When the above code is compiled and executed, it produces the following result
0 5 10 15 20
a b c d e

Features of Generics
Generics is a technique that enriches your programs in the following ways
It helps you to maximize code reuse, type safety, and performance.
You can create generic collection classes. The .NET Framework class
library contains several new generic collection classes in
the System.Collections.Generic namespace. You may use these generic
collection classes instead of the collection classes in
the System.Collectionsnamespace.
You can create your own generic interfaces, classes, methods, events, and
delegates.
You may create generic classes constrained to enable access to methods on
particular data types.
You may get information on the types used in a generic data type at run-
time by means of reflection.
Generic Methods
In the previous example, we have used a generic class; we can declare a generic
method with a type parameter. The following program illustrates the concept
using System;
using System.Collections.Generic;

namespace GenericMethodAppl {

class Program {

static void Swap<T>(ref T lhs, ref T rhs) {


T temp;
temp = lhs;
lhs = rhs;
rhs = temp;
}

static void Main(string[] args) {


int a, b;
char c, d;
a = 10;
b = 20;
c = 'I';
d = 'V';

//display values before swap:


Console.WriteLine("Int values before calling swap:");
Console.WriteLine("a = {0}, b = {1}", a, b);
Console.WriteLine("Char values before calling swap:");
Console.WriteLine("c = {0}, d = {1}", c, d);

//call swap
Swap<int>(ref a, ref b);
Swap<char>(ref c, ref d);

//display values after swap:


Console.WriteLine("Int values after calling swap:");
Console.WriteLine("a = {0}, b = {1}", a, b);
Console.WriteLine("Char values after calling swap:");
Console.WriteLine("c = {0}, d = {1}", c, d);

Console.ReadKey();
}
}
}

When the above code is compiled and executed, it produces the following result
Int values before calling swap:
a = 10, b = 20
Char values before calling swap:
c = I, d = V
Int values after calling swap:
a = 20, b = 10
Char values after calling swap:
c = V, d = I
Collection classes are specialized classes for data storage and retrieval. These
classes provide support for stacks, queues, lists, and hash tables. Most collection
classes implement the same interfaces.
Collection classes serve various purposes, such as allocating memory dynamically
to elements and accessing a list of items on the basis of an index etc. These classes
create collections of objects of the Object class, which is the base class for all data
types in C#.
Various Collection Classes and Their Usage
The following are the various commonly used classes of
the System.Collection namespace. Click the following links to check their detail.
Sr.No. Class & Description and Useage

1 ArrayList
It represents ordered collection of an object that can
be indexed individually.
It is basically an alternative to an array. However, unlike array you can add
and remove items from a list at a specified position using an index and the
array resizes itself automatically. It also allows dynamic memory allocation,
adding, searching and sorting items in the list.

2 Hashtable
It uses a key to access the elements in the collection.
A hash table is used when you need to access elements by using key, and
you can identify a useful key value. Each item in the hash table has
a key/value pair. The key is used to access the items in the collection.

3 SortedList
It uses a key as well as an index to access the items in a list.
A sorted list is a combination of an array and a hash table. It contains a list
of items that can be accessed using a key or an index. If you access items
using an index, it is an ArrayList, and if you access items using a key , it is a
Hashtable. The collection of items is always sorted by the key value.

4 Stack
It represents a last-in, first out collection of object.
It is used when you need a last-in, first-out access of items. When you add
an item in the list, it is called pushing the item and when you remove it, it is
called popping the item.

5 Queue
It represents a first-in, first out collection of object.
It is used when you need a first-in, first-out access of items. When you add
an item in the list, it is called enqueue and when you remove an item, it is
called deque.

6 BitArray
It represents an array of the binary representation using the values 1 and 0.
It is used when you need to store the bits but do not know the number of bits
in advance. You can access items from the BitArray collection by using
an integer index, which starts from zero.
C# .Net Delegates and Events
The delegate topic seems to be a confusing and tough for most of the developers. In this
article I will explain the basics of delegates and Event handling in C# in a simple
manner.

Delegate is one of the base types in .NET. Delegate is a class, which is used to create
delegate at runtime.

Delegate in C# is similar to a function pointer in C or C++. It's a new type of object in


C#. Delegate is very special type of object as earlier the entire the object we used to
defined contained data but delegate just contains the details of a method.
Need of delegate
There might be situation in which you want to pass methods around to other methods.
For this purpose we create delegate.

A delegate is a class that encapsulates a method signature. Although it can be used in


any context, it often serves as the basis for the event-handling model in C# but can be
used in a context removed from event handling (e.g. passing a method to a method
through a delegate parameter).

One good way of understanding delegates is by thinking of a delegate as


something that gives a name to a method signature.

Example:

public delegate int DelegateMethod(int x, int y);

Any method that matches the delegate's signature, which consists of the return type and
parameters, can be assigned to the delegate. This makes is possible to programmatically
change method calls, and also plug new code into existing classes. As long as you know
the delegate's signature, you can assign your own-delegated method.

This ability to refer to a method as a parameter makes delegates ideal for defining
callback methods.
Delegate magic
In class we create its object, which is instance, but in delegate when we create instance
that is also referred as delegate (means whatever you do you will get delegate).

Delegate does not know or care about the class of the object that it references. Any
object will do; all that matters is that the method's argument types and return type
match the delegate's. This makes delegates perfectly suited for "anonymous" invocation.
Benefit of delegates
In simple words delegates are object oriented and type-safe and very secure as they
ensure that the signature of the method being called is correct. Delegate helps in code
optimization.
Types of delegates
1) Singlecast delegates

2) Multiplecast delegates

Delegate is a class. Any delegate is inherited from base delegate class of .NET class
library when it is declared. This can be from either of the two classes from
System.Delegate or System.MulticastDelegate.
Singlecast delegate
Singlecast delegate point to single method at a time. In this the delegate is assigned to a
single method at a time. They are derived from System.Delegate class.
Multicast Delegate
When a delegate is wrapped with more than one method that is known as a multicast
delegate.

In C#, delegates are multicast, which means that they can point to more than one
function at a time. They are derived from System.MulticastDelegate class.
There are three steps in defining and using delegates:

1. Declaration

To create a delegate, you use the delegate keyword.


[attributes] [modifiers] delegate ReturnType Name ([formal-parameters]);

The attributes factor can be a normal C# attribute.

The modifier can be one or an appropriate combination of the following keywords: new,
public, private, protected, or internal.

The ReturnType can be any of the data types we have used so far. It can also be a type
void or the name of a class.

The Name must be a valid C# name.

Because a delegate is some type of a template for a method, you must use parentheses,
required for every method. If this method will not take any argument, leave the
parentheses empty.

Example:
public delegate void DelegateExample();

The code piece defines a delegate DelegateExample() that has void return type and
accept no parameters.

2. Instantiation
DelegateExample d1 = new DelegateExample(Display);

The above code piece show how the delegate is initiated

3. Invocation
d1();

The above code piece invoke the delegate d1().


Program to demonstrate Singlecast delegate
using System;
namespace ConsoleApplication5
{
class Program
{
public delegate void delmethod();
public class P
{
public static void display()
{
Console.WriteLine("Hello!");
}

public static void show()


{
Console.WriteLine("Hi!");
}

public void print()


{
Console.WriteLine("Print");
}

}
static void Main(string[] args)
{
// here we have assigned static method show() of class P to
delegate delmethod()
delmethod del1 = P.show;
// here we have assigned static method display() of class P to
delegate delmethod() using new operator
// you can use both ways to assign the delagate
delmethod del2 = new delmethod(P.display);

P obj = new P();

// here first we have create instance of class P and assigned


the method print() to the delegate i.e. delegate with class
delmethod del3 = obj.print;

del1();
del2();
del3();
Console.ReadLine();
}
}
}

Program to demonstrate Multicast delegate

using System;

namespace delegate_Example4
{
class Program
{
public delegate void delmethod(int x, int y);

public class TestMultipleDelegate


{
public void plus_Method1(int x, int y)
{
Console.Write("You are in plus_Method");
Console.WriteLine(x + y);
}

public void subtract_Method2(int x, int y)


{
Console.Write("You are in subtract_Method");
Console.WriteLine(x - y);
}
}
static void Main(string[] args)
{
TestMultipleDelegate obj = new TestMultipleDelegate();
delmethod del = new delmethod(obj.plus_Method1);
// Here we have multicast
del += new delmethod(obj.subtract_Method2);
// plus_Method1 and subtract_Method2 are called
del(50, 10);

Console.WriteLine();
//Here again we have multicast
del -= new delmethod(obj.plus_Method1);
//Only subtract_Method2 is called
del(20, 10);
Console.ReadLine();
}
}
}

Point to remember about Delegates:

Delegates are similar to C++ function pointers, but are type safe.
Delegate gives a name to a method signature.
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.
C# version 2.0 introduces the concept of Anonymous Methods, which permit code
blocks to be passed as parameters in place of a separately defined method.
Delegate helps in code optimization.

Usage areas of delegates

The most common example of using delegates is in events.


They are extensively used in threading
Delegates are also used for generic class libraries, which have generic
functionality, defined.

An Anonymous Delegate

You can create a delegate, but there is no need to declare the method associated with it.
You do not have to explicitly define a method prior to using the delegate. Such a method
is referred to as anonymous.

In other words, if a delegate itself contains its method definition it is known as


anonymous method.
Program to show An Anonymous Delegate
using System;
public delegate void Test();
public class Program
{
static int Main()
{
Test Display = delegate()
{
Console.WriteLine("Anonymous Delegate method");
};
Display();
return 0;
}
}

Note: You can also handle event in anonymous method.

Events
Event and delegate are linked together.

Event is a reference of delegate i.e. when event will be raised delegate will be called.

In C# terms, events are a special form of delegate. Events are nothing but change of
state. Events play an important part in GUI programming. Events and delegates work
hand-in-hand to provide a program's functionality.

A C# event is a class member that is activated whenever the event it was designed for
occurs.

It starts with a class that declares an event. Any class, including the same class that the
event is declared in, may register one of its methods for the event. This occurs through a
delegate, which specifies the signature of the method that is registered for the event.
The event keyword is a delegate modifier. It must always be used in connection with a
delegate.

The delegate may be one of the pre-defined .NET delegates or one you declare yourself.
Whichever is appropriate, you assign the delegate to the event, which effectively
registers the method that will be called when the event fires.

How to use events?


Once an event is declared, it must be associated with one or more event handlers before
it can be raised. An event handler is nothing but a method that is called using a
delegate. Use the += operator to associate an event with an instance of a delegate that
already exists.

Example:
obj.MyEvent += new MyDelegate(obj.Display);

An event has the value null if it has no registered listeners.

Although events are mostly used in Windows controls programming, they can also be
implemented in console, web and other applications.

Program for creating custom Singlecast delegate and event


using System;
namespace delegate_custom
{
class Program
{
public delegate void MyDelegate(int a);

public class XX
{
public event MyDelegate MyEvent;

public void RaiseEvent()


{
MyEvent(20);
Console.WriteLine("Event Raised");
}

public void Display(int x)


{
Console.WriteLine("Display Method {0}", x);
}
}

static void Main(string[] args)


{
XX obj = new XX();
obj.MyEvent += new MyDelegate(obj.Display);

obj.RaiseEvent();
Console.ReadLine();
}
}
}

Program for creating custom Multiplecast delegate and event


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

namespace delegate_custom_multicast
{
class Program
{
public delegate void MyDelegate(int a, int b);

public class XX
{

public event MyDelegate MyEvent;

public void RaiseEvent(int a, int b)


{
MyEvent(a, b);
Console.WriteLine("Event Raised");
}
public void Add(int x, int y)
{
Console.WriteLine("Add Method {0}", x + y);
}

public void Subtract(int x, int y)


{
Console.WriteLine("Subtract Method {0}", x - y);
}
}

static void Main(string[] args)


{
XX obj = new XX();
obj.MyEvent += new MyDelegate(obj.Add);
obj.MyEvent += new MyDelegate(obj.Subtract);
obj.RaiseEvent(20, 10);
Console.ReadLine();
}
}
}

You might also like