2013-07-03 25 views
2

給定Msdn:常量表達式是一個可以在編譯時完全評估的表達式。ConstantExpression不是常量

但是在下面的示例代碼中,我有一個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); 
} 
+0

要成爲一個常量表達式,您的'maybeAConstantExpression'應該保持一個常量值,但它不是,它依賴於運行時的控制檯讀取行;所以你的constantExpression不會在編譯時被評估。 – Jegan

回答

5

A const是可以在編譯時評估的東西。 a ConstantExpression僅僅代表固定值。這可能來自編譯時,但它不是必需的,而且通常不是。

有一個常量表達式(在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); 

,如果你與Expresion API手動編寫它(即像上面那樣)

+0

因此,在您的第一個代碼示例中,Expression.Constant(ctx)如何成爲常量?這是HorribleNameThatYouCannotSay的一個實例,不是嗎? – Toto

+0

@Toto再一次,我明確地說,它不是在語言意義上的「常量」。它在「表達式」意義上是一個常量,因爲它表示一個固定值(與參數等相對)。但是這個固定值是在運行時提供的。 'Expression'是一個運行時API。 –

+0

@Toto要清楚 - 在第一個例子中,我所做的所有事情都是寫成'Expression >表達式= c => c.Key == wantedKey;',但是*編譯器做它* –

相關問題