此代码来自stackoverflow成员mr.Lukazoid。我想知道这是怎么回事。我觉得有点奇怪,你怎么这样调用一个方法。TResult
的作用是什么?
public static string[] Foo<T, TResult>(Expression<Func<T, TResult>> func)
{
return typeof(TResult).GetProperties().Select(pi => pi.Name).ToArray();
}
Foo((Person x) => new { x.LastName, x.DateOfBirth });
谢谢你。
解决方案是尝试以类型化的方式从类中获取属性名称的子集。
有几种方法可以做到这一点,但是作者选择了一种非常狡猾的方法,利用泛型推理来节省委托/表达式调用的成本。这就是为什么func
从来不被称为…
为了实现这一点,作者依赖于以下事实:泛型类型参数是静态编译的,并且可以通过方法的参数推断。
本例中通用参数为<T, TResult>
。T
从(Person x)
(lambda的参数侧)推导出,TResult
从new { x.LastName, x.DateOfBirth }
(lambda的主体)推导出。
由于泛型是编译时语言特性,该方法可以访问typeof(TResult)
的自反属性…不需要调用/执行表达式。
看起来很棒,工作完成了。然而,同样的事情也可以用Func
委托来完成,而且成本要低得多
public static string[] Foo2<T,TResult>(Func<T, TResult> _)
=> typeof(TResult).GetProperties().Select(pi => pi.Name).ToArray();
StdDev | |||
---|---|---|---|
Expression | 2,852.9 ns | 47.68 ns | 44.60 ns |
Func | 122.7 ns | 2.47 ns | 2.31 ns |
Func<T, TResult>
表示这样声明的函数:
TResult functionName(T parameter)
.
也就是说,TResult
是函数返回值的类型。上述类型(本例中为T
)是传递给函数的参数类型。
在这段代码中,Foo((Person x) => new { x.LastName, x.DateOfBirth });
,方法Foo
被传递给签名为Func<Person, AnonymousTypeContainingNameAndBirth>
的匿名方法
也就是说,TResult
就是AnonymousTypeContainingNameAndBirth
。
由于
Foo
方法期望Expression<Func<T, TResult>>
,该匿名方法实际上在传递给Foo之前转换为表达式,但这是另一个讨论的故事。
您提供的代码返回string[] { "LastName", "DateOfBirth" }
。