Rod*_*man 4 c# extension-methods anonymous-methods anonymous-types
我知道你不能从方法中返回匿名类型,但我想知道Select扩展方法如何返回匿名类型.它只是一个编译技巧吗?
编辑
假设L是一个列表.这是如何运作的?
L.Select(s => new { Name = s })
Run Code Online (Sandbox Code Playgroud)
返回类型是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);
Run Code Online (Sandbox Code Playgroud)
如果x
是某个匿名类型的列表,或者lambda表达式的推断返回类型是匿名类型,则情况也是如此.不要忘记即使你不能明确说明使用匿名类型的变量的类型,它仍然有一个确定的类型,编译器已知.
该类型实际上是由调用者定义的,因此它在调用函数的范围内 - 整齐地避免了"返回"匿名类型的问题.
这是通过通用类型推断实现的.Select的签名是Select<Tsource, TResult>(IEnumerable<TSource>, Func<TSource, TResult>
.的IEnumerable<TSource>
是,很明显,源集合.该Func<Tsource, TResult>
转换函数是在编译器可以使用类型推理来声明匿名类型.
换句话说,为了传递Func<Tsource, TResult>
给Select
你,你 - 调用者 - 必须定义TResult
.这意味着Select
不会返回由它定义的匿名类型 - 而是由您自己返回.
要模拟这个,你只需让调用者来定义类型:
TResult ReturnAnonymousType<TResult>(Func<TResult> f) {
return f();
}
Console.WriteLine(ReturnAnonymousType(
() => return new { Text = "Hello World!" } // type defined here, before calling
);
Run Code Online (Sandbox Code Playgroud)
来自评论:"那么我将如何实施类似的方法"
这里你需要的是任何通用方法:
public List<T> Foo<T>(T template) { // doesn't actually use "template"
return new List<T>(); // just an example
}
Run Code Online (Sandbox Code Playgroud)
然后你可以:
var list = Foo(new {Bar=1});
Run Code Online (Sandbox Code Playgroud)
编译器提供<T>
via泛型类型推断.
有点厚脸皮,但你甚至可以毫不费力地创建一个anon类型的实例:
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});
Run Code Online (Sandbox Code Playgroud)
同样,编译器通过lambda的返回值提供.
归档时间: |
|
查看次数: |
4404 次 |
最近记录: |