C# LINQ查询表达式转换器?

C# LINQ查询表达式转换器?,c#,linq,query-expressions,C#,Linq,Query Expressions,我正在向一些自定义对象添加LINQ接口,但是。但是,我可以使用原始扩展方法编写等效查询,并且类型推断成功,因此我不确定编译器如何将查询表达式转换为扩展方法调用 是否有一个工具或编译器标志,以便我可以查看编译器从查询表达式生成的内容,从而解决这个问题 这段代码在一个开源项目中,所以如果有帮助的话,我可以提供到源代码的链接。扩展方法的类型签名的细微变化可以避免这种类型推断错误,但这些变体没有我想要的语义。您可以在关闭优化的情况下使用和查看代码。您可以在关闭优化的情况下使用和查看代码。您的查询理解代码

我正在向一些自定义对象添加LINQ接口,但是。但是,我可以使用原始扩展方法编写等效查询,并且类型推断成功,因此我不确定编译器如何将查询表达式转换为扩展方法调用

是否有一个工具或编译器标志,以便我可以查看编译器从查询表达式生成的内容,从而解决这个问题


这段代码在一个开源项目中,所以如果有帮助的话,我可以提供到源代码的链接。扩展方法的类型签名的细微变化可以避免这种类型推断错误,但这些变体没有我想要的语义。

您可以在关闭优化的情况下使用和查看代码。

您可以在关闭优化的情况下使用和查看代码。

您的查询理解代码是:

from f1 in e1
from f2 in e2
from f3 in e3
select f3
您的方法调用代码是:

e1
.SelectMany(f1 => e2)
.SelectMany(f2 => e3), (f2, f3) => f3))
查询转换过程如下所示。首先,我们处理条款中的前两个:

from f1 in e1
from f2 in e2
from f3 in e3
select f3;
这被翻译成

from x in ( e1 ) . SelectMany( f1 => e2 , ( f1 , f2 ) => new { f1 , f2 } )
from f3 in e3
select f3;
其中“x”是一个透明标识符。由于e1、e2或e3都不使用任何范围变量,因此这是一个透明标识符这一事实无关紧要;处理透明标识符语义不需要进一步重写

然后将该结果转换为

( ( e1 ) . SelectMany( f1 => e2 , ( f1 , f2 ) => new { f1 , f2 } ) ) 
.SelectMany( x => e3 , ( x , f3 ) => f3 )
我们可以去掉一些括号:

e1 
.SelectMany( f1 => e2 , ( f1 , f2 ) => new { f1 , f2 } ) ) 
.SelectMany( x => e3 , ( x , f3 ) => f3 )
显然,这与您手动完成的语法转换有很大不同,回想起来,它是

e1
.SelectMany(f1 => e2)
.SelectMany(f2 => e3), (f2, f3) => f3))
如果将e1、e2、e3替换为上面的实际语法转换,则得到的表达式是否通过类型推断

如果没有,那么问题是“为什么不?”要么代码有问题,要么类型推断器有问题。如果类型推断器有问题,请告诉我

如果是这样,那么问题是“语法转换过程有什么问题?”?如果语法转换过程中出现问题,请再次通知我


谢谢

您的查询理解代码是:

from f1 in e1
from f2 in e2
from f3 in e3
select f3
您的方法调用代码是:

e1
.SelectMany(f1 => e2)
.SelectMany(f2 => e3), (f2, f3) => f3))
查询转换过程如下所示。首先,我们处理条款中的前两个:

from f1 in e1
from f2 in e2
from f3 in e3
select f3;
这被翻译成

from x in ( e1 ) . SelectMany( f1 => e2 , ( f1 , f2 ) => new { f1 , f2 } )
from f3 in e3
select f3;
其中“x”是一个透明标识符。由于e1、e2或e3都不使用任何范围变量,因此这是一个透明标识符这一事实无关紧要;处理透明标识符语义不需要进一步重写

然后将该结果转换为

( ( e1 ) . SelectMany( f1 => e2 , ( f1 , f2 ) => new { f1 , f2 } ) ) 
.SelectMany( x => e3 , ( x , f3 ) => f3 )
我们可以去掉一些括号:

e1 
.SelectMany( f1 => e2 , ( f1 , f2 ) => new { f1 , f2 } ) ) 
.SelectMany( x => e3 , ( x , f3 ) => f3 )
显然,这与您手动完成的语法转换有很大不同,回想起来,它是

e1
.SelectMany(f1 => e2)
.SelectMany(f2 => e3), (f2, f3) => f3))
如果将e1、e2、e3替换为上面的实际语法转换,则得到的表达式是否通过类型推断

如果没有,那么问题是“为什么不?”要么代码有问题,要么类型推断器有问题。如果类型推断器有问题,请告诉我

如果是这样,那么问题是“语法转换过程有什么问题?”?如果语法转换过程中出现问题,请再次通知我


谢谢

Eric的概述让我了解了这些查询是如何处理的。问题是我试图以查询转换不喜欢的方式约束正在操作的类型

from x in Foo.Bar()
...
Bar()应该返回Future,x也应该是Future类型,但这不适用于查询转换。我通过添加另一层间接寻址来解决这个问题,基本上是将futures包装在一个异步类型中,该类型只能用futures实例化,即

public sealed class Async<T> { internal T value; }
public static class Async
{
   public static Async<Future<T>> Begin<T>(Future<T> future) { ... }
}
其中x现在是future类型,我可以任意强制或延迟期货和承诺


谢谢大家的建议。不过,在Visual Studio中内置一个查询表达式转换器会很好,以防MS的任何人都在阅读此文档。;-)

Eric的概述让我了解了这些查询是如何处理的。问题是我试图以查询转换不喜欢的方式约束正在操作的类型

from x in Foo.Bar()
...
Bar()应该返回Future,x也应该是Future类型,但这不适用于查询转换。我通过添加另一层间接寻址来解决这个问题,基本上是将futures包装在一个异步类型中,该类型只能用futures实例化,即

public sealed class Async<T> { internal T value; }
public static class Async
{
   public static Async<Future<T>> Begin<T>(Future<T> future) { ... }
}
其中x现在是future类型,我可以任意强制或延迟期货和承诺


谢谢大家的建议。不过,在Visual Studio中内置一个查询表达式转换器会很好,以防MS的任何人都在阅读此文档。;-)

不,正如我说的,查询表达式的代码没有编译,所以我没有什么要检查的。我正在寻找一些工具/技术,使用等效的扩展方法将查询表达式的源代码转换为源代码,这样我就可以了解查询表达式无法编译的原因。你能发布代码吗?也许如果我看一下它,我可以帮助你弄清楚发生了什么。带扩展方法的核心类,选择在第427行及以后定义的许多:Tests,请参阅第93行方法“testLinqSuccess”,了解我描述的错误:多一点背景:这些是使用未来的异步计算。我的第一个版本的行为类似于错误monad,如果先前的异常失败,则所有后续的未来都会失败,但这不是所需的语义。我很感谢您的见解。不,正如我所说的,查询表达式的代码没有编译,所以我没有什么要检查的。我正在寻找一些工具/技术,使用等效的扩展方法将查询表达式的源代码转换为源代码,这样我就可以了解查询表达式无法编译的原因。你能发布代码吗?也许如果我看一下它,我可以帮你弄清楚到底发生了什么