[英]C#: implicit operator and extension methods
我正在嘗試創建一個包含Expression<Func<T, bool>>
的PredicateBuilder<T>
類,並提供一些方法來使用各種And
和Or
方法輕松構建表達式。 我認為如果我可以直接使用這個PredicateBuilder<T>
作為Expression<Func<T, bool>>
會很酷,並且認為這可以通過implicit operator
方法來完成。
這個類的精簡版看起來像這樣:
class PredicateBuilder<T>
{
public Expression<Func<T, bool>> Predicate { get; protected set; }
public PredicateBuilder(bool initialPredicate)
{
Predicate = initialPredicate
? (Expression<Func<T, bool>>) (x => true)
: x => false;
}
public static implicit operator Expression<Func<T, bool>>(
PredicateBuilder<T> expressionBuilder)
{
return expressionBuilder.Predicate;
}
}
然后,就像測試一樣,我在靜態類中有這個擴展方法:
public static void PrintExpression<T>(this Expression<Func<T, bool>> expression)
{
Console.WriteLine(expression);
}
在我的腦海中,我應該能夠做到這些:
var p = new PredicateBuilder<int>(true);
p.PrintExpression();
PredicateExtensions.PrintExpression(p);
但是它們都不起作用。 對於第一個,找不到擴展方法。 而對於第二個,它說
無法從用法中推斷出方法'ExtravagantExpressions.PredicateHelper.PrintExpression(System.Linq.Expressions.Expression>)'的類型參數。 嘗試顯式指定類型參數。
所以我嘗試了以下工作:
PredicateExtensions.PrintExpression<int>(p);
此外,這當然有效:
((Expression<Func<int, bool>>) p).PrintExpression();
但是,為什么其他人不工作呢? 我是否誤解了這個implicit operator
的工作原理?
這不是擴展方法特有的。 除非有關於目標類型的線索,否則C#不會隱式地將對象強制轉換為其他類型。 假設如下:
class A {
public static implicit operator B(A obj) { ... }
public static implicit operator C(A obj) { ... }
}
class B {
public void Foo() { ... }
}
class C {
public void Foo() { ... }
}
您希望在以下語句中調用哪種方法?
new A().Foo(); // B.Foo? C.Foo?
不,你沒有,但C#編譯器的類型推導不夠強大,無法理解你的代碼,特別是它不會看隱式運算符。 你必須堅持使用Expression<Func<T,bool>>
- 為什么沒有像Or
這樣的擴展方法, And
直接在表達式上?
正如Anton所說,如果將擴展方法直接放在Expression<Func<...>>
它可能會起作用。
更多的解釋......沒有什么特別聰明,但想法是你沒有一個你創建實例的PredicateBuilder
類。 相反,你只有純粹的靜態構建塊:
public static class Predicates
{
public static Expression<Func<T, bool>> True<T>()
{
return x => true;
}
public static Expression<Func<T, bool>> False<T>()
{
return x => false;
}
public static Expression<Func<T, bool>> And<T>(
this Expression<Func<T, bool>> left,
Expression<Func<T, bool>> right)
{
return ... // returns equivalent of (left && right)
}
}
這兩個函數True
和False
扮演你的PredicateBuilder(bool)
構造函數的角色,你可能會有類似的原始比較等等,然后像And
這樣的運算符會讓你把兩個表達式插在一起。
但是,您將失去使用運算符符號的功能,您可以將其與包裝器對象一起使用,而必須使用方法名稱。 我一直在玩同樣的方法,我總是回到過的地方是我希望能夠定義擴展操作符。 C#團隊顯然認為這些是3.0(以及擴展屬性),但它們的優先級較低,因為它們沒有參與Linq的整體目標。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.