Hi,
Can somebody explain what is the exact reason behind using Action<T>
and Predicate<T>
as delegates in C#
views:
161answers:
5What else would they be? Delegates are the most flexible and closest match to what Action<T>
, Predicate<T>
and Func<T>
are modlling - an invocation list with specified parameter types (aka delegates).
You are looking at the problem from the wrong point of view.
The question should not be "Why are Action<>
, Func<>
& Predicate<>
delegates?" (The answer to that is "because they need to be")
The real question is, "Why do we have specific named objects, to handle simple delegate tasks? Why use Action<>
in a place where a ordinary delegate would work?"
The answer is that those particular delegates are used a lot on the CLR itself, and since that they are used in CLR methods where the end developers will have to defined the method being called, the declaration for the delegate would have to be public. So, Microsoft could have defined thousands of delegates, each used by just one CLR method, or define a simple way to specific what type of delegate is needed.
The best way to explain why the idiom for performing action and predicate operations using the Action<T>
and Predicate<T>
delegates was chosen is to first consider the alternative. How could you accomplish the same thing without delegates? The next best thing would be to have interfaces IAction
and IPredicate
and force developers to declare a class and implement the appropriate interface for each different type of operation needed. But, the problem with that approach is that it requires more effort, more class proliferation, and less maintainable code. The delegate approach is a lot more convenient because you can write the logic inline with where it will be used using anonymous methods or lambda expressions.
Are you asking why they exist, or why they're defined as delegates?
As to why they exist, perhaps the best reason is convenience. If you want a delegate that returns no value and takes a single parameter of some type, they you could define it yourself:
public delegate void MyDelegate(int size);
And then later create one:
MyDelegate proc = new MyDelegate((s) => { // do stuff here });
And, of course, you'd have to do that for every different type you want to have such a method.
Or, you can just use Action<T>
:
Action<int> proc = new Action<int>((s) => { /* do stuff here */ });
Of course, you can shorten that to:
Action<int> proc = (s) => { /* do stuff here */ });
As to "why are they delegates?" Because that's how function references are manipulated in .NET: we use delegates. Note the similarities in the examples above. That is, MyDelegate
is conceptually the same thing as an Action<int>
. They're not exactly the same thing, since they have different types, but you could easily replace every instance of that MyDelegate
in a program with Action<int>
, and the program would work.