tags:

views:

108

answers:

4

Hi

I just read the Microsoft Surface Tutorial. There is the following C# sample:

private void OnCenterItems(object sender, RoutedEventArgs e)
{
    var x = this.Photos.ActualWidth / 2;
    var y = this.Photos.ActualHeight / 2;
    FindChildren(this.Photos, d => d.GetType() == typeof(ScatterViewItem), 
                          d => ((ScatterViewItem)d).Center = new Point(x,y));
}

private void FindChildren(DependencyObject source, 
                          Predicate<DependencyObject> predicate, 
                          Action<DependencyObject> itemFoundCallback)
{
    int childCount = VisualTreeHelper.GetChildrenCount(source);
    for (int i = 0; i < childCount; i++)
    {
        DependencyObject child = VisualTreeHelper.GetChild(source, i);
        if (predicate(child))
        {
            itemFoundCallback(child);
        }
        FindChildren(child, predicate, itemFoundCallback);
    }
}

I think I understand more or less what this two methods are doing, but I never saw a method call like this:

 FindChildren(this.Photos, d => d.GetType() == typeof(ScatterViewItem), 
                           d => ((ScatterViewItem)d).Center = new Point(x,y));

This is maybe because I'm a Java programmer. So can anyone explain what this syntax is doing?

+5  A: 

What your seeing with the following is a C# lambda expression

d => d.GetType() == typeof(ScatterViewItem)

It's essentially an expression which produces a delegate. Some people like to think of them as inline functions.

Here are some references for reading

JaredPar
+2  A: 

d => d.GetType() == typeof(ScatterViewItem) is called a Lambda Expression. It says "For any DependencyObject, d, return (d.GetType() == typeof(ScatterViewItem))". It's a method without a name, an anonymous method.

Long-hand would be:

static bool myPredicate(DependencyObject d)
{
  return d.GetType() == typeof(ScatterViewItem);
}

called with:

FindChildren(this.Photos, myPredicate, [...] )

Predicate<DependencyObject> is a delegate-type, or "signature shape". It can hold a reference to any method which takes a DependencyObject and returns a bool.

FindChildren knows to use the provided predicate to evaluate whatever it's supposed to do. Because it takes certain kinds of data and returns certain kinds of data, FindChildren doesn't care how the operation happens, it can just call it and know it will get a useful answer.

uosɐſ
+5  A: 

These are lambda expressions, generating anonymous methods.

d => d.GetType() == typeof(ScatterViewItem)

this can be written as

(object d) => { return (d.GetType() == typeof(ScatterViewItem)); }

this call would represent this method, if written out:

public bool CheckObjecteEqualsScatterViewItemType (object d)
{
  return d.GetType() == typeof(ScatterViewItem);
}

The method FindChildren requires a generic delegate (compareable to a function pointer in C, but strongly typed) Func<object, bool> (ie. any method taking an object and returning a bool) to be given as parameter, the lambda expression generates this method on the fly. (This is done by the compiler, so this is not done at runtime and is fully type checked, and involves no loss of performance).

Femaref
It's actually called a lambda _expression_.
SLaks
right, I was thinking about the `=>` specifically, because this is the lambda operator ;)
Femaref
No, it's not an operator.
SLaks
Yes it is: "All lambda expressions use the lambda operator => [...]" (http://msdn.microsoft.com/en-us/library/bb397687.aspx)
Femaref
I take that back; I was wrong. Unlike a regular operator, the left side is not a real expression, which is why I thought that it wasn't an operator.
SLaks
I guess if you define "regular operator" as one that takes two expressions, then yeah. :-) Several other C# operators take non-expressions, like member access (`.`), casts (`()`), instantiation (`new`), the true/false operators (which don't seem to really look like anything at all).
Ken
Ok thanks for all the answers. So the benefit of this complicated lambda expressions is better performance?
Roflcoptr
No, not performance. It has the same performance as using delegates and seperate methods for each call. The purpose is to prevent cluttering up code with single line methods which are only used in one spot. Some call lambdas "inline methods" which they are in a sense. I had problems with lambdas as well in the beginning and I found them complicated as hell - but after some time, I learned to embrace them, and saw what is possible with them, now I can't imagine losing them again. You will get used to it after some time.
Femaref
+1  A: 

The => is the new "lambda" operator, for defining functions on the fly.

See: www.switchonthecode.com/tutorials/csharp-tutorial-the-lambda-operator

Loadmaster