Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does the keyword delegate work compared to creating a delegate

Tags:

c#

delegates

I'm slowly getting my head around delegates, in that the signature of the delegate must match that of the method it is delegating too.

However, please review the following code.

public static void Save()
{
    ThreadStart threadStart = delegate
    {
        SaveToDatabase();
    };
    new Thread(threadStart).Start();
}

private static void SaveToDatabase() { }

I am now stumped at this point, because the delegate returns void (as that is what SaveToDatabase() is) but, it's clearly returning a ThreadStart... Or is it?

If I were to write my own delegate, I would have no idea how to achieve this because the delegate would have to be void to match the return type of SaveToDatabase(). But it can't be; it would be of type ThreadStart!

My question is, have I totally mis-understood or is this made possible by some .NET trickery? If I wanted to write this method but create my own delegate, how would I ?

like image 755
Dave Avatar asked Dec 10 '12 14:12

Dave


1 Answers

The word "delegate" is a bit abused. It's easier with classes and objects. A "class" is like a blueprint for an object. An "object" is an actual instance in memory, which follows the blueprint of the class.

For delegates we use the same word, hence I suspect your confusion. Consider the following code:

class Main
{
    public delegate int DelegateType(string x);
    public int SomeFunction(string y) { return int.Parse(y)*2; }
    public void Main()
    {
        DelegateType delegateInstance = null;
        delegateInstance = SomeFunction;
        int z = delegateInstance("21");
        Console.WriteLine(z);
    }
}

This code outputs "42".

The DelegateType is the type of the delegate. Like a class is a blueprint for an object, the delegate is a blueprint for a function.

So later we create a variable named delegateInstance which is of the type DelegateType. To that variable, we can assign ANY function that takes a single string parameter and returns an integer. Note, that we assigned the function itself, not the results of that function. It's like the delegateInstance variable is now a synonym of that function. Indeed, as demonstrated a line later, we can now use delegateInstance to call that funcion! Just as if delegateInstance was a function itself. But, since it is variable, we can also do all the same things that we usually do with variables - like pass them as parameters to other functions, or even return from other functions (A function that returns a function! Wrap your head around that!)

OK, let's see the code that baffled you.

public static void Save()
{
    ThreadStart threadStart = delegate
    {
        SaveToDatabase();
    };
    new Thread(threadStart).Start();
}

private static void SaveToDatabase() { }

First thing to notice is that you used an anonymous delegate. Another misuse of the term. When compiled, it results in something like this:

public static void Save()
{
    ThreadStart threadStart;
    threadStart = __ASDASDASD6546549871;
    var tmp = new Thread(threadStart);
    tmp.Start();
}

private static void SaveToDatabase() { }

private void __ASDASDASD6546549871()
{
    SaveToDatabase();
}

Note that your anonymous function was actually transformed to a completely regular function with a random name, and then that function was assigned to the threadStart variable.

So now this is just like the example above. Just replace DelegateType with ThreadStart, delegateInstance with threadStart and SomeFunction with __ASDASDASD6546549871.

Does it make sense now?

like image 193
Vilx- Avatar answered Sep 20 '22 00:09

Vilx-