I promise that this time there will be a short article (relatively). You all know the foreach language construct in C #, don't you? But think twice before saying exactly how the following code works:
foreach ( int x in src) { // Do something with x. } * This source code was highlighted with Source Code Highlighter .
foreach ( int x in src) { // Do something with x. } * This source code was highlighted with Source Code Highlighter .
foreach ( int x in src) { // Do something with x. } * This source code was highlighted with Source Code Highlighter .
foreach ( int x in src) { // Do something with x. } * This source code was highlighted with Source Code Highlighter .
foreach ( int x in src) { // Do something with x. } * This source code was highlighted with Source Code Highlighter .
foreach ( int x in src) { // Do something with x. } * This source code was highlighted with Source Code Highlighter .
Already know the answer? Let me disappoint you: if you have only
one answer, then you are
mistaken . There is no one answer to the question, because you need to know more about the type of the src variable in order to make a final decision about how the above code works ...
Obviously, you must say that the object must implement IEnumerable or IEnumerable <T>, and maybe you even mention that in the first case, the compiler will type for you when it gets the value "x", causing the IEnumerator.Current property. In other words, you convert the code into something like this:
- var e = src.GetEnumerator ();
- while (e.MoveNext ())
- {
- var x = ( int ) e.Current; // without the cast if src was an IEnumerable <T>
- // Do something with x.
- }
* This source code was highlighted with Source Code Highlighter .
Worthy attempt, but not quite true. First of all, the variable x is declared in the outer zone of visibility (which causes some trouble, if we talk about closures, but now we have a completely different topic ...). Secondly, the enumerator can implement IDisposable, and in this case, the foreach construct provides the correct release of a for “using”:
- {
- int x;
- using ( var e = src.GetEnumerator ())
- {
- while (e.MoveNext ())
- {
- x = ( int ) e.Current; // without the cast if src was an IEnumerable <T>
- // Do something with x.
- }
- }
- }
* This source code was highlighted with Source Code Highlighter .
This is more reasonable, but we missed another type of source that foreach can work with: it is any object, as long as it provides the GetEnumerator enumeration template in tandem with MoveNext and Current. For example, here’s an object that works just fine with the foreach construct.
- class Source
- {
- public SourceEnumerator GetEnumerator ()
- {
- return new SourceEnumerator ();
- }
- }
- class SourceEnumerator
- {
- private Random rand = new Random ();
- public bool MoveNext ()
- {
- return rand.Next (100)! = 0;
- }
- public int Current
- {
- get
- {
- return rand.Next (100);
- }
- }
- }
* This source code was highlighted with Source Code Highlighter .
How it is used is shown below:
- foreach ( int x in new Source ())
- Console .WriteLine (x);
* This source code was highlighted with Source Code Highlighter .
Ok, flexible, isn't it? In fact, it can be said that in the foreach construction,
duck typing : it is not the nominal type that matters (that is, when Source is explicitly declared as IEnumerable and SourceEnumerator as IEnumerator), but only the structure of the object, which determines “compatibility” with the foreach construction .
But who said that foreach over the collection immediately begins to think about LINQ? Suppose the Source class is used like this:
- List < int > res = new List < int > ();
- foreach ( int x in new Source ())
- if (x% 2 == 0)
- res.Add (x);
* This source code was highlighted with Source Code Highlighter .
Looks like a great candidate for LINQ, especially if we started adding more and more logic to our “request”. There is nothing surprising in this conclusion, but in reality, unfortunately, it falls and does not compile:

')
Why? Because in LINQ static typing
(update: in this place, the author asks to read the comments on his article and agrees that it would be more accurate in this case to speak about LINQ to Objects) , so LINQ expects me to refer to the
nominal implementation enumerator: to something that is explicitly defined as an IEnumerable, and not to something that "accidentally" turned out to be similar to an IEnumerable. Question of the day: how to convert an existing
structural enumerator into a nominal one so that it can be used with LINQ? Of course, we can write a special code for the Source object, which will create the necessary iterator from Source:
- static void Main ()
- {
- var res = from x in IterateOver ( new Source ())
- where x% 2 == 0
- select x;
- foreach ( var x in res)
- Console .WriteLine (x);
- }
- static IEnumerable < int > IterateOver (Source s)
- {
- foreach ( int i in s)
- yield return i;
- }
* This source code was highlighted with Source Code Highlighter .
But perhaps you are in such a situation, when there is a whole abundance of such structural enumerators around (for example, some Office automation libraries provide GetEnumerator in types like Range, while the Type type does not implement IEnumerable interface, therefore, it is not suitable for use with LINQ) so you want to summarize the above solution. In essence, we need the ability to add an iterator with duck typing over any object and this is a suitable task for the extender method and the dynamic keyword from C # 4.0:
- static class DuckEnumerable
- {
- public static IEnumerable <T> AsDuckEnumerable <T> ( this object source)
- {
- dynamic src = source;
- var e = src.GetEnumerator ();
- try
- {
- while (e.MoveNext ())
- yield return e.Current;
- }
- finally
- {
- var d = e as IDisposable;
- if (d! = null )
- {
- d.Dispose ();
- }
- }
- }
- }
* This source code was highlighted with Source Code Highlighter .
Question to the reader: why can't we just write a foreach loop over an “object that is cast to dynamic”? Hint: how then do you implement the translation of the foreach construct in a dynamic object?
Yes, you will pile up the required list of methods on System.Object, so be careful with using this, or simply use a call to the old flat method to "translate" the structural into the nominal. Notice how easy it looks like dynamically typed code in C # 4.0. With a large number of type conversions, it looks like this:
- static class DuckEnumerable
- {
- public static IEnumerable <T> AsDuckEnumerable <T> ( this object source)
- {
- dynamic src = (dynamic) source;
- dynamic e = src.GetEnumerator ();
- try
- {
- while (( bool ) e.MoveNext ())
- yield return (T) e.Current;
- }
- finally
- {
- var d = e as IDisposable;
- if (d! = null )
- {
- d.Dispose ();
- }
- }
- }
- }
* This source code was highlighted with Source Code Highlighter .
And now we can write this:
- var res = from x in new Source (). AsDuckEnumerable < int > ()
- where x% 2 == 0
- select x;
- foreach ( var x in res)
- Console .WriteLine (x);
* This source code was highlighted with Source Code Highlighter .
Dynamic glue - why not? In fact, even objects from other languages ​​(like Ruby or Python) that follow the paradigm of duck typing now work with LINQ, and for existing compatible objects, calling the operator is harmless (but wasteful). Oh, and note that you can also have an IEnumerable in “dynamic” objects if you are dealing with objects from dynamic languages ​​...
Can you implement the AsDuckEnumerable method in C # 3.0? Of course, if you limit yourself to reflection-based methods (left as an exercise for the reader).
Enjoy!