The MSDN gives this code example in the article on the Func Generic Delegate:
Func<String, int, bool> predicate = ( str, index) => str.Length == index;
String[] words = { "orange", "apple", "Article", "elephant", "star", "and" };
IEnumerable<String> aWords = words.Where(predicate).Select(str => str);
foreach (String word in aWords)
Console.WriteLine(word);
I understand what all this is doing. What I don't understand is the
Select(str => str)
bit. Surely that's not needed? If you leave it out and just have
IEnumerable<String> aWords = words.Where(predicate);
then you still get an IEnumerable back that contains the same results, and the code prints the same thing.
Am I missing something, or is the example misleading?
A Func in C# is a way to define a method in-line that has a return value. There is a similar concept of an Action that doesn't have a return value, but we'll get to that in a sec. The return value's type is always the last generic parameter on the Func 's definition.
Func is a generic delegate included in the System namespace. It has zero or more input parameters and one out parameter. The last parameter is considered as an out parameter. This delegate can point to a method that takes up to 16 Parameters and returns a value.
TResult. The type of the return value of the method that this delegate encapsulates. This type parameter is covariant.
Action delegate can contain a maximum of 16 input parameters and does not have any return type.
The Select
is indeed redundant.
I suspect that this example may have been "translated" from the query comprehension syntax, as in:
IEnumerable<String> aWords =
from w in words
where (...)
select w;
When using this syntax, you have to select
at the end, it's just how the compiler works. When using the Where
extension method, however, it's completely unnecessary unless you actually need to do a separate projection.
Or, maybe it's just a mistake. The MSDN writers aren't infallible!
No it's not needed.
Such a construct could be used if you wanted to force a sequence to be lazily evaluated i.e. to prevent casting. If you had a method that returned a List<T>
but declared an IEnumerable<T>
return type then a client could cast the return type and manipulate the underlying list directly. Obviously this is a very bad idea, but a class could protect its state by applying an identity select such as the one used in this example:
public IEnumerable<T> Items
{
get { return privateList.Select(i => i); }
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With