Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/332.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#表达式内部结构_C#_Expression Trees - Fatal编程技术网

C#表达式内部结构

C#表达式内部结构,c#,expression-trees,C#,Expression Trees,我在努力理解表达是如何在课堂上起作用的 一个简单的例子: Expression<Func<string, bool>> exp = p => p.Contains("x"); 是微软魔术吗?我没有找到任何超调转换器或其他东西,谁调用了参数方法?他们是否在编译器中编写了一些特殊代码来编译Expression类而不是任何其他“标准”类?是的,您可以称之为magic,因为编译器会在后台为您做很多提升。让我们看看最简单的程序会发生什么。我刚刚创建了一个

我在努力理解表达是如何在课堂上起作用的

一个简单的例子:

Expression<Func<string, bool>> exp = p => p.Contains("x");

是微软魔术吗?我没有找到任何超调转换器或其他东西,谁调用了参数方法?他们是否在编译器中编写了一些特殊代码来编译Expression类而不是任何其他“标准”类?

是的,您可以称之为magic,因为编译器会在后台为您做很多提升。让我们看看最简单的程序会发生什么。我刚刚创建了一个控制台应用程序并添加了您的代码

internal class Program {
    private static void Main(string[] args) {
        Expression<Func<string, bool>> exp = p => p.Contains("x");
    }
}
内部类程序{
私有静态void Main(字符串[]args){
表达式exp=p=>p.Contains(“x”);
}
}
我编译了它并查看了IL代码。(如果您愿意,可以跳过此部分)

IL_0000:ldtoken[mscorlib/*23000001*/]System.String/*01000021*/
IL_0005:调用类[mscorlib/*23000001*/]System.Type/*01000014*/[mscorlib/*23000001*/]System.Type/*01000014*/::GetTypeFromHandle(值类型[mscorlib/*23000001*/]System.RuntimeTypeHandle/*01000022*/)/*0A000014*/
IL_000a:ldstr“p”
IL_000f:调用类[System.Core/*23000002*/]System.Linq.Expressions.ParameterExpression/*0100001D*/[System.Core/*23000002*/]System.Linq.Expressions.Expression/*0100002D*/::参数(类[mscorlib/*23000001*/]System.Type/*01000014*/,字符串)/*0A000040*/
IL_0014:stloc.0//V_0
IL_0015:ldloc.0//V_0
IL_0016:ldtoken方法实例bool[mscorlib/*23000001*/]System.String/*01000021*/::Contains(String)/*0A000041*/
IL_001b:调用类[mscorlib/*23000001*/]System.Reflection.MethodBase/*0100002E*/[mscorlib/*23000001*/]System.Reflection.MethodBase/*0100002E*/::GetMethodFromHandle(值类型[mscorlib/*23000001*/]System.RuntimeMethodHandle/*0100002F*/)/*0A000042*/
IL_0020:castclass[mscorlib/*23000001*/]System.Reflection.MethodInfo/*01000017*/
IL_0025:ldc.i4.1
IL_0026:newarr[System.Core/*23000002*/]System.Linq.Expressions.Expression/*0100002D*/
IL_002b:dup
IL_002c:ldc.i4.0
IL_002d:ldstr“x”
IL_0032:ldtoken[mscorlib/*23000001*/]System.String/*01000021*/
IL_0037:调用类[mscorlib/*23000001*/]System.Type/*01000014*/[mscorlib/*23000001*/]System.Type/*01000014*/::GetTypeFromHandle(值类型[mscorlib/*23000001*/]System.RuntimeTypeHandle/*01000022*/)/*0A000014*/
IL_003c:调用类[System.Core/*23000002*/]System.Linq.Expressions.ConstantExpression/*01000030*/[System.Core/*23000002*/]System.Linq.Expressions.Expression/*0100002D*/::常量(对象,类[mscorlib/*23000001*/]System.Type/*01000014*/)/*0A000043*/
IL_0041:stelem.ref
IL_0042:调用类[System.Core/*23000002*/]System.Linq.Expressions.MethodCallExpression/*01000031*/[System.Core/*23000002*/]System.Linq.Expressions.Expression/*0100002D*/::调用(类[System.Core/*23000002*/]System.Linq.Expressions.Expression/*0100002D*/,类[mscorlib/*23000001*/]System.Reflection.MethodInfo/*01000017*/,类[System.Core/*23000002*/]System.Linq.Expressions.Expression/*0100002D*/[])/*0A000044*/
IL_0047:ldc.i4.1
IL_0048:newarr[System.Core/*23000002*/]System.Linq.Expressions.ParameterExpression/*0100001D*/
IL_004d:dup
IL_004e:ldc.i4.0
IL_004f:ldloc.0//V_0
IL_0050:stelem.ref
IL_0051:调用类[System.Core/*23000002*/]System.Linq.Expressions.Expression`1/*01000032*/*/>[System.Core/*23000002*/]System.Linq.Expressions.Expression/*0100002D*/::Lambda(class[System.Core/*23000002*/]System.Linq.Expressions.Expression/*0100002D*/,class[System.Core/*23000002*/]System.Linq.Expressions.ParameterExpression/*0100001D*/[])/*2B00002*/
IL_0056:流行音乐
这个IL代码大致翻译为

// Define Expresin parameter p
var parameterExpression = Expression.Parameter(typeof (string), "p");
// Gets method handler for string.Contains method
// Plase note that __methodref can not be used in c# butit is valid in il code
var methodInfo = (MethodInfo) MethodBase.GetMethodFromHandle(__methodref (string.Contains));
// Constant string x added as paramter
var constantXString = new Expression[] {Expression.Constant("x", typeof (string))};
// Call given method on the the given parameter and make it into a lambda expression
Expression.Lambda<Func<string, bool>>(Expression.Call(parameterExpression, methodInfo, constantXString), parameterExpression);
//定义Expresin参数p
var parameterExpression=Expression.Parameter(typeof(string),“p”);
//获取string.Contains方法的方法处理程序
//请注意,methodref不能在c中使用,但它在il代码中有效
var methodInfo=(methodInfo)MethodBase.GetMethodFromHandle(uuMethodRef(string.Contains));
//常量字符串x添加为参数
var constantTXString=新表达式[]{Expression.Constant(“x”,typeof(string))};
//对给定参数调用给定的方法,并将其转换为lambda表达式
Lambda(Expression.Call(parameterExpression、methodInfo、ConstantTXString)、parameterExpression);

这是代码的第一行,您可以看到正在调用
公共静态参数expression Parameter(Type Type,string name)

NB。我已经编写了一个函数,它接受一个表达式树并生成一个字符串。@ZevSpitz NB您也可以。让我看看it@ZevSpitz很整洁!我喜欢
IL_0000: ldtoken      [mscorlib/*23000001*/]System.String/*01000021*/
IL_0005: call         class [mscorlib/*23000001*/]System.Type/*01000014*/ [mscorlib/*23000001*/]System.Type/*01000014*/::GetTypeFromHandle(valuetype [mscorlib/*23000001*/]System.RuntimeTypeHandle/*01000022*/)/*0A000014*/
IL_000a: ldstr        "p"
IL_000f: call         class [System.Core/*23000002*/]System.Linq.Expressions.ParameterExpression/*0100001D*/ [System.Core/*23000002*/]System.Linq.Expressions.Expression/*0100002D*/::Parameter(class [mscorlib/*23000001*/]System.Type/*01000014*/, string)/*0A000040*/
IL_0014: stloc.0      // V_0
IL_0015: ldloc.0      // V_0
IL_0016: ldtoken      method instance bool [mscorlib/*23000001*/]System.String/*01000021*/::Contains(string)/*0A000041*/
IL_001b: call         class [mscorlib/*23000001*/]System.Reflection.MethodBase/*0100002E*/ [mscorlib/*23000001*/]System.Reflection.MethodBase/*0100002E*/::GetMethodFromHandle(valuetype [mscorlib/*23000001*/]System.RuntimeMethodHandle/*0100002F*/)/*0A000042*/
IL_0020: castclass    [mscorlib/*23000001*/]System.Reflection.MethodInfo/*01000017*/
IL_0025: ldc.i4.1
IL_0026: newarr       [System.Core/*23000002*/]System.Linq.Expressions.Expression/*0100002D*/
IL_002b: dup
IL_002c: ldc.i4.0
IL_002d: ldstr        "x"
IL_0032: ldtoken      [mscorlib/*23000001*/]System.String/*01000021*/
IL_0037: call         class [mscorlib/*23000001*/]System.Type/*01000014*/ [mscorlib/*23000001*/]System.Type/*01000014*/::GetTypeFromHandle(valuetype [mscorlib/*23000001*/]System.RuntimeTypeHandle/*01000022*/)/*0A000014*/
IL_003c: call         class [System.Core/*23000002*/]System.Linq.Expressions.ConstantExpression/*01000030*/ [System.Core/*23000002*/]System.Linq.Expressions.Expression/*0100002D*/::Constant(object, class [mscorlib/*23000001*/]System.Type/*01000014*/)/*0A000043*/
IL_0041: stelem.ref
IL_0042: call         class [System.Core/*23000002*/]System.Linq.Expressions.MethodCallExpression/*01000031*/ [System.Core/*23000002*/]System.Linq.Expressions.Expression/*0100002D*/::Call(class [System.Core/*23000002*/]System.Linq.Expressions.Expression/*0100002D*/, class [mscorlib/*23000001*/]System.Reflection.MethodInfo/*01000017*/, class [System.Core/*23000002*/]System.Linq.Expressions.Expression/*0100002D*/[])/*0A000044*/
IL_0047: ldc.i4.1
IL_0048: newarr       [System.Core/*23000002*/]System.Linq.Expressions.ParameterExpression/*0100001D*/
IL_004d: dup
IL_004e: ldc.i4.0
IL_004f: ldloc.0      // V_0
IL_0050: stelem.ref
IL_0051: call         class [System.Core/*23000002*/]System.Linq.Expressions.Expression`1/*01000032*/<!!0/*class [mscorlib*//*23000001*//*]System.Func`2*//*01000012*//*<string, bool>*/> [System.Core/*23000002*/]System.Linq.Expressions.Expression/*0100002D*/::Lambda<class [mscorlib/*23000001*/]System.Func`2/*01000012*/<string, bool>>(class [System.Core/*23000002*/]System.Linq.Expressions.Expression/*0100002D*/, class [System.Core/*23000002*/]System.Linq.Expressions.ParameterExpression/*0100001D*/[])/*2B000002*/
IL_0056: pop
// Define Expresin parameter p
var parameterExpression = Expression.Parameter(typeof (string), "p");
// Gets method handler for string.Contains method
// Plase note that __methodref can not be used in c# butit is valid in il code
var methodInfo = (MethodInfo) MethodBase.GetMethodFromHandle(__methodref (string.Contains));
// Constant string x added as paramter
var constantXString = new Expression[] {Expression.Constant("x", typeof (string))};
// Call given method on the the given parameter and make it into a lambda expression
Expression.Lambda<Func<string, bool>>(Expression.Call(parameterExpression, methodInfo, constantXString), parameterExpression);