2009-05-14 6 views
1

イテレータ構文を使用してC#でイテレータ関数を記述すると、コンパイラは内部的に関数をクラスに変換します。私はこのような何か書くのであれば、:C#の参照パラメータに対応するオブジェクトフィールドの検索

IEnumerator<int> MyIterator() { 
    for (int i = 0; i < 10; i++) 
    yield return i; 
} 

呼び出すMyIteratorを()の代わりにスタック変数を使用して、私のためのプライベートフィールドを持つクラスを作成します。質問の今

:私は私の値を格納するために使用するフィールドを検索する方法を見つけたいです。その理由は、少し複雑です:

私は協力スレッドのためのイテレータ関数を使用しています。非同期操作が完了するまで関数の実行を中断するために、このような単純なコードをイテレータに書きます。

Future<string> f; 
yield return file.readLine(out f); 
string line = f.Result; 

これら3つのステートメントが実行されると、readLine関数が呼び出され、未来が 'f'フィールドに格納されます。イテレーター関数は中断され、 'f' Futureに結果が格納されるとウェイクアップして、その時点で結果を取得できます。私が行うことができるようにしたいどのような

が、これは次のとおりです。スタック変数が生きたままことを保証する方法がないので、通常の状況下では

string line; 
yield return file.readLine(out line); 

、これは、.NETで可能ではないでしょう私がそれに書き込むことができるように十分長い。

しかし、反復子関数がすべてのローカルをフィールドの中に格納することを知っているので、私は理論的にはiteratorへの参照を保持することで(それを生かしておくことで)、フィールド自体にも渡すことができるので、readLine操作が完了すると、結果をフィールドに直接格納することができます。

問題は、CLRは私にこれを行う方法を提供していないようだということです。私が「アウト」または「REF」パラメータを使用している場合

は、私は生のポインタ、参照、またはTypedReferenceにそのパラメータを変換するために安全でないC#または生MSILを使用することができます。残念ながら、フィールドにこれらの3つのタイプのいずれかを格納することは合法ではありません。コンパイラを騙しても、バイトコード検証プログラムはコードを実行させません。これは、スタック変数への参照の格納が本質的に安全ではないためです。

だから、私は何を探していることはアウト/ refのパラメータを取り、対応するフィールドを見つけるために呼び出すイテレータのフィールドを検索する関数を記述です。フィールドがあれば、イテレーターとフィールドへの参照をラッパー・タイプに保管し、ラッパーを非同期操作に関連付けます。 .NETのランタイム反射に伴うオーバーヘッドを考えると

は、私はこれが私のソースコードを前処理またはコンパイルした後、私のアセンブリを後処理のいずれかなしには不可能であると思われます。

しかし、代替ソリューションの提案をお待ちしています。 :) 何か案は?

答えて

0

の質問のすべてを理解していなかった私は最終的にここに私のニーズを満たすソリューションを見つけ、あなたは何を知っていますか - それは、LINQを必要とします。

.NETのブログ記事は、式の結果の型を知っている場合は、どの式lambdaを式<>オブジェクトに変換することができますか。

()=> this.Foo.Bar

と(「バー」の)のMemberInfoで終わるためにノードを歩くと:それはあなたがこのように式を取ることができることが判明し、ことを考えます「this.Foo」のための「this」オブジェクト。これら2つの値を指定すると、コンパイル時に指定されたフィールドまたはプロパティに直接バインドできます。プロパティの場合、MemberInfoからプロパティのGetメソッドとSetメソッドを取得し、強く型付けされたデリゲートに変換することで、プロパティを非常に効率的に読み書きできるコストを削減できます。

これは、コンパイラーの筋肉があなたのために使用され、バインディングを許可するために既存のコードを変更する必要がないため、自動リファクタリングとソースコード検索で完璧に機能します。

唯一の欠点は、構造体のフィールド/プロパティにバインドすることは非常に難しいことですが、とにかくそれが特に関連するユースケースであるとは考えません。これを解決するか、同様の問題がここにソースコードを表示することができます探して

誰でも:

http://code.google.com/p/fracture/source/browse/trunk/Squared/Util/Bind.cs

1

イテレータのフィールドをモンキーにして問題が発生しました。イテレータのシグネチャで指定したクラスのメンバーを使用する方が簡単ではないでしょうか?それを渡すか、外に出すか?基本的には、途中で単純なラッパークラスのいくつかの種類が含まれますか?

class MyWrapper { 
    public string Line {get;set;} 
} 

あなたは、単にMyWrapperオブジェクト参照を経由して、かなり安全にLineに話をすることができますか?

それは私が言うことができる最善の方法ですので、私は...、

+0

今後例では、多かれ少なかれ、あなたが記述の目的を果たします。毎回コンテナから値を取り除く必要があるので、私はそのステップをスキップして、できれば直接フィールドに書きたいと思います。 イテレータのフィールドを変更するセマンティクスは私には明らかです。イテレータのために生成されたILを見ると、あなたが正常に行う限り、ローカルを変更することは完全に安全です。 –

関連する問題