Effective C# (Covers C# 6.0), (includes Content Update Program): 50 Specific Ways to Improve Your C#, 3rd Edition By Bill Wagner 讀後心得
在撰寫程式時,委派常被用來通知外部執行的溝通介面;C# 提供三種委派型別。
1. Action<T>(輸入 T、回傳值為 void)
2. Predicate<T>(輸入T、回傳值為 bool)
3. Func<T, TResult>(輸入T、回傳值為 TResult)
2. Predicate<T>(輸入T、回傳值為 bool)
3. Func<T, TResult>(輸入T、回傳值為 TResult)
Note:Predicate<T> 與 Func<T, bool> 在編譯器中並不相同,即便輸入型別皆為 T、回傳型別皆為 bool。
委派的物件內部擁有一個儲存方法記憶體位置的容器,並使用 += 與 -= 處理事件方法的掛載與卸載;當委派物件觸發方法(群)時,將依照掛載方法順序執行(chain)。當方法有一個以上時,需注意若僅是觸發委派;則只會回傳最後一個方法的結果,中間的結果會被忽略。若要個別取得方法結果需呼叫 GetInvocationList 逐一執行並取得結果。
範例程式碼:
internal class PredicateTest
{
private List<int> _container = new List<int>( ) { 1, 2, 3, 4, 5 };
public void lengthyOperation( Func<bool> pred )
{
foreach ( var item in _container )
{
// Do something
Debug.WriteLine( $"lengthyOperation Do something at item : {item}." );
if ( !pred( ) )
return;
}
}
public void lengthyOperation2( Func<bool> pred )
{
bool isContinue = true;
foreach ( var item in _container )
{
// Do something
Debug.WriteLine( $"lengthyOperation2 Do something at item : {item}." );
foreach ( Func<bool> pr in pred.GetInvocationList( ) )
isContinue &= pr( );
if ( !isContinue )
return;
}
}
}
Client 程式碼:
Func<bool> cp = ( ) => false;
cp += ( ) => true;
var x = new PredicateTest( );
x.lengthyOperation( cp );
x.lengthyOperation2( cp );
輸出:
lengthyOperation Do something at item : 1.
lengthyOperation Do something at item : 2.
lengthyOperation Do something at item : 3.
lengthyOperation Do something at item : 4.
lengthyOperation Do something at item : 5.
lengthyOperation2 Do something at item : 1.
結論:
1. 在設計方法時也可試著設計委派型別為引數,讓外部決定處理邏輯;增加設計彈性與封裝性。
2. 使用 GetInvocationList 取得個別方法的結果,否則只會回傳最後一個方法的執行結果。
3. GetInvocationList 回傳結果為 Delegate [ ],在 foreach 繞行時需明確宣告為 Func<bool>。
1. 在設計方法時也可試著設計委派型別為引數,讓外部決定處理邏輯;增加設計彈性與封裝性。
2. 使用 GetInvocationList 取得個別方法的結果,否則只會回傳最後一個方法的執行結果。
3. GetInvocationList 回傳結果為 Delegate [ ],在 foreach 繞行時需明確宣告為 Func<bool>。