Passing JavaScript functions as parameters — and the C# equivalent
Published 2019-10-26
Recently, I was helping a collegue with some JavaScript frontend code. He had a method that accepted a callback, which was defined inline, something like:
document.querySelector("#someSelector").addEventListener("mousedown", function(event){
// process event
});
The callback wasn't particularly long, but it was still a few dozen lines, so I suggested extracting it into its own function and passing that function as the parameter:
function mouseDownHandler(event){
// process event
}
document.querySelector(".mouseEventsSurface").addEventListener("mousedown", mouseDownHandler);
My collegue didn't know about this. I made a comment about how it's very similar to what you can do in C#, and how it comes into use in particular with LINQ, but he wasn't familiar with that either.
Think of a simple method:
public bool IsEvenNumber(int value)
{
return value % 2 == 0;
}
When using LINQ, I can use this method the following way:
Enumerable.Range(1, 10).Where(x => IsEvenNumber(x));
But I can also use it like this:
Enumerable.Range(1, 10).Where(IsEvenNumber);
How does this work? This is the signature of Where
:
public static IEnumerable<TSource> Where<TSource> (this IEnumerable<TSource> source, Func<TSource,bool> predicate);
As an extension method, it takes one parameter, Func<TSource,bool>
. What is Func<TSource,bool>
? It's a delegate:
public delegate TResult Func<in T,out TResult>(T arg);
This means that it's possible to utilise method group conversions by passing a method with a matching signature as the delegate and use it as the predicate. The compiler will take care of overload resolution to pick the appropriate method if the method has overloads.