Action is a delegate type, and in C# delegate types (like Action
, Func
and Predicate
, or just straight up delegate
) are ways of passing methods around as parameters. Delegate types can be called directly by doing itemBuilder(rib)
, this executes the Action (Method) itemBuilder
with the parameter rib
.
What it does is this:
First we declare the method with the Action parameter
public ReceiptBuilder WithItem(string text, Action<ReceiptItemBuilder> itemBuilder)
Action<ReceiptItemBuilder>
Limits our parameter to methods that return a void
and take one parameter of type ReceiptItemBuilder
.
So we can now declare a method that fits these criteria. Here's mine:
public void ItemWithIngredient(ReceiptItemBuilder itemBuilder)
{
itemBuilder.WithIngredients("Ingredients1");
}
And pass to WithItem
like so:
WithItem("Item1", ItemWithIngredient);
Now this isn't of much use as we can't change the Ingredients, as we hardcoded it. So instead we us something called a anonymous method, and we define it with a lambda expression like so:
WithItem("Item1", i => i.WithIngredients("Ingredients1"));
The i => ...
part basically declares a method and uses it. i
here is the parameter and is of type ReceiptItemBuilder
.
This Answer is kinda rambly and I'm bad at explaining things. I highly suggest you check out the Links posted in the comments by Olivier Rogier but here's a quick overview over the three standard delegate types:
Action: Action
is a method that returns a void and takes no parameters. It has some Overloads like Action<T>
which represents a method with one parameter of type T
(replace T
with any type you want). There are more overloads for more parameters (Action<T1, T2>
, Action<T1, T2, T3>
...)
Func: Func<T>
is a method that returns T
and takes no parameters (there is no Func
as Func always returns something). There are overloads for this as well, these take parameters (Func<TInput, TOutput>
, Func<TInput1, TInput2, TOutput>
...)
Predicate: A Predicate<T>
always takes one parameter and returns a bool