【问题标题】:Should I make C# private methods generic?我应该使 C# 私有方法通用吗?
【发布时间】:2012-07-07 08:24:50
【问题描述】:

我有一个 API,其中包含一些接受类型参数的方法。我现在将它们转换为泛型方法,作为改进 API(更类型安全)的一部分,同时保留非泛型版本以实现向后兼容性。

当前 - 将被淘汰:

public object MyMethod(object value, Type expectedType)

新:

public T MyMethod<T>(object value)

然而,Mymethod 调用了一个私有的辅助方法,它也接受一个类型参数:

private object HelperMethod(object value, Type expectedType)

问题:我是否也应该将这个私有辅助方法设为通用?

我在下面有自己的答案,但我想知道我是否遗漏了什么。非常感谢您的见解。

我的回答是否定的,我不应该将这个私有方法设为通用。

原因 1:此辅助方法是私有的,因此即使我将其设为通用,它也不会改进 API。

原因2:如果我将其设为泛型,那么非泛型公共方法将不得不使用反射将类型参数传递给该泛型方法,这意味着更多开销。

【问题讨论】:

  • 您说将其转换为泛型会因为反射而导致窃听,但了解 HelperMethod() 对该类型的作用会有所帮助。开销不是现在就在那里发生吗?
  • itsme86 - 我相信当 MyMethod 的非泛型版本使用反射调用泛型 HelperMethod 时会产生额外的开销。所以,HelperMethod 的开销不在图中……
  • 值参数是否也将是 T 类型或者这是某种转换器?如果它是 T 类型,我肯定会建议制作该方法的通用版本以避免装箱/拆箱处罚。事实上,如果不是 T 类型,那么一个 T MyMethod(U value) 来避免装箱呢?
  • 泛型的一个主要好处是它使代码快速。没有拳击,没有铸造。没有充分的理由让私有方法变慢。
  • itsme86 - value 参数仅用于此示例,但实际上它属于特定类型...但是,我肯定会在未来的场景中使用您的建议,谢谢!

标签: c# generics methods private


【解决方案1】:

我认为这取决于您计划支持非泛型方法的时间量、调用频率、对反射的影响等等。

我认为您会尽可能多地使用通用功能来利用所需的类型安全性。然后在必要时改造非泛型版本以使用泛型版本,并最终尽快弃用它。

【讨论】:

  • MyMethod() 的非泛型版本仍然被广泛使用,增加开销不是我的愿望。我会说他们会存在很长一段时间。我为所有公共方法提供了一个通用版本。但我的问题是,我是否应该使用私有辅助方法来这样做? (成为一名优秀的开发人员,纯粹主义者......等等......);)
【解决方案2】:

使您的私有辅助方法泛型确实可以通过在您的实现中始终携带泛型类型特异性来改进 API。如果您将类型限制为处理无类型 System.Objects 的核心,那么您的实现并没有完全实现泛型的类型安全优势。

例如,为什么 MyMethod 的参数仍然是 System.Object?如果该参数源自源,那么它也应该是一个类型参数。如果参数源自数据,则最好使用 System.Object。泛型在与源代码一起使用时最有用,因为源代码表达式在大多数上下文中隐式提供了类型。

泛型的隐藏成本取决于将与 API 一起使用的类型组合。如果大多数类型将是值类型(内置和结构),那么将 API 切换到泛型可能会增加您的内存消耗,因为泛型代码必须针对每种值类型进行不同的 jit。如果与通用 API 一起使用的大多数类型都是引用类型(类和接口),那么代码/内存爆炸就不是问题,因为所有引用类型都共享相同的 JIT 代码。

让旧 API 调用新的通用 API 的成本是否 a) 可衡量和 b) 可接受完全取决于您在私有帮助器方法中所做的事情 - 特别是私有帮助器方法对 Type 所做的事情范围。

如果辅助方法实现相当轻量,并且您确定(通过性能测量)调整旧 API 以调用新的通用辅助方法的成本是不可接受的,我会考虑复制辅助方法实现,并排,一个在旧样式中,在新的通用样式中。这消除了 API 样式之间的交叉转换成本,并消除了将新错误引入旧 API 的风险,但代价是略微增加了内部代码维护工作。

【讨论】:

  • 感谢您提供非常有见地和教育性的建议。我倾向于复制辅助方法。它的实现不是轻量级的,但维护工作是可控的。通过这种方式,我可以确保更彻底地转换为泛型。
猜你喜欢
  • 2011-10-09
  • 1970-01-01
  • 1970-01-01
  • 2014-08-02
  • 1970-01-01
  • 2016-04-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多