Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 可枚举和可查询扩展方法的Lambda表达式参数_C#_Linq - Fatal编程技术网

C# 可枚举和可查询扩展方法的Lambda表达式参数

C# 可枚举和可查询扩展方法的Lambda表达式参数,c#,linq,C#,Linq,lambda表达式是一个匿名方法,它的封面下是一个委托,因此我可以这样做: delegate bool Foo(int x); Foo bar = x => x == 1; 将此委托传递给可枚举扩展方法非常有意义,因为典型的预期参数是Func,它是委托的缩写: public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<T

lambda表达式是一个匿名方法,它的封面下是一个委托,因此我可以这样做:

 delegate bool Foo(int x);

 Foo bar = x => x == 1;
将此委托传递给可枚举扩展方法非常有意义,因为典型的预期参数是Func,它是委托的缩写:

 public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);
此方法需要表达式参数,但传入lambda表达式是完全合法的。是什么机制将lambda表达式强制转换为表达式,以便可以使用它

我很熟悉可查询方法构建表达式树以供提供者解析的事实,我只是好奇这一点,这一点对我来说并不明显

更新

我对自己的无知越来越无知了。Lambda表达式不是委托,但可用于创建委托或表达式:

 Expression<Func<int, bool>> foo = c => c == 1;

我相信这与查询是如何建立在IQueryable上有关。该方法需要一个表达式树,因为它可以是结构化的,以匹配更优化的查询或更接近底层数据源的映射。因此,简单地传入Func只允许执行,而an允许观察和执行表达式树


另外,可能更接近于回答您的确切问题。

我认为这与查询如何建立在IQueryable上有关。该方法需要一个表达式树,因为它可以是结构化的,以匹配更优化的查询或更接近底层数据源的映射。因此,简单地传入Func只允许执行,而an允许观察和执行表达式树

另外,可能更接近于回答你的确切问题。

很简单,你不能。 然而,为了使IQueryable方法有用,VS2008及以上版本包含了一个聪明的编译器技巧。作为单个语句的lambda表达式可以同时分配给委托和表达式。编译器通常会提升表达式并生成一个方法

但是对于表达式的赋值,它将语句分解为它们的语法意义,并将其转换为表达式树

e、 g

这是无效的,因为func是委托。但您可以这样做::

func=expression.Compile()
它将表达式编译为func

**注意,建议的转换可能不是100%正确

他们这样做的原因是允许linqto对象基本上从其他语言映射/减少,以共享与linqto提供者相同的友好语法。因此,您可以编写一条语句,该语句的含义相同,但可以更改过滤和转换发生的位置。 GetEmployees.Wheree=>e.LastName==Smith 可以读取相同的内容,但理论上可以描述在这个框中进行过滤,或数据库中的一个实例,或解析xml文件或任何数量的各种内容

很简单,你不能。 然而,为了使IQueryable方法有用,VS2008及以上版本包含了一个聪明的编译器技巧。作为单个语句的lambda表达式可以同时分配给委托和表达式。编译器通常会提升表达式并生成一个方法

但是对于表达式的赋值,它将语句分解为它们的语法意义,并将其转换为表达式树

e、 g

这是无效的,因为func是委托。但您可以这样做::

func=expression.Compile()
它将表达式编译为func

**注意,建议的转换可能不是100%正确

他们这样做的原因是允许linqto对象基本上从其他语言映射/减少,以共享与linqto提供者相同的友好语法。因此,您可以编写一条语句,该语句的含义相同,但可以更改过滤和转换发生的位置。 GetEmployees.Wheree=>e.LastName==Smith
可以读取相同的内容,但理论上可以描述在这个框中进行过滤,或数据库中的一个实例,或解析xml文件或任何数量的各种内容

规范中对此进行了描述:

4.6表达式树类型

如果存在从lambda表达式到委托类型D的转换, 也存在到表达式树类型表达式的转换。 而lambda表达式到委托类型的转换 生成引用lambda的可执行代码的委托 表达式,转换为表达式树类型将创建 lambda表达式的表达式树表示形式。表示 树是lambda的有效内存数据表示形式 表达式并使lambda表达式的结构透明 明确的


因此,存在从lambda到兼容表达式树类型的转换,编译器将发出等效表达式树,而不是创建委托。

规范中描述了这一点:

4.6表达式树类型

如果一个conv 存在从lambda表达式到委托类型D的版本, 也存在到表达式树类型表达式的转换。 而lambda表达式到委托类型的转换 生成引用lambda的可执行代码的委托 表达式,转换为表达式树类型将创建 lambda表达式的表达式树表示形式。表示 树是lambda的有效内存数据表示形式 表达式并使lambda表达式的结构透明 明确的

因此,存在从lambda到兼容表达式树类型的转换,编译器将发出等效表达式树,而不是创建委托

Func<int,int> func = x=>x*x;
Expression<Func<int,int>> expression = x=>x*x;
private static int <B012>SomeMethod(int x){
   return x*x;
}
ParameterExpression paramX = Expression.Parameter(typeof(int));
Expression<Func<int,int>> expression = Expression.Lambda<Func<int,int>>(
     Expression.Multiply(paramX,paramX),paramX);
expression = func;
func=expression.Compile()