2

给定 Msdn :常量表达式是可以在编译时完全评估的表达式。

但是在下面的示例代码中,我有一个无法在编译时评估的 contantExpression。

我应该错过了什么,但是什么?

public class SomeClass
{
    public string Key { get; set; }
}

public static void Sample()
{
    var wantedKey = Console.ReadLine();
    Expression<Func<SomeClass, bool>> expression = c => c.Key == wantedKey;

    var maybeAConstantExpression = ((MemberExpression)((BinaryExpression)expression.Body).Right).Expression;

    //Both are true, so we have a constantExpression,righ and Value should be known
    Console.WriteLine(maybeAConstantExpression.NodeType == ExpressionType.Constant);
    Console.WriteLine(maybeAConstantExpression.GetType() == typeof(ConstantExpression));

    var constantExpression = ((ConstantExpression)maybeAConstantExpression);
    var constantValue = constantExpression.Value;

    //ConsoleApplication1.Program+<>c__DisplayClass0
    //Do not looks like a constant..this is a class...
    Console.WriteLine(constantValue);

    var fakeConstantValue = constantValue.GetType().GetField("wantedKey").GetValue(constantValue);
    //Return the value entered whith Console.ReadLine
    //This is not really known at compile time...
    Console.WriteLine(fakeConstantValue);
}
4

1 回答 1

5

Aconst是可以在编译时评估的东西。aConstantExpression代表一个固定值。这可能来自编译时,但它不是必需的,而且通常不是。

常量表达式(在 C# 语言意义上)和ConstantExpression(运行时对象)之间是有区别的。

constantValue您的情况下,代表捕获上下文-提升的静默类wantedKey。基本上,该代码是(通过编译器):

class HorribleNameThatYouCannotSay {
    public string wantedKey; // yes, a public field
}
...
static void Sample()
{
    var ctx = new HorribleNameThatYouCannotSay();
    ctx.wantedKey = Console.ReadLine();
    var p = Expression.Parameter(typeof(SomeClass), "c");
    Expression<Func<SomeClass, bool>> expression =
        Expression.Lambda<Func<SomeClass, bool>>(
            Expression.Equal(
                Expression.PropertyOrField(p, "Key"),
                Expression.PropertyOrField(
                    Expression.Constant(ctx), "wantedKey")
                ), p);
    );
}

或者非常接近的东西

但它可能只是:

string wantedKey = Console.ReadLine();
var p = Expression.Parameter(typeof(SomeClass), "c");
Expression<Func<SomeClass, bool>> expression =
    Expression.Lambda<Func<SomeClass, bool>>(
        Expression.Equal(
            Expression.PropertyOrField(p, "Key"),
            Expression.Constant(wantedKey, typeof(string))
            ), p);

如果您使用 API 手动编写它Expresion(即如上)

于 2013-07-03T09:07:43.957 回答