The Way To Lambda

Florian Rappl, MVP Visual C#

The Way To Lambda

using lambda expressions to boost your efficiency

Lambda Talk Cover

About

  • MVP for Visual C# from Regensburg, Germany
  • Currently writing PhD thesis in theoretical particle physics
  • Three main areas of interest:

    App

    C#, WinForms, WPF

    Web

    C#, JS, ASP.NET MVC

    HPC

    C/C++, MIC, IB

  • Each area requires a unique way of thinking

Agenda

  1. General concept
  2. Properties
  3. JavaScript patterns
  4. Further usages
  5. Summary

The required syntax

  • The key ingredient is the fat arrow => operator
  • Arguments (given in round brackets) are mapped to a code block
  • Round brackets can be omitted if only one argument is given
  • Curly brackets can be omitted if we have only one statement
  • The return statement is only needed within curly brackets

Some basic examples

Func<double, double> squ = x => x * x;

Func<double, double, double> f = (x, y) => x * x + y;

Action dot = () => Console.Write(".");

Action<string> print = (str) => Console.WriteLine(str);

Action<string, params object[]> printf = (s, o) =gt; Console.WriteLine(s, o);

var mc = (Func<double>)(
	() => {
		var ran = new Random();
		var d = ran.NextDouble();
		return d > 0.5 ? d * d : 1.0 + 1.0 / d;
});

A closer look

  • We can explicitly specify argument types (optional)
  • Also async can be specified for using await
  • The delegate (function signature) has to be specified
  • Setting Expression<T> as target type generates a view of the related expression tree

Some advanced examples

public void GiveMeSomeLambda<T>(Func<T, T> theLambda) { /* ... */ }

//Here stating the argument type explicitly makes sense (one way)
GiveMeSomeLambda((double s) => s * s);

Func<double, Task<double>> f = async x =>
{
	var res = await Task.Run(/* Long running task with some result depending on x */);
	return res;
};

((string s, int no) => {
	// Do Something here!
})("Example", 8);

Generating expression trees

  • Performance: Terrible init time as a method
  • Can be very useful for reliability
  • Good example: ASP.NET MVC ext. methods
  • Useful: Require member information and a method to invoke

An anonymous method

  • Performance: Same as hand-written
  • Replacement for specifying anonymous functions with the delegate syntax
  • Compiler generates the method
  • Everything is done at compile time

Capture local variables

  • Performance: Slightly worse than hand-written
  • Compiler generates a class
  • All captured variables are global variables of the class
  • Overhead is created by instantiating the class
  • Method is also created in this generated class

Useful JavaScript patterns

  • Callback pattern
  • Returning functions
  • Self-defining functions
  • Immediately-invoked function expression
  • Immediate object initialization
  • Init-time branching

One example: Init-time branching

  • Construction determines how certain methods behave
  • Instead of actual methods use properties
  • The properties can be set by the class and read from outside
  • Advantage: Reliability (only one method visible)
  • Increased performance (due to no further checking required)

Some code: Init-time branching concept

class MyClass
{
	//Let's assume the class is dependent on some object
	public MyClass(Settings settings)
	{
		/* Read some settings of the user */

		//A property (or method) of the object is required to determine the status
		if(settings.EnableAutoSave)
			AutoSave = () => { /* Perform Auto Save */ };
		else
			AutoSave = () => { }; //Just do nothing!
	}

	public Action AutoSave { get; private set; }
}

Main usage: code reduction

  • Consider writing LINQ statements without lambda expressions
  • Possible, but highly uncomfortable
  • Another good example: use the power of closures
  • Closures result in compiler generated classes
  • Therefore we do not need to encapsulate objects by hand

A popular example: Asynchronous communication

  • We use the SynchronizationContext for invoking events
  • With lambda expressions we can use it like that:
    SynchronizationContext context = SynchronizationContext.Current ?? new SynchronizationContext();
    
    public event EventHandler<MyEventArgs> SomethingHappend;
    
    public void RaiseSomethingHappend()
    {
    	if(SomethingHappend != null)
    		context.Post(o => SomethingHappend(this, new MyEventArgs(field1, ..., fieldn)), null);
    }
    
  • This version (with closure) is a lot shorter to write

Improve code maintenance

  • Simple scenario: user input should be mapped to a function
  • The usual solution is to get everything done by using switch
  • Sometimes a Dictionary gives us more flexibility:
    Dictionary<string, Func<double, double>> functions = new Dictionary<string, Func<double>>();
    void Init() 
    {
    	functions.Add("sin", Math.Sin); functions.Add("cos", Math.Cos); functions.Add("exp", Math.Exp);
    }
    public double Evaluate(string f, double x) //Let's just assume that the specified function exists
    {	
    	return functions[f](x);
    }
    

Summary

  • Lambda expressions provide a wide range of possibilities
  • Using JavaScript patterns is an option
  • They help to reduce code
  • Improve code maintenance and reliability

Any questions?

MVP

Florian Rappl, MVP Visual C#