为了确保我理解有人可以确认 lambda 表达式使用反射吗?
3 回答
他们可以,但不是必须的。如果将它们编译为委托,则不需要反射:但是,如果将它们编译为 ab 表达式树,则表达式树绝对是基于反射的。表达式树的某些部分可以直接从元数据标记 (ldtoken) 组装 - 特别是方法(包括运算符和 getter/setter 以及类型) - 但其他部分不能。这包括属性(PropertyInfo
不能通过令牌加载) - 因此编译的 lambda 的 IL 可以显式包含GetProperty
等。
但是无论它是如何加载的(令牌或反射),表达式树都是用反射(MemberInfo
等)表示的。这可能稍后会被编译,或者可能由提供者分析。
为了提高性能,表达式编译器可能会缓存部分或全部表达式树,并重新使用它。
编译器将 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 在运行时具有特定的已知值,因此查询提供程序需要将其从. 它可能决定这样做的一种方法是通过反思。Id
user
user
lambda 表达式只是用于创建委托的编译器语法糖。这里没有使用反射。