Author Topic: What the Duck - ForEach, IEnumerable, IEnumerator DuckTyping  (Read 3176 times)

0 Members and 1 Guest are viewing this topic.

Jeff H

  • Needs a day job
  • Posts: 6131
I never knew how much duck typing was going on under hood.
Do not have to implement IEnumerable or IEnumerator.
For a for each loop to work on a object just needs a method called GetEnumerator that returns an Object that has method MoveNext that returns a bool and a property Current that returns any type.
Had it return StreamReader, etc......
Code - C#: [Select]
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Collections;
  6. using System.IO;
  7. namespace WhatTheDuck
  8. {
  9.     class Program
  10.     {
  11.         static void Main(string[] args)
  12.         {
  13.             Duck d = new Duck();
  14.  
  15.             foreach(var i in d)
  16.             {
  17.                 Console.WriteLine("{0}{1}{0}", "*Duck*", i);
  18.             }
  19.             Console.ReadLine();
  20.         }
  21.     }
  22.     public class Duck
  23.     {
  24.         public Quack GetEnumerator()
  25.         {
  26.             return new Quack();            
  27.         }
  28.        
  29.     }
  30.     public class Quack
  31.     {
  32.         static int counter = 0;
  33.         public int Current
  34.         {
  35.             get
  36.             {
  37.                 counter++;
  38.                 Console.WriteLine("*Quack*Current*Quack*");
  39.                 return counter;
  40.                 //return new StreamReader(@"C:\Testing\SSM.txt");
  41.             }
  42.         }
  43.         public bool MoveNext()
  44.         {
  45.             Console.WriteLine("*Quack*MoveNext*Quack*");
  46.             return counter < 10;
  47.         }
  48.         //public void Reset()
  49.         //{
  50.         //    counter = 1;
  51.         //}
  52.     }
  53. }
  54.  
  55.  

kaefer

  • Swamp Rat
  • Posts: 572
Re: What the Duck - ForEach, IEnumerable, IEnumerator DuckTyping
« Reply #1 on: June 18, 2013, 10:58:29 AM »
I never knew how much duck typing was going on under hood.

Me too. But see the C# spec:

Quote
The compile-time processing of a foreach statement first determines the collection type, enumerator type and element type of the expression. This determination proceeds as follows:
    If the type X of expression is an array type then ...
    If the type X of expression is dynamic then ...
    Otherwise, determine whether the type X has an appropriate GetEnumerator method:
    o    Perform member lookup on the type X with identifier GetEnumerator and no type arguments. ...
    o    ...
    o    If the return type E of the GetEnumerator method is not a class, struct or interface type, an error is produced and no further steps are taken.
    o    Member lookup is performed on E with the identifier Current and no type arguments. ...
    o    Member lookup is performed on E with the identifier MoveNext and no type arguments. ...
    o     ...
    o    The collection type is X, the enumerator type is E, and the element type is the type of the Current property.
    Otherwise, check for an enumerable interface:
    ...

Jeff H

  • Needs a day job
  • Posts: 6131
Re: What the Duck - ForEach, IEnumerable, IEnumerator DuckTyping
« Reply #2 on: June 18, 2013, 12:37:41 PM »
Thanks kaefer,
 
I see all you smart guys refer to the specs and I need to start referring to those more, I just was looking at some MSIL and noticed it was not calling any of the methods through the interface

kaefer

  • Swamp Rat
  • Posts: 572
Re: What the Duck - ForEach, IEnumerable, IEnumerator DuckTyping
« Reply #3 on: June 18, 2013, 04:53:33 PM »
I see all you smart guys refer to the specs and I need to start referring to those more, I just was looking at some MSIL and noticed it was not calling any of the methods through the interface

What would you do if you just know that those methods are there?

Rereading of the material cited does not suggest that the types X (collection type) and E (enumerator type) need to be disjunct. Thus my Minimum Duck (without Quack):

Code - C#: [Select]
  1.     public class Duck
  2.     {
  3.         int counter = 0;
  4.         public Duck GetEnumerator() { return this; }
  5.         public int Current
  6.         {
  7.             get
  8.             {
  9.                 Console.WriteLine("*Quack*Current*Quack*");
  10.                 return counter;
  11.             }
  12.         }
  13.         public bool MoveNext()
  14.         {
  15.             Console.WriteLine("*Quack*MoveNext*Quack*");
  16.             return counter++ < 10;
  17.         }
  18.     }

Edit #2: How is this relevant to AutoCAD?

I've always wondered how the compiler could be so damn sure about the element type of a collection, when encountered in a foreach loop; F# being no different that C#. Many collections in AutoCAD's API are basically broken when accessed in a functional setting; they are missing type information enforced by implementing a generic interface. This compiler quirk explains why they are very efficient when imperative legwork is used, with attendant type safety.
« Last Edit: June 18, 2013, 05:27:20 PM by kaefer »

Jeff H

  • Needs a day job
  • Posts: 6131
Re: What the Duck - ForEach, IEnumerable, IEnumerator DuckTyping
« Reply #4 on: June 19, 2013, 01:32:20 AM »
What would you do if you just know that those methods are there?
I dunno?
 
What would you do if you just know that those methods are there?
Edit #2: How is this relevant to AutoCAD?
I dunno?