2010-10-20 5 views
4

Je viens de lire le Microsoft Surface Tutorial. Il y a l'exemple suivant C#:Quelle méthode bizarre appelez-vous?

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); 
    } 
} 

Je pense que je comprends plus ou moins ce que ces deux méthodes font, mais je n'a jamais vu un appel de méthode comme ceci:

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

Ceci est peut-être parce que je suis un programmeur Java. Donc, quelqu'un peut-il expliquer ce que fait cette syntaxe?

Répondre

5

Il s'agit d'expressions lambda générant des méthodes anonymes.

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

cela peut être écrit comme

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

cet appel représenterait cette méthode, si elle était écrite sur:

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

La méthode FindChildren nécessite un délégué générique (compareable à un pointeur de fonction en C, mais fortement typé) Func<object, bool> (c'est-à-dire que toute méthode prenant un objet et retournant un bool) doit être donnée en paramètre, l'expression lambda génère cette m ethod à la volée. (Ceci est fait par le compilateur, donc c'est pas fait à l'exécution et est entièrement vérifié par type, et n'implique aucune perte de performance).

+0

Il est en fait appelée lambda _expression_. – SLaks

+0

à droite, je pensais à '' => 'spécifiquement, parce que c'est l'opérateur lambda;) – Femaref

+0

Non, ce n'est pas un opérateur. – SLaks

2

d => d.GetType() == typeof(ScatterViewItem) est appelée Expression Lambda. Il dit "Pour tout DependencyObject, d, return (d.GetType() == typeof (ScatterViewItem))". C'est une méthode sans nom, une méthode anonyme.

longue main serait:

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

appelé avec:

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

Predicate<DependencyObject> est un type de délégué, ou "forme de signature". Il peut contenir une référence à n'importe quelle méthode qui prend un DependencyObject et retourne un booléen.

FindChildren sait utiliser le prédicat fourni pour évaluer tout ce qu'il est censé faire. Parce qu'il prend certains types de données et renvoie certains types de données, FindChildren ne se soucie pas comment l'opération se produit, il peut simplement l'appeler et savoir qu'il obtiendra une réponse utile.