在可以修改的类上使用扩展方法是可以接受的
我最近一直在玩弄使用扩展方法在我控制的类上实现助手实用程序的想法(即,在同一个程序中,我可以修改)。 背后的基本原理是很多时候,这些帮助程序实用程序都用于特定的场景,并且不需要访问类内部值。
例如,假设我有一个StackExchange类。 它会有PostQuestion
和Search
和AnswerQuestion
。
现在,如果我想手动计算我的声望以确保StackOverflow不会欺骗我,该怎么办? 我会按照以下方式执行一些操作:
int rep=0;
foreach(var post in StackExchangeInstance.MyPosts)
{
rep+=post.RepEarned;
}
我可以将一个方法添加到StackExchange类中,但它不需要任何内部部件,并且只能从程序的一个或两个其他部分使用。
现在想象一下,如果你有10或20个这些特定的辅助方法。 肯定会在某种情况下有用,但绝对不适用于一般情况。 我的想法正在改变
public static RepCalcHelpers
{
public static int CalcRep(StackExchange inst){ ... }
}
像这样的东西
namespace Mynamespace.Extensions.RepCalculations
{
public static RepCalcExtensions
{
public static int CalcRep(this Stackexchange inst){...}
}
}
请注意命名空间。 理想情况下,我可以使用它在特定场景中对扩展方法进行分组。 例如“RepCalculations”,“Statistics”等
我试着搜索这种类型的模式是否听说过,并且还没有发现任何扩展方法的证据被用于除了你不能修改的类以外的任何东西。
这种“模式”有什么缺点? 我是否应该坚持继承或组合,或者只是一个好的“静态助手类”?
我会阅读扩展方法的框架设计指南部分。 这是第二版的作者之一。 Phil Haack引用了你描述的用例(专门的帮助器方法)作为扩展方法的有效用法,缺点是它需要API的额外知识才能找到这些“隐藏”方法。
没有在该文章中提到,但本书推荐的是扩展方法从扩展类进入单独的名称空间。 否则,他们将始终以智能感知出现,并且无法关闭它们。
我想我在其他地方看到过这种模式。 它可能相当混乱,但也相当强大。 这样,您可以在一个库中提供一个类,并在单独的名称空间中提供一组扩展方法。 那么谁使用你的库可以选择使用你的扩展方法来导入命名空间,或者提供他们自己的扩展方法。
如果你有一些扩展方法只用于单元测试(例如,比较两个对象在单元测试中是否相等),那么这个模式的一个好的候选者是。
您似乎在进行比较,即扩展方法等同于公共实例方法。 它真的不是。
扩展方法只是一个公共静态实用程序方法,它恰好具有用于调用的更方便的语法。
所以首先我们必须问自己,这个方法适合作为类本身的一个实例方法,还是更适合它作为外部类的静态方法。 事实上很少有类的用户需要这种功能,因为它是高度本地化的,并不是真正的行为,而是类本身执行的行为,而是由外部实体在类上执行的行为意味着它适合于静态。 主要缺点是,如果某人有User
并且想要重新计算他们的代表,那么这种行为可能很难找到。 现在,在这个特殊的情况下,它有点像栅栏,你可以用另一种方式,但我倾向于静态方法。
现在我们已经决定它应该是静态的,这是一个完全独立的问题,它是否应该是扩展方法。 这更主观,并进入个人偏好领域。 这些方法是否可能被链接? 如果是这样,扩展方法比嵌套调用静态方法更好地链接。 它可能会在使用它的文件中使用很多? 如果是的话,扩展方法可能会简化一些代码,如果不是这样,它并没有真正的帮助,甚至伤害。 对于玩具的例子,我可能会说我个人不会这样做,但我根本不会遇到任何问题(毕竟你仍然可以使用扩展方法,就好像它是常规的公共静态方法一样)。 对于一个非玩具的例子,它主要是一个个案的决定。 关键是要小心扩展什么类,并问问自己,如果用户愿意混淆某种类型的Intellisense只是为了方便地调用方法(这又会回到它使用的每个文件使用了多少在)。
另外值得一提的是,在扩展方法比实例化方法更强大的情况下,存在一些边缘情况。 特别是通过使用类型推断。 使用常规实例方法很容易接受类型或该类型的任何子类型,但有时返回传入的类型而非父类型是有用的。 这在流利的API中特别使用。 虽然这不是一个很常见的例子,只是与你的问题松散相关,所以我不会在这方面进行扩展。
链接地址: http://www.djcxy.com/p/96955.html上一篇: Is it acceptable to use extension methods on a class which you can modify