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
Can't you iterate backwards with lists?
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.
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
Welcome to Python :)