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.