Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling delegates individually?

Tags:

c#

delegates

if I have a delegate like so:

 Delegate void Render();
 Render ToRender;

And use it here:

 ToRender += FunctionRender;
 ToRender += SomeOtherRender;

How can I make it so I can invoke each function seperately? Something like this:

 foreach(Render render in ToRender)
 {
     BeginRender();


     render();


     EndRender();
 }
like image 460
meds Avatar asked Dec 15 '10 15:12

meds


People also ask

Why delegates why not call methods directly?

If you think of delegates as being similar to interface definitions for a specific type of method, you can start to see why delegates exist. They allow clients of our delegates to ignore all the details of their implementations - even their names!

Can delegates be private?

Just like classes and interfaces, we can declare delegates outside of classes or nested within classes. We can mark them private , public , or internal .

What's the purpose of delegates?

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. Methods don't have to match the delegate type exactly.

Can delegates be shared?

Delegates can be shared.


2 Answers

You can fetch each one separately using Delegate.GetInvocationList().

foreach (Render render in ToRender.GetInvocationList())
{
    ...
}

Note that GetInvocationList() just returns a Delegate[], but foreach has an implicit cast on each item, which is what makes the above loop work.

Oh, and you should check whether ToRender is null or not first, of course - otherwise you'll get a NullReferenceException. You could actually write a generic extension method to make this nicer, but you'd need a constraint on the delegate type which isn't allowed in C# :(

If you don't care about the lack of constraints, you could fake it:

public static IEnumerable<T> GetIndividualDelegates<T>(this T multiDelegate)
    where T : class
{
    if (multiDelegate == null)
    {
        yield break;
    }
    Delegate d = (Delegate)(object) multiDelegate;
    foreach (Delegate item in d.GetInvocationList())
    {
         yield return (T)(object) item;
    }    
}

(It's awkward because of the restrictions on generic conversions.)

That way you could write:

foreach (Render render in ToRender.GetIndividualDelegates())
{
    ...
}

without worrying about whether ToRender was null or not.

like image 179
Jon Skeet Avatar answered Oct 13 '22 23:10

Jon Skeet


foreach (Render render in ToRender.GetInvocationList())

Ideal Way:

Render temp = ToRender;

if (temp != null)
{
    foreach (Render render in temp.GetInvocationList())
    {
        BeginRender();

        render();

        EndRender();
    }
}
like image 31
decyclone Avatar answered Oct 13 '22 22:10

decyclone