C#泛型编程: "X<T> where T: X<T>" 泛型类型约束有什么意义?

19

阅读一本书:NHibernate 3: 入门指南,我发现了一个让我感到好奇的片段:

动手实践——创建基础实体

(...)

  1. 在项目的 Domain 文件夹中添加一个新类,并将其命名为 Entity。将该类声明为抽象类并使用 T 泛型。你的代码应该与以下代码片段类似:
 using System;

 namespace OrderingSystem.Domain
 {
     public abstract class Entity<T> where T : Entity<T>
     { }
 }

我的问题是:片段where T : Entity<T>的意义是什么?

我知道where部分可以用来添加类型约束,但上面的代码看起来似乎永远不可能实例化这样的类(即使它本来就是抽象的)。


1个回答

30

这很可能是为了提供更多的类型安全性,以便于返回(或接收)更多派生类型的实例,从而使调用者无需将结果转换为更多的派生类型。

abstract class Cloneable<T> where T : Cloneable<T>
{
    public abstract T Clone();
}

sealed class MyCloneable : Cloneable<MyCloneable>
{
    public override MyCloneable Clone()
    {
        return new MyCloneable();
    }
}

MyCloneable instance = new MyCloneable();
MyCloneable clone = instance.Clone();

编辑

根据@siride的评论,这被称为奇妙递归模板模式。Eric Lippert在C#中应用它写了一篇很棒的文章:

https://blogs.msdn.microsoft.com/ericlippert/2011/02/03/curiouser-and-curiouser/

附:如果您去除泛型约束,上面的示例将如何呈现:

abstract class Cloneable
{
    public abstract Cloneable Clone();
}

sealed class MyCloneable : Cloneable
{
    public override Cloneable Clone()
    {
        return new MyCloneable();
    }
}

MyCloneable instance = new MyCloneable();
MyCloneable clone = (MyCloneable)instance.Clone(); // Note the cast.

3
这是它的一个变体:https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern。 - siride

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接