2015-12-28 116 views
1

委託的概念對我來說並不是太新,但我似乎無法找到如何從Func委託中獲取所有結果。更具體地說,我有一個類有一個Func委託,返回一個類型布爾。像這樣的......從Func獲取所有結果調用

private Func<Employee, Shift, bool> qualificationCheckCallback; 

回調也有'註冊'和'取消註冊'的方法。我的目標是查看代碼中存儲的任何方法是否稍後在代碼中調用時返回false。任何你可能在這個問題上的洞察力非常感謝!謝謝。

回答

0

正如在Andrew的回答中所提到的,如果您只是像調用普通方法那樣調用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); 

我並不是說這是一個很好的做法,但它可以做到的。

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事件模型的優點在於其使用的匿名性。這意味着事件訂閱者完全從 事件發佈者中抽象出來。

0

您正在使用錯誤的模式。我建議存儲這些委託的列表並遍歷列表,而不是使用多重委託來調用多個目標。

您可以通過更改簽名以包括通過引用傳遞給每個來電者一個「狀態」變量,使這項工作(如果需要):

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); 
    } 
}