The concept of delegates aren't too new to me but I cannot seem to find out how to get all results from a Func delegates. More specifically, I have a class that has a Func delegate that returns a type bool. Something like this...
private Func<Employee, Shift, bool> qualificationCheckCallback;
There are both 'register' and 'unregister' methods for the callback as well. My goal is to see if any of the methods stored in the delegate return false when invoked later in code. Any insight you may have on this issue is much appreciated! Thanks.
As mentioned in Andrew's answer, if you simply invoke qualificationCheckCallback
like a normal method, you'll only get back the return value from one of the methods. For this reason, it's pretty unusual to have multicast delegates that have a return value.
If your goal is to see if at least one of the methods stored in your delegate returns false, you'll need to invoke the methods individually. Here is one way to do that using the Delegate.GetInvocationList() method:
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);
I'm not suggesting this is a good practice, but it can be done.
You are using the wrong pattern. I'd recommend storing a list of these delegates and iterating over the list, rather than using multidelegates to call multiple targets.
You can make this work (if you need to) by changing the signature to include a "state" variable that is passed by reference to each caller:
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
}
Keep in mind, this requires the callees to honor the signature, and not overwrite anyone else's failed state:
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;
}
Of course, you can also extend this pattern to make it safer:
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);
}
}
A quick search on MSDN found this thread:
https://social.msdn.microsoft.com/Forums/en-US/38a638fe-4a7d-44d6-876c-729d90c20737/how-to-get-return-value-from-delegate?forum=csharplanguage
The problem with events is that the return values cannot be fully
trusted. You will get only one return value no matter how many
subscribers that you have for the event. The central issue is that
you cannot reliably determine which subscriber produced the return
value. The beauty of the .NET Event Model is the anonymity that it
uses. That means event subscribers are completely abstracted from the
event publishers.