Question

I know that you cannot return anonymous types from methods but I am wondering how the Select extension method returns an anonymous type. Is it just a compiler trick?

Edit

Suppose L is a List. How does this work?

L.Select(s => new { Name = s })

The return type is IEnumerable<'a> where 'a = new {String Name}

Was it helpful?

Solution

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 
);

OTHER TIPS

Well, it's normal type inference for generic method type arguments. For instance:

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);

The same would be true if x were a list of some anonymous type, or if the inferred return type of the lambda expression were an anonymous type. Don't forget that even though you can't explicitly state the type of a variable which uses an anonymous type, it still does have a definite type, known to the compiler.

From comment: " So how would I go about implementing a similar method"

All you need here is any generic method:

public List<T> Foo<T>(T template) { // doesn't actually use "template"
    return new List<T>();  // just an example
}

then you can have:

var list = Foo(new {Bar=1});

The compiler provides the <T> via generic type inference.

A bit cheeky, but you can even do it without actaully ever creating an instance of the anon-type:

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});

Again, the is provided by the compiler via the return value of the lambda.

The return type of Select is generic, and it is inferred from the lambda provided in most situations.

For example:

List<int> list = new List<int<();

var val = list.Select(x => new {value = x, mod = x % 10});

The return value of the select is based on the anonymous type I defined, and is extrapolated from the lambda, to a delegate, to the Select function. The Select function in this case does not know about or care about the particular anonymous type, as it is a generic type from its perspective.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top