views:

140

answers:

2

This is a terminology question. In C#, I can do this:

delegate Stream StreamOpenerDelegate(String name);

void WorkMethod(StreamOpenerDelegate d)
{
    // ...
}

void Exec1()
{
    WorkMethod((x) =>
        {
            return File.OpenRead(x);
        });
}

void Exec2()
{
    StreamOpenerDelegate opener = (x) =>
        {
            return File.OpenRead(x);
        };

    WorkMethod(opener);
}

Q1
The Exec1() method demonstrates the use of an anonymous delegate, correct?

Q2
Inside Exec2(), would opener be considered an anonymous delegate? It does have a name. If it's not an anonymous delegate, what should I call it? Is there a name for this syntax? "named anonymous delegate?" a local variable holding an anonymous delegate?

+9  A: 

No and no.

A1: This feature is new to C# 3.0 and is called a lambda expression. C# 2.0 has a similar feature called anonymous methods; for example:

button.Click += delegate {
    //code
};

A2: opener is a regular variable that happens to hold a lambda expression.

By the way, a lambda expression that takes exactly one parameter doesn't need parentheses. Also, a lambda expression that consists only of a return statement doesn't need braces.

For example:

StreamOpenerDelegate opener = x => File.OpenRead(x);
SLaks
Thank you, very helpful.
Cheeso
+14  A: 

Q1: There's no such term as "anonymous delegate" (in the C# language specification) - but this uses a lambda expression which is one kind of anonymous function. See section 7.14 of the C# language specification for details.

Q2: opener is a variable. The variable is assigned a value created using a lambda expression. After it's been created, the delegate is just an instance of StreamOpenerDelegate. In other words, the concepts of lambda expression, anonymous function and anonymous method are source code concepts rather than execution time concepts. The CLR doesn't care how you created the delegate.

By the way, both of your lambda expressions can be expressed more concisely - fewer parentheses etc:

void Exec1()
{
    WorkMethod(x => File.OpenRead(x));
}

void Exec2()
{
    StreamOpenerDelegate opener = x => File.OpenRead(x);
    WorkMethod(opener);
}

alternatively you could just use a method group conversion:

StreamOpenerDelegate opener = File.OpenRead;
Jon Skeet
Excellent, great to know, thank you.
Cheeso