3

我正在研究Josh Smith 的 CommandSink 示例base.Executed += (s, e) =>...结构让我很困惑,有人能帮我弄清楚吗?

我的理解:

  • base.CanExecute 是继承类 CommandBinding 上的事件
  • += 正在向该事件添加委托
  • 委托是遵循该行的匿名函数

我不明白的是:

  • (s,e) 是该函数的签名吗?
  • 变量 s 在哪里使用?

这是上下文中的代码:

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;
                    };
            }
        } 
        ...
4

4 回答 4

11

(s, e)是事件处理程序的方法参数签名(在这种情况下是定义的匿名方法)

思考(object Sender, EventArgs e)

s参数只是没有在方法的其余部分中使用,这很好。它必须在那里以匹配预期的签名

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

相当于做

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;
};
于 2009-04-21T07:13:49.167 回答
1

是的,(s, e) 是签名。该函数必须具有事件定义的签名(CommandBinding.CanExecute:http: //msdn.microsoft.com/en-us/library/system.windows.input.commandbinding.canexecute.aspx)。

在此特定示例中,未使用变量 s。该事件遵循与 .NET 中的大多数其他事件相同的设计模式。第一个参数通常包含对引发事件的实例的引用,第二个参数包含 EventArgs 类(或更专业的继承 EventArgs 的类)。在这种情况下,第二个参数将是 CanExecuteRoutedEventArgs 类型的实例(除非我误解了任何信息)。

于 2009-04-21T07:15:59.007 回答
1

(s, e) 是一种签名——但它的解释取决于 C# 编译器的推断。C#编译器知道Executed的类型是ExecutedRoutedEventHandler,相当于void delegate(object, ExecutedRoutedEventArgs). 它查看 lambda 表达式(s, e) => { ... }并确定 s 必须是 object 类型,e 必须是 ExecutedRoutedEventArgs 类型,整个表达式是从 (object, ExecutedRoutedEventArgs) 到 void 的函数。

正如其他人所指出的,s 存在是因为如果它不存在,匿名函数将不符合 ExecutedRoutedEventHandler 所需的签名。一些语言有一个特殊的符号来表示“这个参数必须在这里出于正式的技术原因,但我对此不感兴趣。” C# 没有,所以它必须命名参数,即使它没有被使用。

于 2009-04-21T07:18:07.113 回答
1
base.CanExecute += (s, e) =>
                {
                    bool handled;
                    e.CanExecute = _commandSink.CanExecuteCommand(e.Command, e.Parameter, out handled);
                    e.Handled = handled;
                };

您在这里看到的是 C# 3 中的 Lambda。

在 C# 2 中,这将是:-

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

C# 3 允许这种 (s, e) 收缩,因为它能够从右侧暗示类型(它可以看到 CanExecute 采用委托类型以及它的参数是什么类型)。

=> 表示要执行的函数,简单的单行表达式通常不需要大括号。

于 2009-04-21T07:23:18.473 回答