Gentlemen, there are two pieces of code:

int[] nums = { 1, -2, 3, 0, -4, 5 }; 

and

 var posNums = from n in nums where n > 0 select n; 

Actually, my question is this: I can not understand what type of data is obtained from the variable posNums. At first, I decided that the collection was returning, but I realized that it was not. It turns out that the enumerator is returned. However, as I understand it, the enumerator is engaged in “enumerating” a data set in a particular class that contains this data, that is, a collection or an array. Then the question arises in this connection, is this LINQ query returning a specific class or what does it return at all? When using GetType (), I get wherearrayiterator, but what does it mean, I do not understand, and Google, too. Enlighten, please. Thank.

  • one
    > At the beginning, I decided that the collection was being returned, but I realized that it was not so on the basis of what did you understand it? - DreamChild
  • As in any literature, it says that the enumerator is returned. But the enumerator is only a method, so it cannot be returned. So the class that contains the data + enumerator is returned - Polyakov Sergey
  • one
    > Since in any literature it is said that the enumerator @polyakov_s returns then show where and in what literature it is said (preferably if this “any literature” will not always give you an example of a tongue-tied Schild with a disgusting translation, but something more adequate ). In particular, in msdn it is written in Russian and white that the return value of the Where method is IEnumerable <T>, no enumerators - DreamChild
  • @polyakov_s I see in the example given by you the following:> IEnumerable <T> provides an enumerator as you see, it is not said anywhere here that this interface is an enumerator. It says here that he provides this enumerator. These are different things - DreamChild

2 answers 2

You fill your head with some completely unnecessary details. When working with Linq, it is important to understand that you absolutely don’t need all these dreadful data types. You need only one data type (or more precisely, the interface) - this is IEnumerable <T> . There is nothing to know (with some reservations, in particular IQueriable) about types in Linq. When working with linq, you should know what an IEnumerable is, namely that it is a kind of sequence, about which we only know what kind of elements it consists of. Including we do not know anything about its length (this is a hint that IEnumerable doesn’t have the Count method, and calling it enumerates the collection), we cannot add or remove elements from it, but we know very much The important thing is that all operations in linq operate on this interface. (It is also worth noting that this interface has two important features - the danger of multiple enumeration and "lazy" calculations, which need to be discussed separately)

Never a programmer working with linq writes something like

 WhereArrayIterator foo = from ... 

He will write

 IEnumerable<Foo> foo = from ... 

and even better

 var foo = from ... 

since the data type here has a very mediocre role (and sometimes it is completely impossible to derive it in compile-time)

  • one
    Thank you. I don’t understand - yes, indeed, you are right that returns a certain object, implemented by GetEnumerator (). But in the case of the first piece of code, in addition to this, in this returned object there should be all the values ​​obtained from the array by Linq-query. And my confusion is that how does the GetEnumerator () method (namely, IEnumerator consisting of 3 methods) access the content retrieved from an array by this LINQ query using the GetEnumerator () method. After all, only IEnumerable is implemented in this object, not IEnumerator. That is, I do not understand how foreach reads data from this object - Polyakov Sergey
  • 2
    @polyakov_s has such a smart dude, Sergey Teplyakov (he has a very good blog where he writes interesting articles on C #). So I will quote one of his articles: "In order for the foreach construct to be successfully compiled it is necessary that the object has a GetEnumerator () method that returns an object with the MoveNext () method and the Current property, and if there is no such method, then we will look for interfaces IEnumerable and IEnumerable <T> " - DreamChild
  • one
    Oh, thanks for the clever dude. An interesting blog. And a special thank you to you for not sending me away because of my, sometimes, abnormal questions. - Polyakov Sergey

Which type is returned is not so important, especially since no particular type is guaranteed. Worse, this type has the right to change when the type of the nums collection changes. And of course it can change with the change of optimization settings, the release of the next version of the compiler or the installation of the service pack on the client’s machine.

The only thing guaranteed is that the return type supports the IEnumerable<T> interface. Also, if I'm not mistaken, it is guaranteed that there will be no access to nums until the actual enumeration (what is called a lazy evaluation), so this code:

 int nums[] = { 1, -2, 3, 0, -4, 5 }; var posNums = from n in nums where n > 0 select n; nums[0] = -1; Console.WriteLine(posNums.First()); 

will print 3, not 1.


wherearrayiterator is an internal detail of the current implementation. Do not rely on it.

  • Thanks for the help !!! - Polyakov Sergey
  • @polyakov_s: Please! - VladD