In this case, we are talking about the Команда pattern described in the classic book on patterns. (first available link from google)
The Команда allows you to wrap an action in an object and then, for example, place actions (operations) in a queue, transfer and, in general, perform them not immediately, but when necessary.
The question arises how to wrap up the action. Usually we describe the action as a function, and store the address of this function. Modern processors allow you to indirectly call functions, that is, transfer control to an address located at a different address.
The only limitation is that all such functions must have an identical signature, that is, the number and type of parameters, as well as the type of the return value.
Thus, we actually store, transfer and place in the queue a regular integer, which we interpret as the address of a function in the address space of our process.
C # is a managed language, and it protects us a bit from such an extra-flexible construction. It introduces a data type as a delegate to consistently handle static class methods, class instance methods, and even collections of these methods. In addition, he strictly enforces signatures.
You can describe the type of Foo as a delegate:
delegate void Foo(int a);
In a variable of this type, it will be possible to place several pointers to methods that receive an integer and do not return anything.
private void Print(int number) { Console.WriteLine(number); } private void Print2(int number) { Console.WriteLine(2 * number); } . . . Foo foo; foo += Print; // на самом деле здесь всё сложнее, но пока можно считать, что всё просто foo += Print2; foo(5); // напечатает 5 на первой строке и 10 на второй
Important aspects: all methods must have the same signature. This signature matches the delegate signature. Calling a delegate looks like a method call, but in fact it leads to calling all the methods that are added to the delegate.
Now look at the type of Action<T> . It is described as:
delegate void Action<in T>(T obj);
Angle brackets in this case say that the type is generalized, that is, instead of T then you can substitute a specific type. In fact, we described a delegate with a signature of one parameter of some type and no return values .
public Command(Action<object> action) { ExecuteDelegate = action; }
Here, as a parameter, we get a delegate that is specialized with the object type, that is, the full delegate type of Action<object> . If we recall the signature, it means that we can pass here any method that accepts a parameter of type object and returns nothing. We save this method in the ExecuteDelegate property. Subsequently, we can perform an action at any time using the Execute method:
public void Execute(object parameter) { ExecuteDelegate(parameter); }
Finally, answer your question. In the implementation of the Команда pattern, this feature of the C # language is used as delegates . Thanks to generic programming in C #, you can use such a type as Action<T> to describe a whole group of delegates: all methods with one parameter that return no value. The Команда pattern uses a specific specialization of a generalized type, namely Action<object> which corresponds to methods with a single parameter of type object . Angle brackets are lexemes by which generic types are designated in C #, both descriptions and specializations.