3

私はC#を深く読んでいて、親愛なる作者によって説明された2フェーズ型推論規則で混乱しました。

コードを考えてみましょう:

static void PrintConvertedValue<TInput,TOutput> (TInput input, Converter<TInput,TOutput> converter) 
{ Console.WriteLine(converter(input)); } 
... 
PrintConvertedValue("I'm a string", x => x.Length);

その後、彼は2相推論アルゴリズムを使用した推論のプロセスを説明します。

1.フェーズ1が始まります。

2.最初のパラメーターはTInput型であり、最初の引数はstring型です。文字列からTInputへの暗黙の変換が必要であると推測します。

3. 2番目のパラメーターはConverter型であり、2番目の引数は暗黙的に型指定されたラムダ式です。推論は実行されません—十分な情報がありません。

4.フェーズ2が始まります。

5.TInput固定されていない型パラメータに依存しないため、文字列に固定されます。

6. 2番目の引数の入力タイプは固定されていますが、出力タイプは固定されていません。それをと見なし(string x) => x.Length、戻り型をintとして推測することができます。したがって、暗黙の変換はintから。に行われる必要がありますTOutput

7.フェーズ2が繰り返されます。

8.TOutput固定されていないものには依存しないため、intに固定されます。9固定されていない型パラメーターがないため、推論は成功します

私はステップ2とステップ5と非常に混同しています。ステップ2では、コンパイラーはどのようにしてそのような推論を行うことができますか?つまり、世界の転換はどのように現場にもたらされるのでしょうか?変換は、BTWタイプのパラメーターやタイプではなく、BTWタイプで行われます。

そしてステップ5は私を完全に理解しませんでした、タイプパラメータが他のタイプパラメータに依存する可能性がある簡単な例を誰かが私に提示できますか?作者が何を意味しようとしているのか説明してください。

私はあえてC#仕様に潜入しましたが、私のようなサルではなく、非常によく似たインテリジェントな人々のためにインテリジェントな人々がそれを作ったようです:)

4

1 に答える 1

4

値に対して変換が行われ、型のパラメーターの引数として文字列値を使用してメソッドを呼び出すことができるという事実は、からへTInputの変換が必要であることを意味します。であると推測された場合、を必要とするメソッドを呼び出しますが、-を指定すると、明らかに無効になります。stringTInputTInputintintstring

より簡単な例として、次のように変更するだけであることに注意してください。

void Foo<T>(T input) { }

で呼び出されます:

Foo("Hello");

呼び出しを有効にするには、からstringへの変換が必要です。に情報がないため、これは単純にであると推測されます。TTTstring

もう少し複雑な例では、次のようになります。

public void Bar<T>(T x, T y) {}

Foo("Hello", new object());

ここでは、次のことを推測します。

  • stringからへの変換が必要ですT
  • objectからへの変換が必要ですT

...だから私たちはそれがであると推測しTますobject

タイプパラメータの依存関係については、C#5仕様のセクション7.5.2.5から:

ある引数に対して、タイプTkのEkがタイプTkの入力タイプEkで発生し、XiがタイプTkの出力タイプEkで発生する場合、非固定型変数Xiは非固定型変数Xjに直接依存します。

XjがXiに直接依存する場合、またはXiがXkに直接依存し、XkがXjに依存する場合、XjはXiに依存します。したがって、「依存する」は、「直接依存する」の推移的ではあるが反射的ではない閉鎖です。

したがって、たとえば:

public void Foo<T1, T2>(T1 value, Func<T1, T2> func)

と:

Foo("foo", x => x.Length);

T2これはに依存します-T1一度推測するとT1、推測することができT2ます。

于 2013-01-15T18:38:24.490 に答える