Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C#: implicit operator and extension methods

I am trying to create a PredicateBuilder<T> class which wraps an Expression<Func<T, bool>> and provides some methods to easily build up an expression with various And and Or methods. I thought it would be cool if I could use this PredicateBuilder<T> as an Expression<Func<T, bool>> directly, and thought this could be done by having an implicit operator method thing.

Stripped down version of the class looks like this:

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;
    }
}

Then, just as a test, I have this extention method in a static class:

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

In my head, I should then be able to do these:

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

p.PrintExpression();
PredicateExtensions.PrintExpression(p);

However none of them work. For the first one, the extension method is not found. And for the second, it says that

The type arguments for method 'ExtravagantExpressions.PredicateHelper.PrintExpression(System.Linq.Expressions.Expression>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

So I tried the following, which worked:

PredicateExtensions.PrintExpression<int>(p);

Also, this works, of course:

((Expression<Func<int, bool>>) p).PrintExpression();

But yeah... why don't the others work? Have I misunderstood something about how this implicit operator thing works?

like image 936
Svish Avatar asked Mar 26 '09 10:03

Svish


1 Answers

This is not specific to extension methods. C# won't implicitly cast an object to another type unless there is a clue about the target type. Assume the following:

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() { ... }
}

Which method would you expect to be called in the following statement?

new A().Foo(); // B.Foo? C.Foo? 
like image 112
mmx Avatar answered Sep 24 '22 18:09

mmx