メソッドから匿名型を返すことができないことは知っていますが、Select 拡張メソッドがどのように匿名型を返すのか疑問に思っています。それは単なるコンパイラのトリックですか?
編集
L がリストであるとします。これはどのように作動しますか?
L.Select(s => new { Name = s })
戻り値の型は IEnumerable<'a> で、'a = new {String Name}
メソッドから匿名型を返すことができないことは知っていますが、Select 拡張メソッドがどのように匿名型を返すのか疑問に思っています。それは単なるコンパイラのトリックですか?
編集
L がリストであるとします。これはどのように作動しますか?
L.Select(s => new { Name = s })
戻り値の型は IEnumerable<'a> で、'a = new {String Name}
まあ、それはジェネリックメソッド型引数の通常の型推論です。例えば:
List<string> x = new List<string>();
// The compiler converts this:
x.Select(y => y.Length);
// Into this, using type inference:
Enumerable.Select<string, int>(x, y => y.Length);
x
匿名型のリストである場合、またはラムダ式の推定される戻り型が匿名型である場合も、同じことが当てはまります。匿名型を使用する変数の型を明示的に指定することはできませんが、コンパイラーに認識されている明確な型があることを忘れないでください。
型は実際には callerによって定義されるため、呼び出し元の関数のスコープ内にあり、匿名型を「返す」問題をうまく回避できます。
これは、ジェネリック型の推論によって実現されます。Selectの署名はSelect<Tsource, TResult>(IEnumerable<TSource>, Func<TSource, TResult>
. はIEnumerable<TSource>
、明らかに、ソース コレクションです。変換関数は、Func<Tsource, TResult>
コンパイラが型推論を使用して匿名型を宣言できる場所です。
Func<Tsource, TResult>
つまり、 aを toに渡すにはSelect
、呼び出し元であるあなたが を定義する必要がありますTResult
。つまりSelect
、それによって定義された匿名型を返すのではなく、あなたによって.
これをエミュレートするには、呼び出し元に型を定義させるだけです。
TResult ReturnAnonymousType<TResult>(Func<TResult> f) {
return f();
}
Console.WriteLine(ReturnAnonymousType(
() => return new { Text = "Hello World!" } // type defined here, before calling
);
コメントから:「では、どうすれば同様の方法を実装できますか」
ここで必要なのは、ジェネリック メソッドだけです。
public List<T> Foo<T>(T template) { // doesn't actually use "template"
return new List<T>(); // just an example
}
次に、次のことができます。
var list = Foo(new {Bar=1});
コンパイラは<T>
via ジェネリック型推論を提供します。
少し生意気ですが、アノン型のインスタンスを実際に作成しなくても実行できます。
public List<T> Foo<T>(Func<T> func) { // doesn't actually use "func"
return new List<T>(); // just an example
}
var list = Foo(() => new {Bar = 1});
繰り返しますが、ラムダの戻り値を介してコンパイラによって提供されます。
Selectの戻り型は一般的であり、ほとんどの状況で提供されるラムダから推測されます。
例えば:
List<int> list = new List<int<();
var val = list.Select(x => new {value = x, mod = x % 10});
selectの戻り値は、私が定義した匿名タイプに基づいており、ラムダからデリゲート、Select関数に外挿されます。この場合のSelect関数は、特定の匿名型を認識または認識しません。これは、その観点からはジェネリック型であるためです。