2009-04-21 6 views
3

Je travaille à travers Josh Smith's CommandSink Example et les structures base.Executed += (s, e) =>... me lancent, quelqu'un peut-il aider à rendre ce cristal clair?quelqu'un peut-il expliquer cette structure C#: base.Executed + = (s, e) =>

ce que je comprends:

  • base.CanExecute est l'événement de la classe héritée CommandBinding
  • le + = est l'ajout d'un délégué à cet événement
  • le délégué est la fonction anonyme qui suit cette ligne

ce que je ne comprends pas:

  • est (s, e) est la signature de cette fonction?
  • Où la variable s est-elle utilisée?

Voici le code dans le contexte:

public class CommandSinkBinding : CommandBinding 
    { 
     #region CommandSink [instance property] 

     ICommandSink _commandSink; 

     public ICommandSink CommandSink 
     { 
      get { return _commandSink; } 
      set 
      { 
       if (value == null) 
        throw new ArgumentNullException("Cannot set CommandSink to null."); 

       if (_commandSink != null) 
        throw new InvalidOperationException("Cannot set CommandSink more than once."); 

       _commandSink = value; 

       base.CanExecute += (s, e) => 
        { 
         bool handled; 
         e.CanExecute = _commandSink.CanExecuteCommand(e.Command, e.Parameter, out handled); 
         e.Handled = handled; 
        }; 

       base.Executed += (s, e) => 
        { 
         bool handled; 
         _commandSink.ExecuteCommand(e.Command, e.Parameter, out handled); 
         e.Handled = handled; 
        }; 
      } 
     } 
     ... 

Répondre

11

(s, e) est la méthode Paramètre Signature pour le gestionnaire d'événement (dans ce cas la méthode Anoymous qui est défini)

pense (object Sender, EventArgs e)

Le paramètre s n'est tout simplement pas utilisé dans le reste de la méthode, ce qui est correct. Il doit être là pour correspondre à la signature attendue

base.CanExecute += (s, e) => 
        { 
         bool handled; 
         e.CanExecute = _commandSink.CanExecuteCommand(e.Command, e.Parameter, out handled); 
         e.Handled = handled; 
        }; 

est l'équivalent de faire

base.CanExecute += new EventHandler(myMethod_CanExecute); 

///.... 
protected void myMethod_CanExecute(object sender, EventArgs e) 
{ 
    bool handled; 
    e.CanExecute = _commandSink.CanExecuteCommand(e.Command, e.Parameter, out handled); 
    e.Handled = handled; 
}; 
+0

donc vous pourriez aussi écrire (expéditeur, e) ou même (whatevernnn, e), c'est juste un espace réservé, non? –

+0

Correct. La signature (s, e) ou (jimbob, blahvar) est juste votre convention de nommage pour les paramètres afin que vous puissiez les référencer dans le reste de la déclaration de méthode anonyme. Mais vous devriez vous en tenir à quelque chose d'assez évident comme (s, e)/(expéditeur, e)/(expéditeur, args) –

1

Oui, (s, e) est la signature. La fonction doit avoir la signature définie par l'événement (CommandBinding.CanExecute: http://msdn.microsoft.com/en-us/library/system.windows.input.commandbinding.canexecute.aspx).

La variable s n'est pas utilisée, dans cet exemple particulier. L'événement suit le même modèle de conception que la plupart des autres événements dans .NET. Le premier paramètre contient généralement une référence à l'instance qui a déclenché l'événement, le deuxième paramètre contient une classe EventArgs (ou une classe plus spécialisée qui hérite EventArgs). Dans ce cas, le deuxième paramètre serait une instance du type CanExecuteRoutedEventArgs (sauf si j'ai mal interprété des informations).

1

(s, e) est une sorte de signature - mais son interprétation dépend de l'inférence du compilateur C#. Le compilateur C# sait que le type de Executed est ExecutedRoutedEventHandler, ce qui équivaut à void delegate(object, ExecutedRoutedEventArgs). Il voit l'expression lambda (s, e) => { ... } et détermine que s doit être de type objet, e doit être de type ExecutedRoutedEventArgs, et l'expression entière est une fonction de (objet, ExecutedRoutedEventArgs) à void.

Comme d'autres l'ont noté, s est là parce que s'il n'y était pas, la fonction anonyme ne serait pas conforme à la signature requise par ExecutedRoutedEventHandler. Certaines langues ont une notation spéciale pour dire "ce paramètre doit être ici pour des raisons techniques formelles, mais cela ne m'intéresse pas". C# ne le fait pas, donc il doit nommer le paramètre même s'il n'est pas utilisé.

+0

ok, dans System.Windows.Input ExecutedRoutedEventHandler est défini ainsi: public delegate void ExecutedRoutedEventHandler (expéditeur d'objet, ExecutedRoutedEventArgs e) qui détermine la signature, donne un sens –

1
base.CanExecute += (s, e) => 
       { 
        bool handled; 
        e.CanExecute = _commandSink.CanExecuteCommand(e.Command, e.Parameter, out handled); 
        e.Handled = handled; 
       }; 

Ce que vous voyez ici est Lambda en C# 3.

En C# 2 serait: -

base.CanExecute += delegate(object s, EventArgs e) 
       { 
        bool handled; 
        e.CanExecute = _commandSink.CanExecuteCommand(e.Command, e.Parameter, out handled); 
        e.Handled = handled; 
       }; 

C# 3 permet à ce (s, e) la contraction depuis sa mesure impliquer les types du côté droit (il peut voir que CanExecute prend un type de délégué et quels sont ses types). Le => exprime la fonction à exécuter, souvent les accolades ne sont pas nécessaires pour une simple expression de ligne simple.

+0

merci, je me souviens avoir lu qu'une caractéristique de C# 3 est qu'il peut "inférer des informations" et ne l'a pas vraiment compris, cela doit être un exemple de cela: il peut déduire des types de paramètres le fait qu'il y ait un délégué là en premier lieu –

Questions connexes