locked
why foreach(var s in StringCollection) returns string [see detail] RRS feed

  • Question

  • as StringCollection(in System.Collection.Specialized) only implement IEnumerable, at its explicit implementation of IEnumerable.GetEnumerator it simply return inner arraylist's Enumerator.

    StringCollection also has a public GetEnumerator which return a StringEnumerator object, but the StringEnumerator class doesn't derives from IEnumerator nor IEnumerator<String>

    so how does VS know the variable s is a string in statements like(foreach(var s in StringCollection))?

          var strCollec = new StringCollection();
          strCollec.Add("sfef");
          strCollec.Add("sdifje ");
    
          foreach (var s in strCollec)
            Console.WriteLine(s.Length);
    


     

     

    Thursday, June 30, 2011 4:22 PM

Answers

  • If you read section 8.8.4 of the C# spec, foreach doesn't necessarily use IEnumerable.  It actually checks for a class returned by a "GetEnumerator" method (by name), then checks the return type of the "Current" identifier, and uses that return type.  (This is done at compile time.)

     

    In this case, StringCollection explicilty implements IEnumerable, but provides a public GetEnumerator that returns the StringEnumerator.  This is found, then the Current property of StringEnumerator is checked, which returns string.  The compiler sees this, and decides that s is a string.

     

    This was done specifically to allow this type of "type safe" collection to be generated prior to generics.  I suspect that, if the language was being designed today, this might not be the same way - but in .NET 1.1 days, without this, every foreach would've required a cast.

     


    Reed Copsey, Jr. - http://reedcopsey.com
    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".
    • Proposed as answer by RaheelKhan Friday, July 1, 2011 11:19 AM
    • Marked as answer by Tom Shark Friday, July 1, 2011 1:15 PM
    Thursday, June 30, 2011 4:53 PM

All replies

  • If you read section 8.8.4 of the C# spec, foreach doesn't necessarily use IEnumerable.  It actually checks for a class returned by a "GetEnumerator" method (by name), then checks the return type of the "Current" identifier, and uses that return type.  (This is done at compile time.)

     

    In this case, StringCollection explicilty implements IEnumerable, but provides a public GetEnumerator that returns the StringEnumerator.  This is found, then the Current property of StringEnumerator is checked, which returns string.  The compiler sees this, and decides that s is a string.

     

    This was done specifically to allow this type of "type safe" collection to be generated prior to generics.  I suspect that, if the language was being designed today, this might not be the same way - but in .NET 1.1 days, without this, every foreach would've required a cast.

     


    Reed Copsey, Jr. - http://reedcopsey.com
    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".
    • Proposed as answer by RaheelKhan Friday, July 1, 2011 11:19 AM
    • Marked as answer by Tom Shark Friday, July 1, 2011 1:15 PM
    Thursday, June 30, 2011 4:53 PM
  • Hi,

    foreach checks for public GetEnumerator() from in part, in this case "StringCollection"

    And GetEnumerator() return type must have implemented methods

    Current, MoveNext and Reset so that it can traverse through each type in collection.

     

    StringCollection's GetEnumerator() method returns StringEnumerator. Which implements these methods so no complains when you use foreach

    Hope this helps you...


    If this post answers your question, please click "Mark As Answer". If this post is helpful please click "Mark as Helpful".
    Thursday, June 30, 2011 5:00 PM
  • Ironically, Eric Lippert decided to blog on this very subject today: http://blogs.msdn.com/b/ericlippert/archive/2011/06/30/following-the-pattern.aspx

     

    I'd strongly recommend reading this - it's a great discussion of the rationale behind using the pattern based approach instead of interface based approach.


    Reed Copsey, Jr. - http://reedcopsey.com
    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".
    Thursday, June 30, 2011 5:09 PM