这个C#构造的作用是什么?为什么? MyClass <tmyclass>:MyClass where </tmyclass>

时间:2013-10-10 14:24:44

标签: c# generics inheritance

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

public abstract class MyClass
{
    ...
}

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

5 个答案:

答案 0 :(得分:3)

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

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

如果您重命名类型,则会更容易看到:

public abstract class MyBaseClass
{
    ...
}

public abstract class MyClass<T> : MyBaseClass
    where T: MyClass<T>
{
    ...
}

答案 1 :(得分:3)

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

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

“递归”构造class C<T> where T: C<T>(来自非泛型C的继承不会改变任何东西,所以我删除它)是所谓的Curiously Recurring Template Pattern上的C#(CRTP )在C ++中。 Eric Lippert has covered this subject在一篇博客文章中非常清楚,其结论是在实现这一点之前应该考虑两次以上 - 它可以解决的问题,但解决方案也有代价。

答案 2 :(得分: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;
        }
    }
}

答案 3 :(得分:0)

这是一个经典的成语,奇怪的重复模板模式,用C#完成。

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

class Foo : MyClass<Foo>
{
}

在此结构中,Foo继承了继承MyClass<Foo>的{​​{1}}。

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

答案 4 :(得分:-1)

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

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

要指出的第二点是,这是一个模板类(或在C#中调用它的泛型类),它接受类型。我会把它简化为T作为约定,这样T总是一个模板,尽管它完全取决于你所谓的东西。

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

 MyClass<TMyClass>

这显示在以下行

 where TMyClass: MyClass<TMyClass>

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

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