从Func调用

时间:2015-12-28 16:15:29

标签: c# delegates

代表的概念对我来说并不新鲜,但我似乎无法找到如何从Func代表那里获得所有结果。更具体地说,我有一个类具有返回类型bool的Func委托。像这样......

private Func<Employee, Shift, bool> qualificationCheckCallback;

有两个&#39;注册&#39;并且&#39;取消注册&#39;回调的方法也是如此。我的目标是查看代理中稍后调用时委托中存储的任何方法是否返回false。您对这个问题的任何见解都非常感谢!谢谢。

3 个答案:

答案 0 :(得分:1)

您使用的是错误的模式。我建议存储这些代表的列表并迭代列表,而不是使用multidelegates来调用多个目标。

您可以通过更改签名以包含&#34;状态&#34;来完成此工作(如果您需要)。通过引用传递给每个调用者传递的变量:

private Action<Employee, Shift, QualCheckState> qualificationCheckCallback;

public class QualCheckState { public bool Passed { get; set; } }

// Call it thus:
var state = new QualCheckState { Passed = true }; // Hope for the best
qualificationCheckCallback(someEmployee, someShift, state);
if (state.Passed) {
    // Assume everyone passed
}

请记住,这要求被调用者兑现签名,而不是覆盖其他任何人的失败状态:

public void SomeCallee(Employee e, Shift s, State state) {
   // If some other check failed, don't bother doing our check.
   if (!state.Passed) return;
   // Do some check here
   if (checkFailed) state.Passed = false;
}

当然,您也可以扩展此模式以使其更安全:

public class QualCheckState {
    private List<bool> _results = new List<bool>();
    public bool Passed { get { return _results.All(s => s); }
    public void RecordResult(bool result) {
        _results.Add(result);
    }
}

答案 1 :(得分:0)

在MSDN上快速搜索找到了这个帖子:

https://social.msdn.microsoft.com/Forums/en-US/38a638fe-4a7d-44d6-876c-729d90c20737/how-to-get-return-value-from-delegate?forum=csharplanguage

  

事件的问题是返回值不能完全   值得信赖的。无论多少,您都只能获得一个返回值   您拥有该活动的订阅者。核心问题是   您无法可靠地确定哪个订户产生了回报   值。 .NET事件模型的美妙之处在于它的匿名性   使用。这意味着事件订阅者完全被抽象出来了   活动出版商。

答案 2 :(得分:0)

正如安德鲁的回答中所提到的,如果你只是像普通方法一样调用qualificationCheckCallback,那么你只能从其中一个方法中获取返回值。因此,拥有返回值的多播委托是非常罕见的。

如果您的目标是查看代理中存储的至少一个方法是否返回false,则需要单独调用这些方法。以下是使用Delegate.GetInvocationList()方法执行此操作的一种方法:

bool hasAtLeastOneFalse = false;
if (qualificationCheckCallback != null)
{
    foreach(var f in qualificationCheckCallback.GetInvocationList()
                                               .Cast<Func<Employee, Shift, bool>>())
    {
        if (!f(employee, shift))
        {
            hasAtLeastOneFalse = true;
            // break; // If you don't care about invoking all delegates, you can choose to break here.
        }
    }
}

Console.WriteLine(hasAtLeastOneFalse);

我并不是说这是一个很好的做法,但可以做到。