https://unsplash.com/@aznbokchoy

C# for the Java Developer: Lambdas

A lambda is an anonymous function that can be assigned to a variable, passed as an argument of a method and invoked at any time. We can find lambdas in Java and C# and the resulting code is very similar. A Java lambda can be viewed as the implementation of an interface with only one method (called a functional interface) whereas a C# lambda can be assigned to a delegate, which is a concept that does not exist in Java. This article aims to explain how lambdas work in Java and C# and highlight their differences and similarities.

Java Functional Interfaces

In Java, a lambda can simply be viewed as an anonymous function that implements an interface with only one method. This kind of interface is called a functional interface and can be annotated with the @FunctionalInterface annotation that tells the compiler to enforce the only-one-method rule:

@FunctionalInterface
interface Printer {
    void print(String message);
}
// The function interface is implemented with a lambda
Printer standardPrinter = message -> System.out.println(message);

// The print method of standardPrinter can be invoked
standardPrinter.print("Hello World!");

From the previous snippet, you should note that the way the interface is implemented makes absolutely no difference. It can be a lambda, a concrete or even an anonymous class. In any ways, you can simply invoke the print method of the interface.

There are some pre-defined generic functional interfaces in the JDK that can be used directly off the shelf. The main ones are described below:

NameMethodRole
Function<T,R>R apply(T t)Takes an argument of a given type T and returns an object of type R
Consumer<T>void accept(T)Takes an argument of a given type T and does something useful (typically with side effects)
Predicate<T>boolean test(T)Takes an argument of a given type T and returns a boolean (similar to Function<T, Boolean>)
Supplier<T>T get()Returns an object of type T

C# Delegates

In C#, a lambda can be assigned to a delegate which is a type that encapsulates a method:

delegate void Print(string message);
// A lambda is assigned to the delegate
Print print = message => System.Console.WriteLine(message);

// print can be directly invoked as a method
print("Hello World!");

Like in Java, some delegates are already defined in the .NET framework, the main ones are described below:

MethodRole
TResult Func<in T,out TResult>(T arg)Takes an argument of a given type T and returns an object of type TResult
void Action<in T>(T obj)Takes an argument of a given type T and does something useful (typically with side effects)
bool Predicate<in T>(T obj)Takes an argument of a given type T and returns a boolean (similar to Func<T, bool>)

Conclusion

From a Java perspective, using lambdas in APIs (like Linq for instance) is pretty straightforward. However, when digging a little bit deeper, there are some subtle differences to understand. I find the Java approach simpler as it does not introduce another concept but the C# approach is cleaner because the delegate can be invoked directly like a method.

Comments