【问题标题】:Is there a name for this pattern of using generics?这种使用泛型的模式有名称吗?
【发布时间】:2011-10-31 16:17:44
【问题描述】:
//this class (or interface if you like) is set up as generic...
public abstract class GenericBase<T> 
{
    public T PerformBasicTask(T in) { ... }
}

//... but is intended to be inherited by objects that close the generic...
public class ConcreteForDates:GenericBase<DateTime>
{
    public DateTime PerformSpecificTask(DateTime in) { ... }
}

//... so that consuming code never knows that a generic is involved
var myDateConcrete = new ConcreteForDates(); //look ma, no GTP!
//These two methods look alike, and there is no generic type inference,
//even with PerformBasicTask().
var basicResult = myDateConcrete.PerformBasicTask(DateTime.Now);
var specificResult = myDateConcrete.PerformSpecificTask(DateTime.Today);

//does not compile because T is understood by inheritance to be a DateTime,
//even though PerformBasicTask()'s implementation may well handle an int.
var anotherBasicResult = myDateConcrete.PerformBasicTask(1);

我已经多次看到并使用过这种模式,它对于跨一系列特定于类型的子类提供通用功能非常有用。例如,这可能是控制器/演示者的模型,特定于一种域对象类型,该域对象是该类用于控制的页面的中心;检索/持久性等基本操作可能使用 100% 的通用功能,但绑定/解除绑定可能非常具体。

这种泛型声明模式是否有一个名称,而不会将泛型暴露给最终用户?

【问题讨论】:

  • “关闭通用”对我来说听起来不错。
  • 那么您究竟为什么要这样做?
  • 好吧,例如,您可能有一组控制器,每个控制器都采用您的一个域类(或 DTO)并在 UI 中的视图上执行绑定/取消绑定/验证任务。此外,他们还必须知道如何检索和持久化这些对象。该持久性机制可能(IMO 应该)被很好地抽象,以便控制器可以使用相同的代码执行操作。但是,验证/绑定/解除绑定几乎肯定是非常特定于类的。
  • 因此,您将定义一个具有通用持久性逻辑的 ControllerBase,然后在派生级别,因为您确切知道可以使用的类,关闭通用并指定您的特定类型逻辑。

标签: c# generics design-patterns


【解决方案1】:

我相信这不是一种模式,而是 .NET Framework 的 Generic Type 子系统的细节,它通过用具体类型(在您的示例中为 DateTime)替换泛型类型参数在运行时生成具体类型。所有其他关于分享共同行为的事情都被称为Inheritance

【讨论】:

    【解决方案2】:

    如果我要命名它,我会称之为 Specifics,我同意 Aliostad 的观点,因为它是一种反模式。

    【讨论】:

    • 你能不能也回答一下stackoverflow.com/questions/9447865/...?这个问题是否显示了泛型或反模式的正确用法?
    【解决方案3】:

    泛型用于重用需要在类型之外描述的行为 - 或至少在 where 子句强制执行的限制范围内。

    恕我直言,您看到的示例是泛型反模式。类型应该无关紧要,或者如果有,则只有在限制中定义时才重要 - 即where 子句。

    所以基本上,期望所有子类都实现抽象的泛型抽象类不使用泛型。我不能简单地开始使用Generic&lt;MyType&gt;,这是泛型的重点。

    我认为那是不合时宜的。

    在这种情况下,使用通用抽象类/接口有轻微的好处,这是PerformSpecificTask 实现的类型安全


    更新

    我知道这是一个有争议的问题,我会被左右开除,但我相信确实如此。

    一个类可以愉快地继承一个泛型类并添加更多功能。但在这种情况下,定义了该类的身份的是额外功能。当我不能只说Generic&lt;MyOwnTypeOfVolition&gt; 时,我就违背了泛型的目标。然而,有时,我关心的不是泛型——它是 interface,这里似乎就是这种情况。


    更新 2

    一个经典的例子是 .NET Framework 中的IConvertible

    您可以为它设置一个通用接口/抽象类并要求所有子类实现它,但框架将其设为可选情况,并且仅支持实现该接口的类。

    【讨论】:

    • 不得不说,我真的很反对这种想法。问题不在于允许在 C# 中执行此操作,而是 C# 没有更大、更正交的泛型系统。抽象基类在行为方面未指定。我看不出为什么它不能在类型方面也被低估,由派生类填充。
    • 什么,那么通过继承 Collection<T> 来实现非泛型集合是一种反模式?
    • 因此,如果我有一个 CustomerPageController 和一个 PersonPageController,它们分别与 Customer 和 Person 对象一起工作,并且我在后台有一个可以处理任何一个对象的存储库,但验证会完全不同,那么在实现我自己的特定类型的 Validate() 时,我不能从通用基础中公开 Save() 方法?
    • 关于编辑:这里的问题是 C# 没有办法拥有“抽象泛型”,其中填写类型也是合同的一部分。我们通过文档来解决这个问题。错误不在于程序员使用这种模式,而在于语言未能提供合适的机制来实现它。
    • @Justin 继承本身并不是反模式。您必须使用子类而不是 Collection&lt;MyClass&gt; 的事实是蚂蚁模式。
    猜你喜欢
    • 2010-11-21
    • 1970-01-01
    • 2012-04-19
    • 1970-01-01
    • 1970-01-01
    • 2010-09-09
    • 1970-01-01
    • 2011-04-23
    相关资源
    最近更新 更多