Delegates

H

heddy

Using Jesse Liberty's excellent book on C#, I am looking at chapter 12
- Delegates. Now, I was under the impression that a delegate is
essentially a pointer to a member function. However, when I look at
Jesse's code and explanation of it, I just don't get it.

His code looks like this:

#region Using directives

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

#endregion

namespace Delegates
{
public enum Comparison
{
theFirstComesFirst = 1,
theSecondComesFirst = 2
}

// a simple collection to hold 2 items
public class Pair<T>
{

// private array to hold the two objects
private T[] thePair = new T[2];

// the delegate declaration
public delegate Comparison
WhichIsFirst( T obj1, T obj2 );

// passed in constructor take two objects,
// added in order received
public Pair(
T firstObject,
T secondObject )
{
thePair[0] = firstObject;
thePair[1] = secondObject;
}

// public method which orders the two objects
// by whatever criteria the object likes!
public void Sort(
WhichIsFirst theDelegatedFunc )
{
if ( theDelegatedFunc( thePair[0], thePair[1] )
== Comparison.theSecondComesFirst )
{
T temp = thePair[0];
thePair[0] = thePair[1];
thePair[1] = temp;
}
}

// public method which orders the two objects
// by the reverse of whatever criteria the object likes!
public void ReverseSort(
WhichIsFirst theDelegatedFunc )
{
if ( theDelegatedFunc( thePair[0], thePair[1] ) ==
Comparison.theFirstComesFirst )
{
T temp = thePair[0];
thePair[0] = thePair[1];
thePair[1] = temp;
}
}

// ask the two objects to give their string value
public override string ToString()
{
return thePair[0].ToString() + ", "
+ thePair[1].ToString();
}
} // end class Pair

public class Dog
{
private int weight;

public Dog( int weight )
{
this.weight = weight;
}

// dogs are ordered by weight
public static Comparison WhichDogComesFirst(
Dog d1, Dog d2 )
{
return d1.weight > d2.weight ?
Comparison.theSecondComesFirst :
Comparison.theFirstComesFirst;
}
public override string ToString()
{
return weight.ToString();
}
} // end class Dog

public class Student
{
private string name;

public Student( string name )
{
this.name = name;
}

// students are ordered alphabetically
public static Comparison
WhichStudentComesFirst( Student s1, Student s2 )
{
return ( String.Compare( s1.name, s2.name ) < 0 ?
Comparison.theFirstComesFirst :
Comparison.theSecondComesFirst );
}

public override string ToString()
{
return name;
}
} // end class Student

public class Test
{
public static void Main()
{
// create two students and two dogs
// and add them to Pair objects
Student Jesse = new Student( "Jesse" );
Student Stacey = new Student( "Stacey" );
Dog Milo = new Dog( 65 );
Dog Fred = new Dog( 12 );

Pair<Student> studentPair = new Pair<Student>( Jesse, Stacey
);
Pair<Dog> dogPair = new Pair<Dog>( Milo, Fred );
Console.WriteLine( "studentPair\t\t\t: {0}",
studentPair.ToString() );
Console.WriteLine( "dogPair\t\t\t\t: {0}",
dogPair.ToString() );

// Instantiate the delegates
Pair<Student>.WhichIsFirst theStudentDelegate =
new Pair<Student>.WhichIsFirst(
Student.WhichStudentComesFirst );

Pair<Dog>.WhichIsFirst theDogDelegate =
new Pair<Dog>.WhichIsFirst(
Dog.WhichDogComesFirst );

// sort using the delegates
studentPair.Sort( theStudentDelegate );
Console.WriteLine( "After Sort studentPair\t\t: {0}",
studentPair.ToString() );
studentPair.ReverseSort( theStudentDelegate );
Console.WriteLine( "After ReverseSort studentPair\t: {0}",
studentPair.ToString() );

dogPair.Sort( theDogDelegate );
Console.WriteLine( "After Sort dogPair\t\t: {0}",
dogPair.ToString() );
dogPair.ReverseSort( theDogDelegate );
Console.WriteLine( "After ReverseSort dogPair\t: {0}",
dogPair.ToString() );
}
}
}

Can someone give me a simpler explanation of how delegates work? This
example is just confusing to me.

Thanks :)
 
N

Nicholas Paldino [.NET/C# MVP]

heddy,

That's a lot of code for something so simple.

Delegates are basically a type-safe way of accessing a method with the
signature that matches a delegate. So basically, if you have a delegate
that looks like this:

public delegate void DoSomething(int i);

Then you can assign any method with a void return type and one parameter
of type int to that delegate. You can then call that delegate and it will
call the method assigned to it.

You can also chain delegates together, so that one delegate represents a
list of methods to call.

There isn't a limitation on what methods you can assign to a delegate.
They can be static or instance, public, protected, private, or internal. As
long as you have access to the method, you can assign it to a delegate with
the proper signature.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

heddy said:
Using Jesse Liberty's excellent book on C#, I am looking at chapter 12
- Delegates. Now, I was under the impression that a delegate is
essentially a pointer to a member function. However, when I look at
Jesse's code and explanation of it, I just don't get it.

His code looks like this:

#region Using directives

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

#endregion

namespace Delegates
{
public enum Comparison
{
theFirstComesFirst = 1,
theSecondComesFirst = 2
}

// a simple collection to hold 2 items
public class Pair<T>
{

// private array to hold the two objects
private T[] thePair = new T[2];

// the delegate declaration
public delegate Comparison
WhichIsFirst( T obj1, T obj2 );

// passed in constructor take two objects,
// added in order received
public Pair(
T firstObject,
T secondObject )
{
thePair[0] = firstObject;
thePair[1] = secondObject;
}

// public method which orders the two objects
// by whatever criteria the object likes!
public void Sort(
WhichIsFirst theDelegatedFunc )
{
if ( theDelegatedFunc( thePair[0], thePair[1] )
== Comparison.theSecondComesFirst )
{
T temp = thePair[0];
thePair[0] = thePair[1];
thePair[1] = temp;
}
}

// public method which orders the two objects
// by the reverse of whatever criteria the object likes!
public void ReverseSort(
WhichIsFirst theDelegatedFunc )
{
if ( theDelegatedFunc( thePair[0], thePair[1] ) ==
Comparison.theFirstComesFirst )
{
T temp = thePair[0];
thePair[0] = thePair[1];
thePair[1] = temp;
}
}

// ask the two objects to give their string value
public override string ToString()
{
return thePair[0].ToString() + ", "
+ thePair[1].ToString();
}
} // end class Pair

public class Dog
{
private int weight;

public Dog( int weight )
{
this.weight = weight;
}

// dogs are ordered by weight
public static Comparison WhichDogComesFirst(
Dog d1, Dog d2 )
{
return d1.weight > d2.weight ?
Comparison.theSecondComesFirst :
Comparison.theFirstComesFirst;
}
public override string ToString()
{
return weight.ToString();
}
} // end class Dog

public class Student
{
private string name;

public Student( string name )
{
this.name = name;
}

// students are ordered alphabetically
public static Comparison
WhichStudentComesFirst( Student s1, Student s2 )
{
return ( String.Compare( s1.name, s2.name ) < 0 ?
Comparison.theFirstComesFirst :
Comparison.theSecondComesFirst );
}

public override string ToString()
{
return name;
}
} // end class Student

public class Test
{
public static void Main()
{
// create two students and two dogs
// and add them to Pair objects
Student Jesse = new Student( "Jesse" );
Student Stacey = new Student( "Stacey" );
Dog Milo = new Dog( 65 );
Dog Fred = new Dog( 12 );

Pair<Student> studentPair = new Pair<Student>( Jesse, Stacey
);
Pair<Dog> dogPair = new Pair<Dog>( Milo, Fred );
Console.WriteLine( "studentPair\t\t\t: {0}",
studentPair.ToString() );
Console.WriteLine( "dogPair\t\t\t\t: {0}",
dogPair.ToString() );

// Instantiate the delegates
Pair<Student>.WhichIsFirst theStudentDelegate =
new Pair<Student>.WhichIsFirst(
Student.WhichStudentComesFirst );

Pair<Dog>.WhichIsFirst theDogDelegate =
new Pair<Dog>.WhichIsFirst(
Dog.WhichDogComesFirst );

// sort using the delegates
studentPair.Sort( theStudentDelegate );
Console.WriteLine( "After Sort studentPair\t\t: {0}",
studentPair.ToString() );
studentPair.ReverseSort( theStudentDelegate );
Console.WriteLine( "After ReverseSort studentPair\t: {0}",
studentPair.ToString() );

dogPair.Sort( theDogDelegate );
Console.WriteLine( "After Sort dogPair\t\t: {0}",
dogPair.ToString() );
dogPair.ReverseSort( theDogDelegate );
Console.WriteLine( "After ReverseSort dogPair\t: {0}",
dogPair.ToString() );
}
}
}

Can someone give me a simpler explanation of how delegates work? This
example is just confusing to me.

Thanks :)
 
H

heddy

Thanks Nicholas. By signature I presume you mean return type and
paramaters passed?

How do you assign a function to a delegate? I am guessing the most
common use for this is for some kind of function dispatcher?
 
N

Nicholas Paldino [.NET/C# MVP]

heddy,

Yes, by signature, I mean return type and parameters passed.

As for assigning a function to a delegate, using the original example:

public delegate void DoSomething(int i);

And if you have a method like this:

public void MyMethod(int k)
{
Console.WriteLine(k);
}

You can do this:

DoSomething d = MyMethod;

This assumes .NET 2.0. In 1.1 and before, you had to do this:

DoSomething d = new DoSomething(MyMethod);

But they are the same, the compiler just does the work for you now.

You can then call the method(s) like this:

d(10);
 
H

heddy

Thank you again, Nicholas. This makes it much clearer for me. Can you
give an example of where this becomes useful?
 
P

Peter Morris [Droopy eyes software]

Thank you again, Nicholas. This makes it much clearer for me. Can you
give an example of where this becomes useful?

public delegate void ProgressDelegate(byte percentComplete);


public class Worker
{
public void DoSomethingVeryIntensive(ProgressDelegate progressDelegate)
{
while (!finished)
{
//Intensive code here
int percentComplete = current * 100 / total;
progressDelegate(percentComplete);
}//while not finished
}
}


You could now have a method in your form like so

private void UpdateProgressBar(int percentComplete)
{
progressBar1.Value = percentComplete;
}

and then call the worker like so

worker.DoSomethingVeryIntensive(UpdateProgressBar);



Delegates are also used a lot in events on components.


Pete
 
K

Kevin Spencer

In addition, delegates are often used for functions that are not
specifically-defined, or implementation-specific. Since a delegate is
essentially a function pointer, you can define a function as a delegate, and
assign it dynamically by assigning a function to the delegate. Then, when
the delegate is called, the function assigned to it is called. This is used
a lot in Generic classes and methods, such as the Array.FindLast method:

public static T FindLast<T> (
T[] array,
Predicate<T> match
)

The Predicate parameter is a delegate called a Predicate, which is a generic
function. It is defined as

public delegate bool Predicate<T> (
T obj
)

As you can see, the implementation is not defined (as with all delegates).
It takes a parameter of the type 'T' and returns a boolean value indicating
whether the passed value does or does not satisfy a condition defined by the
implementation. This way, the FindLast method can define any condition for
which an array element may be true or false.

Another example of the use of delegates as function pointers can be found in
the System.Text.RegularExpressions.Regex.Replace method:


public string Replace (
string input,
MatchEvaluator evaluator
)

The MatchEvaluator parameter is a delegate called a MatchEvaluator, which is
a function that takes a System.Text.RegularExpressions.Match instance, and
returns a string:

public delegate string MatchEvaluator (
Match match
)

The Regex.Replace Method passes each Match in the Matches collection of the
Regex instance to the MatchEvaluator implementation passed, and replaces it
with the result returned by the MatchEvaluator Method used. This way, you
can define any rule you want for replacing Matches returned by a Regular
Expression.

--
HTH,

Kevin Spencer
Microsoft MVP
Chicken Salad Surgery

What You Seek Is What You Get.

Nicholas Paldino said:
Events is the classic example.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

heddy said:
Thank you again, Nicholas. This makes it much clearer for me. Can you
give an example of where this becomes useful?
 
C

Cor Ligthert [MVP]

And than to place as well an addition.

A delegate is not a need. You can do a lot without those.
(Sometimes I have the idea that people are thinking the opposite)

Just as addition,

Cor

Kevin Spencer said:
In addition, delegates are often used for functions that are not
specifically-defined, or implementation-specific. Since a delegate is
essentially a function pointer, you can define a function as a delegate,
and assign it dynamically by assigning a function to the delegate. Then,
when the delegate is called, the function assigned to it is called. This
is used a lot in Generic classes and methods, such as the Array.FindLast
method:

public static T FindLast<T> (
T[] array,
Predicate<T> match
)

The Predicate parameter is a delegate called a Predicate, which is a
generic function. It is defined as

public delegate bool Predicate<T> (
T obj
)

As you can see, the implementation is not defined (as with all delegates).
It takes a parameter of the type 'T' and returns a boolean value
indicating whether the passed value does or does not satisfy a condition
defined by the implementation. This way, the FindLast method can define
any condition for which an array element may be true or false.

Another example of the use of delegates as function pointers can be found
in the System.Text.RegularExpressions.Regex.Replace method:


public string Replace (
string input,
MatchEvaluator evaluator
)

The MatchEvaluator parameter is a delegate called a MatchEvaluator, which
is a function that takes a System.Text.RegularExpressions.Match instance,
and returns a string:

public delegate string MatchEvaluator (
Match match
)

The Regex.Replace Method passes each Match in the Matches collection of
the Regex instance to the MatchEvaluator implementation passed, and
replaces it with the result returned by the MatchEvaluator Method used.
This way, you can define any rule you want for replacing Matches returned
by a Regular Expression.

--
HTH,

Kevin Spencer
Microsoft MVP
Chicken Salad Surgery

What You Seek Is What You Get.

Nicholas Paldino said:
Events is the classic example.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

heddy said:
Thank you again, Nicholas. This makes it much clearer for me. Can you
give an example of where this becomes useful?
 
K

Kevin Spencer

A delegate is not a need. You can do a lot without those.
(Sometimes I have the idea that people are thinking the opposite)

While it is possible to perform the types of operations such as performed by
the Regex.Replace method, using a MatchEvaluator Delegate, you're talking
about a complex and kludgy work-around. And Delegates are particularly
useful when working with multiple threads in Windows Forms. Event-handling
would be a nightmare without them.

Yes, in fact, delegates are not needed. But neither is OOP, or Managed code,
or even high-level programming languages. But they are certainly useful and
efficient.

--
HTH,

Kevin Spencer
Microsoft MVP
Chicken Salad Surgery

What You Seek Is What You Get.

Cor Ligthert said:
And than to place as well an addition.

A delegate is not a need. You can do a lot without those.
(Sometimes I have the idea that people are thinking the opposite)

Just as addition,

Cor

Kevin Spencer said:
In addition, delegates are often used for functions that are not
specifically-defined, or implementation-specific. Since a delegate is
essentially a function pointer, you can define a function as a delegate,
and assign it dynamically by assigning a function to the delegate. Then,
when the delegate is called, the function assigned to it is called. This
is used a lot in Generic classes and methods, such as the Array.FindLast
method:

public static T FindLast<T> (
T[] array,
Predicate<T> match
)

The Predicate parameter is a delegate called a Predicate, which is a
generic function. It is defined as

public delegate bool Predicate<T> (
T obj
)

As you can see, the implementation is not defined (as with all
delegates). It takes a parameter of the type 'T' and returns a boolean
value indicating whether the passed value does or does not satisfy a
condition defined by the implementation. This way, the FindLast method
can define any condition for which an array element may be true or false.

Another example of the use of delegates as function pointers can be found
in the System.Text.RegularExpressions.Regex.Replace method:


public string Replace (
string input,
MatchEvaluator evaluator
)

The MatchEvaluator parameter is a delegate called a MatchEvaluator, which
is a function that takes a System.Text.RegularExpressions.Match instance,
and returns a string:

public delegate string MatchEvaluator (
Match match
)

The Regex.Replace Method passes each Match in the Matches collection of
the Regex instance to the MatchEvaluator implementation passed, and
replaces it with the result returned by the MatchEvaluator Method used.
This way, you can define any rule you want for replacing Matches returned
by a Regular Expression.

--
HTH,

Kevin Spencer
Microsoft MVP
Chicken Salad Surgery

What You Seek Is What You Get.

Nicholas Paldino said:
Events is the classic example.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Thank you again, Nicholas. This makes it much clearer for me. Can you
give an example of where this becomes useful?
 
C

Cor Ligthert [MVP]

Kevin,

As I agree completely with you, however sometimes I have the idea that there
is first searched how to do a solution doing a delegate, that has to be in
my opinion opposite.

That is all.

Cor

Kevin Spencer said:
A delegate is not a need. You can do a lot without those.
(Sometimes I have the idea that people are thinking the opposite)

While it is possible to perform the types of operations such as performed
by the Regex.Replace method, using a MatchEvaluator Delegate, you're
talking about a complex and kludgy work-around. And Delegates are
particularly useful when working with multiple threads in Windows Forms.
Event-handling would be a nightmare without them.

Yes, in fact, delegates are not needed. But neither is OOP, or Managed
code, or even high-level programming languages. But they are certainly
useful and efficient.

--
HTH,

Kevin Spencer
Microsoft MVP
Chicken Salad Surgery

What You Seek Is What You Get.

Cor Ligthert said:
And than to place as well an addition.

A delegate is not a need. You can do a lot without those.
(Sometimes I have the idea that people are thinking the opposite)

Just as addition,

Cor

Kevin Spencer said:
In addition, delegates are often used for functions that are not
specifically-defined, or implementation-specific. Since a delegate is
essentially a function pointer, you can define a function as a delegate,
and assign it dynamically by assigning a function to the delegate. Then,
when the delegate is called, the function assigned to it is called. This
is used a lot in Generic classes and methods, such as the Array.FindLast
method:

public static T FindLast<T> (
T[] array,
Predicate<T> match
)

The Predicate parameter is a delegate called a Predicate, which is a
generic function. It is defined as

public delegate bool Predicate<T> (
T obj
)

As you can see, the implementation is not defined (as with all
delegates). It takes a parameter of the type 'T' and returns a boolean
value indicating whether the passed value does or does not satisfy a
condition defined by the implementation. This way, the FindLast method
can define any condition for which an array element may be true or
false.

Another example of the use of delegates as function pointers can be
found in the System.Text.RegularExpressions.Regex.Replace method:


public string Replace (
string input,
MatchEvaluator evaluator
)

The MatchEvaluator parameter is a delegate called a MatchEvaluator,
which is a function that takes a System.Text.RegularExpressions.Match
instance, and returns a string:

public delegate string MatchEvaluator (
Match match
)

The Regex.Replace Method passes each Match in the Matches collection of
the Regex instance to the MatchEvaluator implementation passed, and
replaces it with the result returned by the MatchEvaluator Method used.
This way, you can define any rule you want for replacing Matches
returned by a Regular Expression.

--
HTH,

Kevin Spencer
Microsoft MVP
Chicken Salad Surgery

What You Seek Is What You Get.

in message Events is the classic example.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Thank you again, Nicholas. This makes it much clearer for me. Can
you
give an example of where this becomes useful?
 
K

Kevin Spencer

Well, of course, one should always use the right tool for the job.

--
:-D,

Kevin Spencer
Microsoft MVP
Chicken Salad Surgery

What You Seek Is What You Get.

Cor Ligthert said:
Kevin,

As I agree completely with you, however sometimes I have the idea that
there is first searched how to do a solution doing a delegate, that has to
be in my opinion opposite.

That is all.

Cor

Kevin Spencer said:
A delegate is not a need. You can do a lot without those.
(Sometimes I have the idea that people are thinking the opposite)

While it is possible to perform the types of operations such as performed
by the Regex.Replace method, using a MatchEvaluator Delegate, you're
talking about a complex and kludgy work-around. And Delegates are
particularly useful when working with multiple threads in Windows Forms.
Event-handling would be a nightmare without them.

Yes, in fact, delegates are not needed. But neither is OOP, or Managed
code, or even high-level programming languages. But they are certainly
useful and efficient.

--
HTH,

Kevin Spencer
Microsoft MVP
Chicken Salad Surgery

What You Seek Is What You Get.

Cor Ligthert said:
And than to place as well an addition.

A delegate is not a need. You can do a lot without those.
(Sometimes I have the idea that people are thinking the opposite)

Just as addition,

Cor

"Kevin Spencer" <[email protected]> schreef in bericht
In addition, delegates are often used for functions that are not
specifically-defined, or implementation-specific. Since a delegate is
essentially a function pointer, you can define a function as a
delegate, and assign it dynamically by assigning a function to the
delegate. Then, when the delegate is called, the function assigned to
it is called. This is used a lot in Generic classes and methods, such
as the Array.FindLast method:

public static T FindLast<T> (
T[] array,
Predicate<T> match
)

The Predicate parameter is a delegate called a Predicate, which is a
generic function. It is defined as

public delegate bool Predicate<T> (
T obj
)

As you can see, the implementation is not defined (as with all
delegates). It takes a parameter of the type 'T' and returns a boolean
value indicating whether the passed value does or does not satisfy a
condition defined by the implementation. This way, the FindLast method
can define any condition for which an array element may be true or
false.

Another example of the use of delegates as function pointers can be
found in the System.Text.RegularExpressions.Regex.Replace method:


public string Replace (
string input,
MatchEvaluator evaluator
)

The MatchEvaluator parameter is a delegate called a MatchEvaluator,
which is a function that takes a System.Text.RegularExpressions.Match
instance, and returns a string:

public delegate string MatchEvaluator (
Match match
)

The Regex.Replace Method passes each Match in the Matches collection of
the Regex instance to the MatchEvaluator implementation passed, and
replaces it with the result returned by the MatchEvaluator Method used.
This way, you can define any rule you want for replacing Matches
returned by a Regular Expression.

--
HTH,

Kevin Spencer
Microsoft MVP
Chicken Salad Surgery

What You Seek Is What You Get.

"Nicholas Paldino [.NET/C# MVP]" <[email protected]>
wrote in message Events is the classic example.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Thank you again, Nicholas. This makes it much clearer for me. Can
you
give an example of where this becomes useful?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top