2010-11-04 25 views
4

J'ai une fonction,Est-il possible de définir "this" en mode anonyme?

public SharpQuery Each(Action<int, HtmlNode> function) 
{ 
    for (int i = 0; i < _context.Count; ++i) 
     function(i, _context[i]); 
    return this; 
} 

qui appelle la fonction adoptée en pour chaque élément du contexte. Est-il possible de définir ce que "ceci" signifie à l'intérieur Action<int, HtmlNode> function?

Par exemple,

sharpQuery.Each((i, node) => /* `this` refers to an HtmlNode here */); 
+0

Voulant un peu de JavaScript pour faire son chemin dans C#? :) – ChaosPandion

+0

@Chaos: Je peux vivre sans ... mais j'essaie d'imiter une certaine bibliothèque JS aussi étroitement que possible. – mpen

Répondre

1

n °

Eh bien, oui, si l'action a été créé dans un tel cadre où 'ce' était disponible et lié à une fermeture - mais transparente : non.

Transmettez toutes les informations nécessaires ou assurez-vous qu'elles sont capturées/disponibles dans l'action elle-même. Il y a d'autres hacks comme thread-locaux, etc. Mieux vaut éviter.

5

Avec un léger changement dans la fonction, vous pouvez obtenir l'effet désiré.

public SharpQuery Each(Action<MyObject, int, HtmlNode> function) 
{ 
    for (int i = 0; i < _context.Count; ++i) 
     function(this, i, _context[i]); 
    return this; 
} 

Ensuite, vous pouvez écrire votre appel de fonction comme ceci:

sharpQuery.Each((self, i, node) => /* do something with `self` which is "this" */); 

Note: La fonction anonyme n'aura accès aux membres du public cependant. Si la fonction anonyme a été définie dans la classe, elle aura accès aux membres protégés et privés comme d'habitude.

par exemple,

class MyObject 
{ 
    public MyObject(int i) 
    { 
     this.Number = i; 
    } 

    public int Number { get; private set; } 
    private int NumberPlus { get { return Number + 1; } } 

    public void DoAction(Action<MyObject> action) 
    { 
     action(this); 
    } 

    public void PrintNumberPlus() 
    { 
     DoAction(self => Console.WriteLine(self.NumberPlus)); // has access to private `NumberPlus` 
    } 
} 

MyObject obj = new MyObject(20); 
obj.DoAction(self => Console.WriteLine(self.Number));  // ok 
obj.PrintNumberPlus();         // ok 
obj.DoAction(self => Console.WriteLine(self.NumberPlus)); // error 
+0

Je suppose que vous pouvez le considérer comme une "méthode d'extension anonyme". –

+1

+1 Mais il semble que OP souhaite parfaitement simuler jQuery en C#. Votre solution fait que la méthode '.Each' diffère de celle de jQuery. En tout cas c'est la meilleure solution à laquelle je peux penser. –

+0

En fait, je voulais que "ceci" fasse référence au HtmlNode, pas à MyObject. Ce n'est pas vraiment nécessaire car je l'ai déjà passé ... mais j'essaye d'essayer de copier certaines fonctionnalités de jQuery. Je suppose que la réponse est "non". – mpen