Author | Message | Time |
---|---|---|
Myndfyr | 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: [code] public IEnumerable<MpqArchive> Patches { get { for (int i = m_patches.Length - 1; i >= 0; i--) { yield return m_patches[i]; } } } [/code] 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 | July 13, 2006, 8:53 AM |
Topaz | Can't you iterate backwards with lists? | July 13, 2006, 9:04 AM |
Myndfyr | 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: [code] public class SpecialList<T> : List<T> { public IEnumerable<T> BackwardsList { get { for (int i = Count - 1; i >= 0; i--) { yield return this[i]; } } } } [/code] Then, to use the code, instead of foreach'ing the object, you foreach the property: [code] foreach (T item in mySpecialList.BackwardsList) { // do something with the list backwards.... } [/code] 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. | July 13, 2006, 9:32 AM |
Myndfyr | I'm looking at the decompilation of it in .NET Reflector: [code] 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; } } [/code] Then there's a hidden child subclass contained by InterfaceData (the class I added the Patches property to): [code] [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; } [/code] So that's how it works. The compiler generates a new class that implements all of the interfaces needed for foreach. :o | July 13, 2006, 9:37 AM |
St0rm.iD | Welcome to Python :) | July 13, 2006, 6:25 PM |