When you write an iterator function in C#, using yield syntax, the compiler internally translates your function into a class. So, if I write something like this:
IEnumerator<int> MyIterator () {
for (int i = 0; i < 10; i++)
yield return i;
}
Invoking MyIterator() constructs a class with a private field for i, instead of using a stack variable.
Now for the question: I want to find a way to locate the field used to store i's value. The reason is a little involved:
I'm using iterator functions for cooperative threading. I write simple code like this in an iterator, in order to suspend execution of a function until an asynchronous operation has completed.
Future<string> f;
yield return file.readLine(out f);
string line = f.Result;
When those three statements are executed, the readLine function is invoked and stores a future into the 'f' field. The iterator function is then suspended, and wakes back up when the 'f' Future has had a result stored into it, at which point I can retrieve the result.
What I want to be able to do, is this:
string line;
yield return file.readLine(out line);
Under normal circumstances, this wouldn't be possible in .NET, since there is no way to guarantee that a stack variable stays alive long enough for me to be able to write to it.
However, knowing that iterator functions store all their locals inside of fields, I can theoretically do this by holding a reference to the iterator (keeping it alive) and to the field itself, so that when the readLine operation completes, I can store the result directly into the field.
The problem is that the CLR doesn't seem to give me a way to do this.
If I have an 'out' or 'ref' parameter, I can use unsafe C# or raw MSIL to convert that parameter into a raw pointer, a reference, or a TypedReference. Unfortunately, it's not legal to store any of those three types in a field - even if you trick the compiler into letting you do it, the bytecode verifier won't let you execute the code. This is most likely because storing a reference to a stack variable would be inherently unsafe.
So what I'm looking to do is write a function that takes an out/ref parameter, and searches the calling iterator's fields to find a corresponding field. Once it has the field, it stores a reference to the iterator and field into a wrapper type and associates the wrapper with an asynchronous operation.
Given the overhead involved in runtime reflection in .NET, I suspect that this isn't possible without either preprocessing my source code or post-processing my assemblies after compilation.
However, I'd love to hear some suggestions for alternate solutions. :) Any ideas?