I want to know the basic IEnumerable
functionality uses in LINQ.
See my code:
string[] fruits = new string[] {"apple", "plum", "cherry"};
IEnumerable<string> results = from a in fruits
select a;
My question is:
In the first line I am declaring a string array, string array is an IEnumerable
type right?
In the second line, we are initializing a variable of type IEnumerable
and applying LINQ query to fetch the results.
Even though string array (fruits
) is an IEnumerable
type, what is the need of casting it into an IEnumerable
type again?
Could anyone help me to understand this simple question.
I want to know the basic IEnumerable
functionality uses in LINQ.
See my code:
string[] fruits = new string[] {"apple", "plum", "cherry"};
IEnumerable<string> results = from a in fruits
select a;
My question is:
In the first line I am declaring a string array, string array is an IEnumerable
type right?
In the second line, we are initializing a variable of type IEnumerable
and applying LINQ query to fetch the results.
Even though string array (fruits
) is an IEnumerable
type, what is the need of casting it into an IEnumerable
type again?
Could anyone help me to understand this simple question.
Share Improve this question edited Feb 1 at 6:29 marc_s 756k184 gold badges1.4k silver badges1.5k bronze badges asked Feb 1 at 5:37 stackoverflowresearch456 sstackoverflowresearch456 s 591 silver badge5 bronze badges 8 | Show 3 more comments2 Answers
Reset to default 4In the first line I am declaring a string array, String array is a IEnumerable type right?
Yes, it is not only just IEnumerable
but IEnumerable<string>
also.
In the second line, we are initializing a variable of type IEnumerable and applying LINQ query to fetch the results
Actually there is no fetching results here happening since enumeration is lazy and you have not applied an operation which will trigger it (like ToArray()
, ToList()
, Count()
, foreach
etc...)
The following:
IEnumerable<string> results = from a in fruits
select a;
Is actually turned by the compile in something like:
IEnumerable<string> results = fruits.Select(a => a);
Which is call to the Enumerable.Select
extension method. Note that results
is an IEnumerable<string>
but not an array, i.e. Console.WriteLine(results is string[]);
will result in False
while Console.WriteLine(fruits is string[]);
is obviously True
.
Also note that select
can contain some data manipulations like select a + " is a fruit!"
, which will not change the data type of the returned value (in the provided case, but you can use one which will) but will result in different data returned on enumeration.
Decompilation to C# @sharplab.
what is the need of casting it into an IEnumerable type again?
There is no casting, you are explicitly defining variable type for new variable result
. You could use var
i.e. var result = ...
(though compiler would determine the type to be the same - IEnumerable<string>
)
I think your real question might be:
Why do LINQ's operators return an
IEnumerable<string>
and not for examplestring[]
even thoughstring[]
implementsIEnumerable<string>
?
Microsoft could have implemented something similar to this for the Where
operator (and other LINQ Operators) - work with C<T>
concrete types instead of IEnumerable<T>
:
public static class LinqExtensions {
public static C Where<C, T>(this C collection, Func<T, bool> predicate)
where C : ICollection<T>, new() {
var filtered = new C();
foreach (var element in collection) {
if (predicate(element)) {
filtered.Add(element);
}
}
return filtered;
}
}
so then you could write what you want:
string[] filtered = stringArray.Where(x => x.Contains("foo"));
As you see - we have to be able to initialize a new C
and also be able to Add
the filtered items. This means that we no longer can work with just IEnumerable<T>
, we have to work with ICollection<T>
which guarantees us the Add
method.
But the real issue is that we HAVE to eagerly build the concrete type at each step.
Imagine we had a more real-life scenario where we stacked conditions:
string[] filteredArray = stringArray
.Where(x => x.Contains("hello")
.Where(x => x.Length>5);
With the concrete-type approach, we would build TWO arrays in the process at each step. But if we just returned IEnumerable<string>
instead of string[]
we can
- Delay the filtering operation until a later point
- Possibly apply both filters in one enumeration step
- Have option of what concrete type to materialize to - maybe we would need a
List<string>
instead ofstring[]
IEnumerable<string> result = (IEnumerable<string>)fruits
and it is indeed would be pointless. – Guru Stron Commented Feb 1 at 6:00