The following is a simplistic cheat-sheet:
T X(T1 p1,... Tn pn)
A method is a named block of code that (optionally) accepts parameters and (optionally) returns values. (Honestly, if you don’t know what a method is, don’t bother read the rest of this – you have other stuff to learn first).
An anonymous method is a block of code that is not named, but instead is assigned directly to any of the delegate types mentioned below.
delegate T X(T1 p1,... Tn pn)
A delegate is a reference to a method of type
T with a particular signature (accepts parameters
pn of types
Tn). A member that is a delegate can be assigned, and reassigned, during run-time, with references to different methods of the same signature. A call to the member triggers a call to the referenced method.
predicate X(T p)
A predicate is a specialized delegate that accepts a parameter
p of type
T and returns a Boolean.
Func<T1,...Tn, R> X
Func is syntactic sugar for
delegate R X<T1,...Tn>(T1 p1,... Tn pn) – a delegate for a method that returns a value of type
R and accepts parameters of type
Action is syntactic sugar for
delegate void X<T1,...Tn>(T1 p1,... Tn pn) – a delegate for a method that does not return a value but accepts parameters of type
Do you want to assign different algorithms to the same procedural call?
-> Yes: Does the algorithm need to return a value?
–> Yes: Will the algorithm test an input parameter and return a bool?
—> Yes: consider using Predicate
—> Otherwise: use a Func.
–> No: Use an Action
-> No: use a method.
You can see more about when to use each here: