【问题标题】:c# "OR" event delegates returning boolc# "OR" 事件代表返回 bool
【发布时间】:2010-09-18 06:19:48
【问题描述】:

我在 XNA 中为我的游戏创建了一个控制台,并且在输入命令时我有一个委托。目前,委托正在返回一个布尔值。我在 Console 类中声明了一个事件(返回 false),然后从其他类订阅了这个事件。这个想法是,如果订阅此事件的所有类都没有返回 true,则假定用户输入了无效命令。但是,如果至少有一个订阅的类返回 true,则假定该命令有效。

目前,只考虑一个类来返回 true 或 false,有没有一种方法可以查看所有订阅类的返回值,然后 OR 他们的结果?

谢谢,

【问题讨论】:

  • Nice Q - AFAIK 一个简单的分配将始终只返回最后一个订阅者的结果。

标签: c# .net events delegates xna


【解决方案1】:

在声明事件的类中,您可以检索事件的调用列表(假设是类字段事件)。单独调用它们中的每一个将允许您检查事件的每个订阅者的返回值。

例如:

public event Func<bool> MyEvent = delegate { return false; };

...     

private bool EmitMyEventAndReturnIfAnySubscriberReturnsTrue()
{
    return MyEvent.GetInvocationList()
                  .Cast<Func<bool>>()
                  .Select(method => method()) 
                  .ToList() //Warning: Has side-effects
                  .Any(ret => ret);
}

在此示例中,每个订阅者都被告知该事件 - 如果其中任何一个响应肯定,则不会发生短路。如果需要,可以通过删除对 ToList() 的调用轻松更改此行为。

说实话,我不太喜欢返回值的事件。它们的语义对订阅者来说并不明显。如果可能的话,我会改变设计。

编辑:更正了根据 Timwi 的评论强制完全执行序列的错误。

【讨论】:

  • 我不会想到为此使用 LINQ。很好的答案。
  • 我看了两种不同的设计,这两种设计都比较干净。而且它很容易理解和实施。我不熟悉 LinQ,但我确实找到了如下所述的替代解决方案。
  • @Dave:您发布的替代解决方案与我的回答具有相同的想法 - 诀窍是访问调用列表。太好了。
  • @Kirk Woll:谢谢。由于查询的副作用性质,我想知道我是否不应该为此使用 LINQ,但我认为这不是这个问题的重要方面,所以继续。
  • 为什么不删除 Select 和 ToList 而只做.Any(method =&gt; method());
【解决方案2】:

我在提出这个问题时就想通了:P

bool handled = false;
foreach (Delegate d in CommandProcessed.GetInvocationList())
    handled |= (bool) d.DynamicInvoke (gameTime, command.ToString());

if (!handled) { } // Command Unrecognized

CommandProcessed 是我的类订阅的事件。
我的委托有两个参数:游戏时间和命令字符串。

【讨论】:

  • 是的 - 我最近必须解决同样的问题以进行链式验证。按位或运算符不会像布尔或运算符那样短路。
【解决方案3】:

我同意事件返回值的问题,因为这对我来说也是如此。然而,另一种选择是您可以创建一个新类CommandEventArgs

class CommandEventArgs : EventArgs
{
    public DateTime GameTime {get; set; }
    public string Command {get; set;}
    public bool Valid {get; set;}
}

然后使用此方法的一个实例来调用事件,然后如果侦听器识别出该命令,则将其设置Valid 为真。因此,如果Valid 在调用后仍然为假,则您知道该命令无法识别。

这是 .NET 处理您将 KeyEventArgs.Handled 设置为 true 的键盘事件的方式,以抑制事件发生的任何进一步操作。

【讨论】:

    猜你喜欢
    • 2015-12-21
    • 2017-02-22
    • 1970-01-01
    • 1970-01-01
    • 2013-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-10
    相关资源
    最近更新 更多