1

一部のカスタムオブジェクトにLINQインターフェイスを追加していますが、C#コンパイラが型推論で失敗します。ただし、生の拡張メソッドを使用して同等のクエリを記述でき、型推論が成功するため、コンパイラがクエリ式を拡張メソッド呼び出しにどのように変換しているかわかりません。

ツールまたはコンパイラフラグがあるので、コンパイラがクエリ式から何を生成しているかを確認できるので、これを理解できますか?

このコードはオープンソースプロジェクトに含まれているので、役立つ場合はソースへのリンクを提供できます。拡張メソッドの型シグネチャのわずかなバリエーションは、この型推論エラーを回避しますが、これらのバリアントには、私が求めているセマンティクスがありません。

4

3 に答える 3

4

クエリ理解コードは次のとおりです。

from f1 in e1
from f2 in e2
from f3 in e3
select f3

メソッド呼び出しコードは次のとおりです。

e1
.SelectMany(f1 => e2)
.SelectMany(f2 => e3), (f2, f3) => f3))

クエリの翻訳は次のように進行します。最初に、最初の2つのfrom句を扱います。

from f1 in e1
from f2 in e2
from f3 in e3
select f3;

これはに翻訳されます

from x in ( e1 ) . SelectMany( f1 => e2 , ( f1 , f2 ) => new { f1 , f2 } )
from f3 in e3
select f3;

ここで、「x」は透過的な識別子です。e1、e2、e3のいずれも範囲変数を消費しないため、これが透過的な識別子であるという事実は関係ありません。透過的な識別子のセマンティクスを処理するために、さらに書き直す必要はありません。

その結果は次に変換されます

( ( e1 ) . SelectMany( f1 => e2 , ( f1 , f2 ) => new { f1 , f2 } ) ) 
.SelectMany( x => e3 , ( x , f3 ) => f3 )

これらの括弧の一部を削除できます。

e1 
.SelectMany( f1 => e2 , ( f1 , f2 ) => new { f1 , f2 } ) ) 
.SelectMany( x => e3 , ( x , f3 ) => f3 )

明らかに、これは手動で行った構文変換とはかなり異なります。

e1
.SelectMany(f1 => e2)
.SelectMany(f2 => e3), (f2, f3) => f3))

e1、e2、e3を上記の実際の構文変換に代入すると、結果の式は型推論に合格しますか?

そうでない場合、問題は「なぜそうではないのか」です。コードに問題があるか、型推論器に問題があります。タイプ推論機能に問題がある場合は、お知らせください。

もしそうなら、質問は「構文変換パスの何が問題になっているのか」です。構文変換パスに問題がある場合は、もう一度お知らせください。

ありがとう!

于 2009-12-07T16:56:00.823 に答える
1

Reflectorを使用して、最適化をオフにしてコードを表示できます。

于 2009-12-07T01:05:48.160 に答える
0

エリックの概要から、これらのクエリがどのように処理されるかを理解することができました。問題は、クエリの変換が気に入らない方法で、操作対象の型を制限しようとしていたことでした。

from x in Foo.Bar()
...

Foo.Bar()はFutureを返すはずであり、xもFuture型であるはずでしたが、これはクエリ変換では機能しません。これに対処するために、間接参照の別のレイヤーを追加しました。基本的には、先物をラップするAsync <T>タイプです。これは、先物でのみインスタンス化できます。

public sealed class Async<T> { internal T value; }
public static class Async
{
   public static Async<Future<T>> Begin<T>(Future<T> future) { ... }
}

次に、非同期値に対してクエリ計算を記述できるため、式は次のようになります。

from x in Async.Begin(Foo.Bar())
...

ここで、xはfutureタイプであり、futuresとpromiseを任意に強制または延期できます。

皆さんの提案に感謝します。ただし、MSの誰かがこれを読んでいる場合に備えて、VisualStudioに組み込まれているクエリ式トランスレーターがあれば便利です。;-)

于 2009-12-10T03:09:54.350 に答える