IEnumerator Cloning
A word of warning. I'm about to show you something you should probably never do. I really enjoy using LINQ in C#. Much of it is founded on IQueryable and IEnumerable types. One time I was deep diving into the inner workings of enumerable types to try to find a simpler syntax to manage some complex processes.Thanks to some information from Jon Skeet, I know that the C# enumerators are compiled into basic state machines behind the scenes. I was attempting this to see how well Enumerators could be used for branching in a game's AI decision tree. It turns out that it quickly makes it hard to manage . But, I would still like to show you a little about it.If you were to make an enumerable that never ends, such as calculating prime numbers, it is possible to take a snapshot and continue later. Every time you hit yield return inside of an IEnumerator
public static class EnumeratorCloner
{
public static T Clone<T>(T source) where T : class, IEnumerator
{
var sourceType = source.GetType().UnderlyingSystemType;
var sourceTypeConstructor = sourceType.GetConstructor(new Type[] { typeof(Int32) });
var newInstance = sourceTypeConstructor.Invoke(new object[] { -2 }) as T;
var nonPublicFields = source.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
var publicFields = source.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance);
foreach (var field in nonPublicFields)
{
var value = field.GetValue(source);
field.SetValue(newInstance, value);
}
foreach (var field in publicFields)
{
var value = field.GetValue(source);
field.SetValue(newInstance, value);
}
return newInstance;
}
}