What is the "correct" way to initialize a C# delegate?
Asked Answered
D

6

10

C# delegates have always been difficult for me to grasp and so I was very happy to stumble across logicchild's article on The Code Project web site titled "C# Delegates: Step by Step". He has a very succinct way of explaining C# delegates and I can recommend it to you. However, in trying out the examples, I see that are two ways to initialize a delegate, mainly:

    //create a new instance of the delegate class
    CalculationHandler sumHandler1 = new CalculationHandler(math.Sum);
    //invoke the delegate
    int result = sumHandler1(8, 9);
    Console.WriteLine("Result 1 is: " + result);

and

    CalculationHandler sumHandler2 = math.Sum;
    //invoke the delegate
    int result = sumHandler2(8, 9);
    Console.WriteLine("Result 2 is: " + result);

where the math class is defined as

public class math
{
    public int Sum(int x, int y)
    {
        return x + y;
    }
}

So which is the "correct" way and why?

Denysedenzil answered 20/9, 2010 at 11:9 Comment(0)
K
10

They are both correct, but method group conversion, which is the second option was added in 2.0 (IIRC). I.e. if you're using an old version of the compiler you need to use the first option. Otherwise the extra typing is really redundant.

Kloman answered 20/9, 2010 at 11:13 Comment(0)
M
3

I always use the first method for the sake of readability. The second option makes it appear that math.Sum is a property and is returning a result that is a CalculationHandler. Personally, I think that's confusing.

Mycology answered 20/9, 2010 at 11:14 Comment(5)
Whoa. Lots of crimes are committed “For the sake of readability,” and prominent among them is writing long, convoluted code instead of clear, concise code. That’s the opposite of readability.Rein
fun I use the second for readability. Just goes to show that readability is subjectiveUlysses
@Konrad, long doesn't automatically equal convoluted. And short doesn't automatically equal readable. RegEx comes to mind... The fact is that the "longer" way more closely follows the way everything else works in C#. The shorter way is potentially confusing. I'd hardly call CalculationHandler sumHandler1 = new CalculationHandler(math.Sum); a crime.Mycology
Not automatically, true. But your code adds an unnecessary redundancy and I find that hard to justify. “for the sake of readability” is not a justification, it’s an unjustified claim.Rein
@Konrad I'm justify why I think it makes it more readable (following existing patterns). Personal preference I suppose. [Respectfully backs away from comment thread for fear of starting flame war]Mycology
S
2

Both are correct.

The second one is a shortcut provided by the compiler, both does actually create the code of the first one.

The first one shows more clearly what's actually happening, while the second one is less code so it's easier to read (once you understand what's really happening).

Standby answered 20/9, 2010 at 11:16 Comment(0)
U
1

Personnaly I preferre the second option (method group conversion). From a functional point of view I don't care about the type of delegate, since that will not give me any hints to what the method assigned to the delegate is doing when invoked. The method name will (at least should) however give me a good idea of what's going to happen when the delegate is invoked and in the second option I don't have to search for the method name.

As a side note VS will give you the first version if you use autocomplete with event handler registration. Resharper will use the second and mark part of the code in the first version as redundant.

Ulysses answered 20/9, 2010 at 11:18 Comment(0)
S
0

Both ways are OK, short version is just C# compiler service. The first way is more verbose and shows exactly what happens. Both versions produce the same IL code, which is actually close to the first version.

Sizeable answered 20/9, 2010 at 11:14 Comment(0)
F
0

I will be add also additional variants of the initialization by lambda expression, which can be useful in some cases:

    Func<int, int, int> func = Sum;
    func = new Func<int, int, int>(Sum);
    func = (x, y) => Sum(x, y);

I don't fully believe that the IL code in all cases will be the same (i didn't check it, with lambda expression can exist the "intermediate call"/"variable"), but the last can give additional variants to call the method

func = (int _, int y) => Sum(5, y);
func = (_, y) => Sum(5, y);
     
Fortin answered 21/11, 2021 at 22:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.