Valhalla Legends Archive

Programming => General Programming => .NET Platform => Topic started by: MyndFyre on July 13, 2006, 03:53 AM

Title: Oooh, I just wrote my first C# iterator property! :D
Post by: MyndFyre on July 13, 2006, 03:53 AM
I was trying to come up with an efficient way to iterate through the MPQ patch list backwards without loading them in reverse order in my code.  This is what I came up with:

public IEnumerable<MpqArchive> Patches
        {
            get
            {
                for (int i = m_patches.Length - 1; i >= 0; i--)
                {
                    yield return m_patches[i];
                }
            }
        }


I've been having difficulty coming up with the utility for this.  I have to say I'm pretty impressed.  First I thought of a custom collection class, then I thought about overriding the GetEnumerator property of List<MpqArchive>, but that didn't pan out (nonvirtual method).  Then I thought about that, jotted it down, first compile I got it right and I was amazed at how straightfoward it was.

:D
Title: Re: Oooh, I just wrote my first C# iterator property! :D
Post by: topaz on July 13, 2006, 04:04 AM
Can't you iterate backwards with lists?
Title: Re: Oooh, I just wrote my first C# iterator property! :D
Post by: MyndFyre on July 13, 2006, 04:32 AM
If you write a custom property for it.  List<T> for instance does not have any virtual methods, so I opted out of using that because I don't like to get the "Member xxx hides inherited member xxx" warning.  However, if you did something like:


public class SpecialList<T> : List<T>
{
    public IEnumerable<T> BackwardsList
    {
        get
        {
            for (int i = Count - 1; i >= 0; i--)
            {
                yield return this[i];
            }
        }
    }
}


Then, to use the code, instead of foreach'ing the object, you foreach the property:

foreach (T item in mySpecialList.BackwardsList)
{
    // do something with the list backwards....
}


It's just a more coherent way of doing things.  You could have done it in .NET 1.x too, but you needed to implement the IEnumerable interface.
Title: Re: Oooh, I just wrote my first C# iterator property! :D
Post by: MyndFyre on July 13, 2006, 04:37 AM
I'm looking at the decompilation of it in .NET Reflector:


public IEnumerable<MpqArchive> Patches
{
      get
      {
            InterfaceData.<get_Patches>d__0 d__1 = new InterfaceData.<get_Patches>d__0(-2);
            d__1.<>4__this = this;
            return d__1;
      }
}


Then there's a hidden child subclass contained by InterfaceData (the class I added the Patches property to):

[CompilerGenerated]
private sealed class <get_Patches>d__0 : IEnumerable<MpqArchive>, IEnumerable, IEnumerator<MpqArchive>, IEnumerator, IDisposable
{
      // Methods
      [DebuggerHidden]
      public <get_Patches>d__0(int <>1__state);
      private bool MoveNext();
      [DebuggerHidden]
      IEnumerator<MpqArchive> IEnumerable<MpqArchive>.GetEnumerator();
      [DebuggerHidden]
      IEnumerator IEnumerable.GetEnumerator();
      [DebuggerHidden]
      void IEnumerator.Reset();
      void IDisposable.Dispose();

      // Properties
      MpqArchive IEnumerator<MpqArchive>.Current { [DebuggerHidden] get; }
      object IEnumerator.Current { [DebuggerHidden] get; }

      // Fields
      private int <>1__state;
      private MpqArchive <>2__current;
      public InterfaceData <>4__this;
      public int <i>5__1;
}

So that's how it works.  The compiler generates a new class that implements all of the interfaces needed for foreach. :o
Title: Re: Oooh, I just wrote my first C# iterator property! :D
Post by: Banana fanna fo fanna on July 13, 2006, 01:25 PM
Welcome to Python :)