6

我在一个文件/类中遇到了以下代码。我省略了细节,它是我感兴趣的构造。为什么同一个类有两个不同的声明,它们有什么不同?第二个声明的语法的目的是什么?

public abstract class MyClass
{
    ...
}

public abstract class MyClass<TMyClass> : MyClass
    where TMyClass: MyClass<TMyClass>
{
    ...
}
4

5 回答 5

3

MyClass- 一个名为 MyClass 的抽象类。

MyClass<TMyClass> : MyClass- 一个名为的抽象泛型类MyClass<>,但具有名为 的泛型类型TMyClass

如果重命名类型,将更容易看到:

public abstract class MyBaseClass
{
    ...
}

public abstract class MyClass<T> : MyBaseClass
    where T: MyClass<T>
{
    ...
}
于 2013-10-10T14:29:31.247 回答
3

具有不同泛型数量的类型(即泛型类型参数的数量,可以是零或更多)被认为与语言完全无关并且可以具有相同的名称。

这意味着您可以同时拥有课程Foo;语法将允许编译器确定您指的是哪个。您可以在包含等的基本框架中看到这种情况。Foo<T>Foo<T,U>ActionAction<T>

“递归”构造class C<T> where T: C<T>(从非泛型继承C并没有改变任何东西,所以我删除了它)是 C# 中所谓的 C++ 中的奇怪循环模板模式(CRTP)。Eric Lippert在一篇博客文章中很好地涵盖了这个主题,其中的结论是在实施之前应该三思而后行——它可以解决一些问题,但解决方案也有代价。

于 2013-10-10T14:30:26.653 回答
2
public abstract class MyClass<TMyClass> : MyClass
    where TMyClass: MyClass<TMyClass>
{
    ...
}

是一个继承自 的类,MyClass它需要一个泛型类型,它必须继承自MyClass<TMyClass>


这是一个更简单的例子

    public static void Main()
    {
        MyClass<Myclass> other = new MyClass<Myclass>(new Myclass());
        List<int> intlist = new List<int>();
    }

    public class Myclass
    {
        public Myclass()
        {
        }
        public int i { get; set; }
    }

    public class MyClass<T> where T : Myclass
    {
        T value;
        public MyClass(T val)
        {
            value = val;
        }
    }
}
于 2013-10-10T14:26:23.280 回答
0

这是一个经典的成语,Curiously Recurring Template Pattern,用 C# 完成。

这意味着模板只能这样使用:

class Foo : MyClass<Foo>
{
}

在这种构造中,Foo继承MyClass<Foo>哪个继承MyClass

这有一些优点,但我忘记了。

于 2013-10-10T14:31:18.980 回答
-1
 public abstract class MyClass<TMyClass> : MyClass
       where TMyClass: MyClass<TMyClass>
 {
        ...
 }

首先要指出的是,这是一个继承自另一个抽象类的抽象类。换句话说,这是一个无法实例化的类(没有另一个类从它继承),而是使用继承从另一个抽象类派生功能(这很好)。

要指出的第二件事是,这是一个 Template 类(或在 C# 中调用它的泛型类),它接受它的 . 我会将其简化为 T 作为约定,以便 T 始终是一个模板,尽管这完全取决于您如何称呼事物。

最后,对此有一个限制,这有点奇怪。它说,无论如何,编译器都不允许任何类类型作为模板类型传入,除非它继承自(沿继承链的某处)

 MyClass<TMyClass>

这显示在以下行中

 where TMyClass: MyClass<TMyClass>

基本上,这可以防止任何人传入不遵循此规则的对象。

有点奇怪的是,约束告诉实现者它不能是模板,除非模板传递的类型实际上是它自己的类型。你作为这个类的设计者(或实现者)必须决定这是否是一个明智的设计,尽管这本身看起来有点奇怪。

于 2013-10-10T14:36:16.820 回答