Protector one
Protector one

Reputation: 7271

Is extending a type to expose an extension method on a private member bad?

I was recently berated for extending a custom class to expose a LINQ extension method on a private member, say:

public virtual T FirstOrDefault(Expression<Func<T, bool>> predicate)
{
    return _someDbSet.FirstOrDefault(predicate);
}

Some team members told this is bad. The explanation given was something along the line of: since the inner method is an extension method, the outer should be as well.

(Why) is this so bad?

Upvotes: 1

Views: 200

Answers (2)

Jon Hanna
Jon Hanna

Reputation: 113332

The explanation given was something along the line of: since the inner method is an extension method, the outer should be as well.

If that was the argument, then that's utter nonsense. Taken to its logical conclusion, we couldn't call any static members in instance members (since extension methods are just static methods with some syntactic sugar to make them look like instance methods on the first argument). Apply that consistently and you'd soon end up with either no static methods at all or no objects at all.

There is a bit of an issue here though:

public virtual T FirstOrDefault(Expression> predicate)

FirstOrDefault is a commonly used extension method. As such we have an idea what it's going to do whenever we call it.

If the class acts as a collection that wraps _someDbSet then this method is pointless; we can just use the FirstOrDefault that already exists.

If the class does not act as a collection that wraps _someDbSet then this method could be confusing, as it wouldn't act as we'd expect the well-known FirstOrDefault to act.

If the class is an IEnumerable or IQueryable and FirstOrDefault doesn't do the same thing as the FirstOrDefault extension method, then it could be very confusing indeed, because the same member name would produce different behaviour depending on how the object was referenced, and that's only very rarely a good thing.

Conversely though, if we had a FirstOrDefault instance method that did the same thing as FirstOrDefault would otherwise but did so much more efficiently, then that is a case where having an instance method mask an extension method is a very good thing indeed; there's no behaviour difference as far as the calling code is concerned, just a performance boost that is "free" as far as that calling code goes, as it's written in exactly the same way that it would be anyway.

Upvotes: 0

Patrick Hofman
Patrick Hofman

Reputation: 157058

There isn't a major problem in adding a method with the same name as an existing extension method if it 'overrides' the functionality of that extension method, or the signatures aren't compatible with each other (or if the extension method can't be applied to that specific class).

If those rules don't apply, or you do intent to use both of them, it can be really confusing which method is getting called in the end. This may lead to bugs, so I would not advise to use a method with the same name as the extension method.

Upvotes: 1

Related Questions