扩展类型以在私有成员上公开扩展方法不好吗?

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

我最近因扩展自定义 class 以在私有成员上公开 LINQ 扩展方法而受到指责,比如:

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

一些团队成员认为这很糟糕。给出的解释是这样的:既然内部方法是一个扩展方法,那么外部方法也应该是。

(为什么)这么糟糕?

如果'overrides'该扩展方法的功能或签名彼此不兼容,则添加与现有扩展方法同名的方法不是主要问题(或者如果扩展方法不能应用于该特定 class).

如果这些规则不适用,或者您确实打算同时使用它们,那么最终调用的方法可能真的很令人困惑。这可能会导致错误,所以我不建议使用与扩展方法同名的方法。

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

如果那是论点,那完全是胡说八道。得出其合乎逻辑的结论,我们不能在实例成员中调用任何静态成员(因为扩展方法只是带有一些语法糖的静态方法,使它们在第一个参数上看起来像实例方法)。始终如一地应用它,您很快就会得到根本没有静态方法或根本没有对象的结果。

不过这里有点问题:

public virtual T FirstOrDefault(Expression> predicate)

FirstOrDefault是常用的扩展方式。因此,我们知道每当我们调用它时它会做什么。

如果 class 充当包装 _someDbSet 的集合,那么此方法毫无意义;我们可以只使用已经存在的FirstOrDefault

如果 class 不作为包装 _someDbSet 的集合,那么这个方法可能会令人困惑,因为它不会像我们期望的那样众所周知 FirstOrDefault 行动起来。

如果 class 是 IEnumerableIQueryable 并且 FirstOrDefaultFirstOrDefault 扩展方法不一样,那么它确实可能会非常混乱,因为相同的成员名称会根据引用对象的方式产生不同的行为,而这很少是一件好事。

相反,如果我们有一个 FirstOrDefault 实例方法,它做与 FirstOrDefault 相同的事情,但效率更高,那么就是有一个实例方法掩码的情况扩展方法确实是一件好事;就调用代码而言,没有行为差异,就调用代码而言,只是性能提升"free",因为它的编写方式与无论如何都完全相同。