Methods and Anonymous Types

I know that you cannot return anonymous types from methods, but I wonder how the Select method returns an anonymous type. Is this just a trick compiler?

Edit

Suppose L is a list. How it works?

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

Return type: IEnumerable <'a> where' a = new {String Name}

+4
source share
4 answers

The type is actually defined by the caller, so it falls within the scope of the calling function - carefully avoiding the problem of returning an anonymous type.

This is achieved by deducing the type of the general type. The signature for Select is Select<Tsource, TResult>(IEnumerable<TSource>, Func<TSource, TResult> . IEnumerable<TSource> is obviously the original collection. The conversion function Func<Tsource, TResult> is where the compiler can use type inference for anonymous type declaration.

In other words, to pass Func<Tsource, TResult> to Select , you - the caller - must define TResult . This means that Select does not return the anonymous type defined by it, but by you.

To emulate this, you just need 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 ); 
+8
source

Well, this is the usual type inference for arguments like the generic method. 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 was a list of some anonymous type, or if the return type of the lambda expression was anonymous. Remember that although you cannot explicitly specify the type of a variable that uses an anonymous type, it still has a specific type known to the compiler.

+8
source

From the comment: "So, how do I go about implementing a similar method"

All you need is any general method:

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

then you can:

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

The compiler provides <T> through a generic output type.

A little sassy, ​​but you can even do it without actaully ever creating an anon-type instance:

 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, it is provided by the compiler via the lambda return value.

+5
source

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

For instance:

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

The return value of the selection is based on a specific anonymous type I and is extrapolated from lambda, to the delegate, to the selection function. The Select function in this case does not know about a specific anonymous type and does not care about it, since this is a general type from its point of view.

+1
source

All Articles