C#:隐式运算符和扩展方法

Svi*_*ish 12 c# extension-methods operator-overloading

我想创建一个PredicateBuilder<T>它包装的类Expression<Func<T, bool>>,并提供一些方法来轻松地建立了各种的表达AndOr方法.我认为这将是冷静,如果我可以用这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;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,就像测试一样,我在静态类中有这个扩展方法:

public static void PrintExpression<T>(this Expression<Func<T, bool>> expression)
{
    Console.WriteLine(expression);
}
Run Code Online (Sandbox Code Playgroud)

在我的脑海中,我应该能够做到这些:

var p = new PredicateBuilder<int>(true);

p.PrintExpression();
PredicateExtensions.PrintExpression(p);
Run Code Online (Sandbox Code Playgroud)

但是它们都不起作用.对于第一个,找不到扩展方法.而对于第二个,它说

无法从用法中推断出方法'ExtravagantExpressions.PredicateHelper.PrintExpression(System.Linq.Expressions.Expression>)'的类型参数.尝试显式指定类型参数.

所以我尝试了以下工作:

PredicateExtensions.PrintExpression<int>(p);
Run Code Online (Sandbox Code Playgroud)

此外,这当然有效:

((Expression<Func<int, bool>>) p).PrintExpression();
Run Code Online (Sandbox Code Playgroud)

但是,为什么其他人不工作呢?我误解了这个东西是如何implicit operator工作的吗?

Meh*_*ari 12

这不是扩展方法特有的.除非有关于目标类型的线索,否则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() { ... }
}
Run Code Online (Sandbox Code Playgroud)

您希望在以下语句中调用哪种方法?

new A().Foo(); // B.Foo? C.Foo? 
Run Code Online (Sandbox Code Playgroud)

  • 我希望"Foo()不明确:B.Foo()或C.Foo()" (3认同)
  • @Anton:这是可能的,但会使语言复杂化并可能隐藏副作用。毕竟,当您在类上定义新的隐式运算符时,如果工作代码突然中断,您会有什么感觉:) 只是在任何地方强制显式类型声明更简单。 (2认同)