2009-11-30 17 views
4

我有一個擴展方法具有以下簽名:如何測試一個表達式短路

public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second) 
{ 
    ... 
} 

我已經寫了測試用例它是確保兩個表達式其實相結合。至少讓我得到新的表達方式起作用。

現在我想寫另一個測試案例,只是確保該方法使用and的短路版本。任何線索我怎麼能做到這一點?

我想我可能只是做這樣的事情:

[Test] 
    public void And_PredicatesAreShortCircuited() 
    { 
     var predicateNotUsed = true; 
     Expression<Func<int, bool>> a = x => false; 
     Expression<Func<int, bool>> b = x => 
      { 
       predicateNotUsed = false; 
       return true; 
      }; 

     var foo = new[] { 1, 2, 3, 4, 5, 6, 7 } 
      .Where(a.And(b).Compile()) 
      .ToArray(); 

     Assert.That(predicateNotUsed); 
    } 

,但我得到一個巨大的紅色波浪是整個語句體下b指出「與語句體lambda表達式不能轉換到表達樹「。那麼......有什麼選擇?或者這是一個不可能的測試寫?

+2

你有一些trues和混淆在那裏的錯誤。 – 2009-11-30 14:54:16

+0

W 012。想想我現在就設法得到它..:p – Svish 2009-12-01 02:15:46

+0

只是關於錯誤的簡短解釋。在單行lambda表達式或表達式lambdas(「a」case)與表達式樹之間存在隱式轉換,但多行lambda表達式或語句lambdas(「b」case)與表達式樹之間沒有隱式轉換。 欲瞭解更多信息,請參閱http://blogs.msdn.com/csharpfaq/archive/2009/09/14/generating-dynamic-methods-with-expression-trees-in-visual-studio-2010.aspx – 2009-12-01 18:36:42

回答

8

簡單的建議:使用引用類型而不是值類型,並將其取消引用到不希望的路徑中。傳入null,看看它是否會拋出異常:)

[Test] 
public void And_PredicatesAreShortCircuited() 
{ 
    Expression<Func<string, bool>> a = x => false; 
    Expression<Func<string, bool>> b = x => x.Length > 10; 

    var foo = new[] { null, null } 
     .Where(a.And(b).Compile()) 
     .ToArray(); 
} 

另一種方法是使用一些副作用的功能對輸入數據(例如傳遞的東西,可以通過表達式樹被改變),但我覺得上面的將可能是最簡單的做法:)

或者另一個想法:

public T NonVoidFail(T x) 
{ 
    Assert.Fail("I shouldn't be called"); 
    return x; // Will never happen 
} 

然後:

[Test] 
public void And_PredicatesAreShortCircuited() 
{ 
    Expression<Func<int, bool>> a = x => false; 
    Expression<Func<int, bool>> b = x => NonVoidFail(x); 

    var foo = new[] { 1, 2, 3, 4, 5, 6, 7 } 
     .Where(a.And(b).Compile()) 
     .ToArray(); 
} 

這是一樣的原則,但它會給你一個更好的例外:)

+1

你想出這個東西......? :p - 謝謝! :d – Svish 2009-12-01 05:39:03