【问题标题】:Helper methods in C#: Static or non-static?C# 中的辅助方法:静态还是非静态?
【发布时间】:2010-08-30 20:51:25
【问题描述】:

我有一个包含一些函数的类,这些函数实际上只是“帮助”方法,客户端代码可以使用其他公共访问器属性/方法自行完成,我不确定是否应该将这些定义为具有getter、实例方法或将实例作为参数的静态方法。此外,我还从类中提取了一个接口,该接口几乎在除构造之外的所有地方都使用,以允许我的代码使用针对该接口实现的任何类。

问题是,从设计的角度来看,哪个最好?例如,作为从此类中获取初始值的一种方式:

class Person : IPerson {
  private string name;

  public string Name { get { return this.name; } }

  // Property with getter
  public string Initial { get { return this.name.Substring(0,1); } }

  // Instance method
  public string GetInitial { return this.name.Substring(0,1); }

  // Static method
  public static string GetInitial(IPerson person) {
    return person.Name.Substring(0,1);
  }
}

该属性适用于更短、更易读的客户端代码,但要求任何针对 IPerson 实现的人编写自己的实现,实例方法也是如此。

静态方法意味着实现类不需要自己编写,我的代码可以保证初始是如何根据名称确定的,但这意味着它不能在接口上,客户端代码是一个稍微详细一点。

这只是归结为允许实现类指定如何计算辅助方法是否是个好主意?

编辑:除了次​​要,为什么不让我添加最佳实践标签?

【问题讨论】:

  • 似乎还没有最佳实践标签。您需要至少 1500 声望才能创建新标签。
  • 这很奇怪..肯定有,我过去用过。
  • 元标签的消亡(例如最佳实践):blog.stackoverflow.com/2010/08/the-death-of-meta-tags
  • @M4N:当我试图确定哪种通用方法更适合相当广泛的问题时,我认为最佳实践是一个有用的标签。也许这个问题不应该被表述为总体上哪个更好,而是在不同的情况下,利弊会支持或反对不同的方法。这似乎是一个公平类型的问题,与“为什么代码 X 打印 Y?”是不同类别的问题。或“我该怎么做 X”。可以肯定的是,后一种问题可能会演变成前一种。 “X 真的是这里最好的方法,还是 Z 可能会更好?”

标签: c#


【解决方案1】:

扩展方法怎么样?

namespace IPersonExtensions
{
    public static class IPersonExtensionClass
    {
        public static string Initial(this IPerson @this)
        {
            return @this.name.Substring(0, 1);
        }
    }
}

像这样使用它:

string initial = person.Initial();

这样,您无需继承或重写代码即可共享实现。使用单独的命名空间使用户可以选择是否要使用此代码。

【讨论】:

  • 没想到那个..虽然我猜那个方法应该可能返回一个字符串:)
  • Flynn 似乎是从零开始创建这个类的。如果是这种情况,则不应使用扩展方法,因为您可以访问源代码。当您无法修改或扩展基类时,应使用扩展方法。 MSDN General GuideLines msdn.microsoft.com/en-us/library/bb383977.aspx “一般来说,我们建议您谨慎地实现扩展方法,并且仅在必要时实现。只要有可能,必须扩展现有类型的客户端代码应该通过创建从现有类型派生的新类型来实现。 "
  • @Flynn1179: 没有,但是扩展方法比较简洁。我认为在这种情况下它是完全有效的。扩展方法并没有扩展类,它只是在其公共接口上调用方法。
  • @Flynn:是的,扩展方法只是语法糖,但重要的是它更符合大多数开发人员现在的想法。用户可以考虑智能感知的工作方式:object -> operation,而不是 operation -> object(帮助类需要)。这绝对有助于提高发现率。
  • 这实际上也使我的代码更整洁,因为辅助方法位于单独的代码文件中。此外,方法在接口上,而不是在类上,这更有意义。
【解决方案2】:

我来回走动,但我开始倾向于使它们非静态

静态案例:强制您声明该函数不使用成员变量并使其无状态。如果你不小心因为需要成员变量而让状态潜入,编译器会警告你,你必须做出具体的决定。

成员函数的例子:静态函数很难继承,所以改变行为也很困难。也使测试变得更加困难,因为用该功能代替测试其他东西更加困难。假设您有一些使用 Initial 的东西,并且您想返回特定于测试的东西......

顺便说一句(也是一个极端的例子),我的一些扩展使用 IOC 容器来定位具体类并在其上调用成员。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-06-22
    • 2011-02-01
    • 2012-06-17
    • 2011-01-17
    • 1970-01-01
    • 2014-10-04
    • 2021-04-05
    • 1970-01-01
    相关资源
    最近更新 更多