When Would You Use Delegates in C#

When & why to use delegates?

I agree with everything that is said already, just trying to put some other words on it.

A delegate can be seen as a placeholder for a/some method(s).

By defining a delegate, you are saying to the user of your class, "Please feel free to assign any method that matches this signature to the delegate and it will be called each time my delegate is called".

Typical use is of course events. All the OnEventX delegate to the methods the user defines.

Delegates are useful to offer to the user of your objects some ability to customize their behavior.
Most of the time, you can use other ways to achieve the same purpose and I do not believe you can ever be forced to create delegates. It is just the easiest way in some situations to get the thing done.

When would you use delegates in C#?

Now that we have lambda expressions and anonymous methods in C#, I use delegates much more. In C# 1, where you always had to have a separate method to implement the logic, using a delegate often didn't make sense. These days I use delegates for:

  • Event handlers (for GUI and more)
  • Starting threads
  • Callbacks (e.g. for async APIs)
  • LINQ and similar (List.Find etc)
  • Anywhere else where I want to effectively apply "template" code with some specialized logic inside (where the delegate provides the specialization)

Why do we need C# delegates

Of course you can call method directly on the object but consider following scenarios:

  1. You want to call series of method by using single delegate without writing lot of method calls.
  2. You want to implement event based system elegantly.
  3. You want to call two methods same in signature but reside in different classes.
  4. You want to pass method as a parameter.
  5. You don't want to write lot of polymorphic code like in LINQ , you can provide lot of implementation to the Select method.

How and why should I use Events and delegates

You don't have to use them..

..it's just that sometimes it's super handy to be able to pass methods around like they were data.

Quite often the utility in this is if you're providing a library for other people to use and you want to make it useful for them but you don't know a thing about their code or how they'll use it. An obvious one is List<T> in the framework; you might be writing something like it and want to provide a way for people to search if, but you don't know what kind of objects they will put in the list or how they want to search for them.

If, however you just provide them with a method like Find(delegate) then it's a "method that takes a method as a parameter" - you declare to the user "provide Find with a method that takes a T and returns a boolean of true if it should be included in the search results", then it means they can write a method like this:

bool IsSmith(Person p) {
return p.LastName == "Smith";
}

And they can pass it to your list Find method, your method runs their method, gives it the List object, gets a bool and decides what to do based on the result

var smiths = myListOfPeople.Find(IsSmith);

Nowadays we don't usually write the method out so long hand, we use the funky inline declaration where we just provide the parameter name and the logic, and the compiler inserts all the other stuff it can work out

var smiths = myListOfPeople.Find(p => p.LastName == "Smith");

In essence you can control every part of the process when you wrote your List class, you can implement the find, you can return the results - but in making your List truly flexible and letting people store what they want in it, you create a gap in the middle where you can't know how to search for a Whatever that the user put into it. Being able to let them pass a method in (of a known arguments type and return type) that you can call closes that gap


Another example; events this time but they're no different. An event is just a list of methods that the user of your class can fill with "bits of code that shall be run when something happens"

Take a button click: you want to download a file, your coworker wants to save an image, I want to calculate factors of a number entered in a text box.. We're all using that same Button class but we all want to do different things when we click our different buttons, so the easiest way for Microsoft to make the perfect button is to just leave that "do this when clicked" part for us to fill in, and that's done by having a way to associate a delegate (method passed round like a variable) with the button, and coding the button so that it runs the delegate when it's clicked, whatever the delegate may do


So all that is great for Microsoft, who create Buttons and Lists and other generic things for us to enjoy, but does it have a place for us in our own code? Sure, though more rare, I find it helpful to make some helper class for example- something that launches ffmpeg and reads from its output stream.. and mostly it's just nonsense but occasionally interesting messages are sent, so I might make an event that I raise when such a message is sent.. I use my helper in one project and I'm looking for dropped frames, in another I want to know if silence is detected.. In those cases I suppose the "person who provides the library to the person who consumes the library" was me at both ends. I have other projects where I want to perform similar tasks on different data, the writer routine is the same but the parsing is different; being able to pass a method to say how to pull a name out of this object but a number out of that one makes life a lot nicer than having some massive "if object is a person pull the name, else if object is a building pull the number and street" conditional block in a place it doesn't belong

How to use delegates in correct way / Understanding delegates

Ho-ho.. you've got something messed up. I didn't quite grasp what problem you are trying to state until I saw the screenshot from VS with red underline under "delegate" declaration.

First, forget about the public void delegate zczcxxzc line for a moment. It is somewhat special. First, let's see some standard kinds *) of delegates.

The two most basic ones are:

  • System.Action
  • System.Func

Both are generic and looking at their signature for the first time, they may seem overly complex. But, they are really very simple.

For starters, let's limit to bare, parameterless, System.Action.

private static void myFunction1() { Console.WriteLine("Hello!"); }
private static void myFunction2() { Console.WriteLine("Bye!"); }
private static void myFunction0() { return; }

... // in some function, i.e. Main()
Action myDelegate = null;

myDelegate = new Action( myFunction1 );
myDelegate(); // writes "Hello!"

myDelegate = new Action( myFunction2 );
myDelegate(); // writes "Bye!"

myDelegate = new Action( myFunction3 );
myDelegate(); // does "nothing"

Just like "int" holds a number, "string" - text, a "delegate" holds information about "something callable", or, to use some terminology, "something invokable".

First, I create a delegate of type "Action" that remembers "myFunction1". Then I invoke/call that delegate - it results in the remembered function being called.

Then, I create a delegate of type "Action" that remembers "myFunction2". Then I invoke/call that delegate - it results in the remembered function being called.

Finally, I create a delegate of type "Action" that remembers "myFunction3". Then I invoke/call that delegate - it results in the remembered function being called, and nothing happens - but only because the target function did nothing.

Please note that I deliberately say "created a delegate". Each time a new Action is executed, a new delegate is created. A "delegate" is just an object, like String "foo" or float[] {1.2, 4.5}.

Also, note that the full syntax for creating delegates used here is new Action(...). Just like creating any object - new + typename + construction parameters. Yet another sign that a "delegate" is just an object.

Another thing to note is that I did not write new Action( myFunction1() ). I did not want to CALL the method and get its result and give that result to the constructor of Action. I wrote new Action( myFunction1 ). I gave the function itself to the constructor.

But, then, what is an "Action"? System.Action is a class. Like String, or Socket or WebClient. Nothing special here. So, we have a "class" whose objects can remember what-function-should-be-called. Cool.

Therefore some compare delegates to "function pointers". But that's not fully right. Function pointers can remember what function to call. Delegates can remember what method to call. Remember the difference? In my example above, I deliberately wrote static at each myFunction. Those can be called object-less/target-less. You just need their name and you can call them from anywhere. To call them, a simple dumb pointer would be enough.

Now, delegates can do more. They can work on methods. But methods need to be invoked against an object..

class GuineaPig
{
public static void Squeak() { Console.WriteLine("Ieek!"); }

public void Well() { Console.WriteLine("actually"); }
public void IDontKnow() { Console.WriteLine("what they do"); }
}

GuineaPig.Squeak(); // says 'ieek'

Action myDelegate = null;
myDelegate = new Action( GuineaPig.Squeak );
myDelegate(); // writes "ieek"

// GuineaPig.Well(); // cannot do!
// myDelegate = new Action( GuineaPig.Well ); // cannot do!

Ok, making a delegate to a static function in other class was easy - just had to say exactly what-function-from-what-class. Again just like calling, but without parenthesis.

But, if you try uncommenting the references to non-static methods, it will not compile. Looking at the GuineaPig.Well - that's obvious. It's not static, it needs to be called against OBJECT, not CLASS. For that very same reason, the delegate could not be created. Let's fix that:

class GuineaPig
{
public void Well() { Console.WriteLine("actually"); }
public void IDontKnow() { Console.WriteLine("what they do"); }
}

GuineaPig myPiggie = new GuineaPig();

myPiggie.Well(); // ok! writes "actually"

Action myDelegate = null;
myDelegate = new Action( myPiggie.Well ); // ok!

myDelegate(); // ok! writes "actually".

Note how classname was replaced with objectvariable during the creation of the delegate. The syntax is preserved: just like calling, but without parens. But, what's all the fuss about "methods" vs "functions"..

Delegates can store not only 'what method' to be called, but also what object to call them upon.

class GuineaPig
{
public string Name;

public void Well() { Console.WriteLine("I'm " + Name); }
}

GuineaPig myPiggie1 = new GuineaPig { Name = "Bubba" };
GuineaPig myPiggie2 = new GuineaPig { Name = "Lassie" };

Action myDelegate = null;

myDelegate = new Action( myPiggie1.Well );
myDelegate(); // -> Bubba

myDelegate = new Action( myPiggie2.Well );
myDelegate(); // -> Lassie

myPiggie1 = myPiggie2 = null;

myDelegate(); // -> Lassie

Now that is something you cannot do with plain function pointers. (Although with very smart function pointers you could.. but, let's leave that).

Note how the fact that "Well" was to be called on "pig#2" was stored inside the delegate object. The "myPiggie2" variable was irrelevant. I could nullify it. The delegate remembered both target and method.

System.Action is just one of the family. It's the simpliest, no params, no returns.. But there are many of them, they can get parameters (Action<string, int>) they can return values (Func<int>) or both (Func<string,int>). Yet, constantly speaking in terms of Func<int,float,string,int,int,bool,decimal> is somewhat ... obscure.

Ok. Let's finally get to the point of all this babbling. Sorry if you knew all of that, but I wanted to be clear.

A "delegate" is all about remembering "target" and "method". In fact, if you ever inspect a delegate in the debugger (or check what Intellisense says after the "dot"), you will see two properties, Target and Method. They are just what their names stand for.

Let's imagine you want to create your own type of a delegate. A type that would not be called Func<int,int,int,bool,bool,Zonk,string>, but rather, "MyStudentFilteringDelegate".

Now, whole point is, that in C# you cannot take &(address) of a function easily, and also you cannot overload the operator(). This results in you being unable to write your own delegate-like classes.

You cannot just write:

class MyStudentFilteringDelegate
{
public object Target;
public somethingstrange* MethodPointer;

// other code
}

because, even if you actually managed to follow that idea, somewhere at the end you would find that:

MyDelegate dd = new MyDelegate ( ... );
dd(); // is just impossible!!!

At least, in current C# version 4.5 or 5.

You just cannot overload the "call"/"invoke" operator, hence you would not be able to fully implement your own, custom-named, delegate type. You'd be stuck at Actions and Funcs for ever.

Now recall that red underline under the public void delegate xxx I asked you to temporarily forget.

public bool delegate MyStudentFilteringDelegate( Student stud );

This line does not create any delegate. This line defines a type of a delegate. It is perfectly the same as Func<Student,bool>, with custom name. *)

In fact, the compiler converts the line to:

public class MyStudentFilteringDelegate : some_framework_Delegate_class
{
// object Target {get;} - inherited from base class
// MethodInfo Method {get;} - inherited from base class, too
}

so that it is a class, and so that you can now create a delegate object:

var dd = new MyStudentFilteringDelegate ( ... ); // like normal class!
dd(); // ok!;

As the class is special, compiler-generated, it can break rules. It's 'call'/'invoke' operator is overloaded, so you can "call" the delegate as it were a method.

Please note that despite the strange notation:

public bool delegate MyStudentFilteringDelegate( Student stud );

the MyStudentFilteringDelegate is a class, just like Action or Func or String or WebClient are. The delegate keyword is just a marker for the compiler to know what transformation it should apply to that line to generate a proper "delegate type" (class).

Now, to actually answer your other question:

It is really irrelevant where you put the delegate type declaration. You may write public void delegate XYZ(...) anywhere you like. Just as you may place a class declaration just about anywhere.

You may place class declarations at default(no-namespace) scope, at some namespace, or inside a class. So, as the delegate-type is just a class, you may also delcare new delegate types at default(no-namespace) scope, at some namespace, or inside a class:

public class Xc {}
public void delegate Xd();

namespace WTF {
public class Xc {}
public void delegate Xd();

class Whatever {
public class Xc {}
public void delegate Xd();
}
}

Note that I completely deliberately named them identically. That's no error. First are named ::global.Xc and ::global.Xd, the second pair is named WTF.Xc and WTF.Xd and the final pair is named WTF.Whatever.Xc and WTF.Whatever.Xd. Just like normal clases.

To decide where to place those declarations, use the same rules as you use for classes. Ie. if you place text-processing classes in namespace MyApp.Text.Parsing, then all the delegatetypes related to that text-processing should sit in that namespace too. But, even so, that's purely cosmetical and organizational. Place/define them at whatever scope it makes sense for you.

EDIT:
*) actually, historically, it was all other way around. The delegate keyword and compiler trick is older than the Action and Func classes. At .Net 2.0, the Action/Func did not exist. The only way to create/use a delegate was to define your own new delegate type (or find/guess some suitable one somewhere deep in the system's namespaces). Keep in mind that every new delegate-type is a new class. Not convertible to any other class, not even similarly-looking. It was so frustratingly tiresome and hard to mantain, that at .Net 3.5 they finally included "general purpose generic delegate types" in the framework. From that point of time, Action/Func are increasingly often used, because even if they are harder to read, they are .. universal. System.Func<Student,bool> can be passed "anywhere", and you don't have a problem that 'bool delegate StudentFilter()from one library does not matchbool delegate StudentSelector()` from anoother one.

Best practices: When should I use a delegate in .NET?

Delegates are useful when you need to tell another piece of code how to do something. Events are the simplest example - separating the event (something happened) from how to handle it. Other examples are some common iterative operations, such as a custom find:

List<Foo> foos = new List<Foo>();
foos.Find(delegate(Foo foo)
{
if(foo.CustomProperty.Contains("special value"))
{
return false;
}
return true;
});

The above is a totally arbitrary example but makes the point that you can separate the what (iterating and running a "find" criteria) from the how (how to determine whether something is found).

The purpose of delegates

Yeah,

You're almost there. A delegate refers to a method or function to be called. .NET uses the Events to say.. when someones presses this button, I want you to execute this piece of code.

For example, in the use of a GPS application:

public delegate void PositionReceivedEventHandler(double latitude, double longitude);

This says that the method must take two doubles as the inputs, and return void. When we come to defining an event:

public event PositionReceivedEventHandler PositionReceived;  

This means that the PositionRecieved event, calls a method with the same definition as the
PositionReceivedEventHandler delegate we defined. So when you do

PositionRecieved += new PositionReceivedEventHandler(method_Name);

The method_Name must match the delegate, so that we know how to execute the method, what parameters it's expecting. If you use a Visual Studio designer to add some events to a button for example, it will all work on a delegate expecting an object and an EventArgs parameter.

Hope that helps some...

When to Use Delegates Instead of Interfaces

A class may need more than one implementation of the method.

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

void SomeMethod()
{
PerformCalculation PerformCalculation_1 = myDelegateFun_1;
PerformCalculation PerformCalculation_2 = myDelegateFun_2;
PerformCalculation_1(5, 3);
PerformCalculation_2(5, 3);
}

private int myDelegateFun_1(int x, int y)
{
return x + y;
}
private int myDelegateFun_2(int x, int y)
{
return x + y;
}

In the above example PerformCalculation_1, PerformCalculation_2 are multiple implementation of PerformCalculation

A class only needs one implementation of the method

 

interface IDimensions 
{
float Length();
}

class Box : IDimensions
{
float Length()
{
return lengthInches;
}
}

In the above example only single implementation of method exposed by interface.



Related Topics



Leave a reply



Submit