3

为了确保我理解有人可以确认 lambda 表达式使用反射吗?

4

3 回答 3

4

他们可以,但不是必须的。如果将它们编译为委托,则不需要反射:但是,如果将它们编译为 ab 表达式树,则表达式树绝对是基于反射的。表达式树的某些部分可以直接从元数据标记 (ldtoken) 组装 - 特别是方法(包括运算符和 getter/setter 以及类型) - 但其他部分不能。这包括属性(PropertyInfo不能通过令牌加载) - 因此编译的 lambda 的 IL 可以显式包含GetProperty等。

但是无论它是如何加载的(令牌或反射),表达式树都是用反射(MemberInfo等)表示的。这可能稍后会被编译,或者可能由提供者分析。

为了提高性能,表达式编译器可能会缓存部分或全部表达式树,并重新使用它。

于 2012-11-20T16:04:09.587 回答
1

编译器将 Lambda 表达式转换为匿名函数或表达式树。由于反射只能在运行时执行,因此在考虑编译器在任何一种情况下对它们做了什么时,它根本不会出现。

在运行时,lambda 表达式可能会导致在非常特定的情况下使用反射:

对于匿名函数:如果您编写了一个显式反映某事物的匿名函数,那么 lambda 将在调用时执行该反射。这当然与您从“正确”方法中进行反射一样。

对于表达式树(即Expression<TDelegate>some的类型值TDelegate):在运行时使用它们IQueryable可能会导致查询提供程序使用反射。例如,假设您这样做:

var user = new User { Id = 42 };
var posts = Queryable.Posts.Where(p => p.UserId == user.Id);

何时posts将要具体化,查询提供者看到它必须找到那些与变量的UserId相等的帖子。由于该 id 在运行时具有特定的已知值,因此查询提供程序需要将其从. 它可能决定这样做的一种方法是通过反思。Iduseruser

于 2012-11-20T15:07:59.597 回答
-1

lambda 表达式只是用于创建委托的编译器语法糖。这里没有使用反射。

于 2012-11-20T15:06:33.520 回答