The type is actually defined by the caller, so it's in the scope of the calling function - neatly avoiding the issue of "returning" an anonymous type.
This is accomplished by generic type inference. The signature for Select is Select<Tsource, TResult>(IEnumerable<TSource>, Func<TSource, TResult>
. The IEnumerable<TSource>
is, obviously, the source collection. The Func<Tsource, TResult>
transformation function is where the compiler can use type inference to declare an anonymous type.
In other words, in order to pass a Func<Tsource, TResult>
to Select
, you - the caller - must define TResult
. Which means Select
isn't returning an anonymous type defined by it - but by you.
To emulate this, you just have to get the caller to define the type:
TResult ReturnAnonymousType<TResult>(Func<TResult> f) {
return f();
}
Console.WriteLine(ReturnAnonymousType(
() => return new { Text = "Hello World!" } // type defined here, before calling
);