简体   繁体   English

这个C#构造的作用是什么?为什么? 我的课 <TMyClass> :MyClass在哪里

[英]What is this C# construct doing and why? MyClass<TMyClass> : MyClass where

I came across the following code, all in a single file/class. 我遇到了以下代码,都在一个文件/类中。 I'm leaving out the details, its the construct I'm interested in. Why are there two different declarations for the same class and how are they different? 我遗漏了细节,它是我感兴趣的构造。为什么同一个类有两个不同的声明,它们有什么不同? What's the purpose of the syntax for the second declaration? 第二个声明的语法的目的是什么?

public abstract class MyClass
{
    ...
}

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

MyClass - A abstract class named MyClass. MyClass - 一个名为MyClass的抽象类。

MyClass<TMyClass> : MyClass - A abstract generic class named MyClass<> but with a generic type named TMyClass . MyClass<TMyClass> : MyClass - 一个名为MyClass<>抽象泛型类,但具有名为TMyClass的泛型类型。

If you rename the types, it will be easier to see: 如果重命名类型,将更容易看到:

public abstract class MyBaseClass
{
    ...
}

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

Types with different generic arity (ie number of generic type parameters, which can be zero or more) are considered as completely unrelated by the language and can have the same name. 具有不同通用arity的类型(即泛型类型参数的数量,可以是零或更多)被认为与语言完全无关,并且可以具有相同的名称。

This means that you can have classes Foo , Foo<T> and Foo<T,U> at the same time; 这意味着你可以同时拥有类FooFoo<T>Foo<T,U> ; the syntax will allow the compiler to determine which you are referring to. 语法将允许编译器确定您指的是哪个。 You can see this happen in the base framework which includes Action , Action<T> etc. 您可以在包含ActionAction<T>等的基础框架中看到这种情况。

The "recursive" construct class C<T> where T: C<T> (the inheritance from a non-generic C does not change anything so I removed it) is the C# on what is called the Curiously Recurring Template Pattern (CRTP) in C++. “递归”构造class C<T> where T: C<T> (来自非泛型C的继承不会改变任何东西,所以我将其删除)是所谓的奇怪重复模板模式 (CRTP)上的C#在C ++中。 Eric Lippert has covered this subject very well in a blog post, where the conclusion is that one should think more than twice before implementing this -- there are problems it can solve, but the solution also has a price. Eric Lippert在博客文章中非常清楚地介绍了这个主题 ,其结论是在实现这个问题之前应该考虑两次以上 - 它可以解决问题,但解决方案也有代价。

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

is a class that inherits from MyClass , and it takes a generic type, which has to inherit from MyClass<TMyClass> 是一个继承自MyClass的类,它采用泛型类型,必须从MyClass<TMyClass>继承


Here's a simpler example of the same thing for you 这是一个更简单的例子,同样适合你

    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;
        }
    }
}

It's a classic idiom, the Curiously Recurring Template Pattern, done in C#. 这是一个经典的成语,奇怪的重复模板模式,用C#完成。

It means the template can only be used thusly: 这意味着模板只能这样使用:

class Foo : MyClass<Foo>
{
}

In this construction, Foo inherits MyClass<Foo> which inherits MyClass . 在这种结构中, Foo继承MyClass<Foo>它继承MyClass

This has a few advantages, but I've forgotten which. 这有一些优点,但我忘了哪个。

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

First thing to point out is that this is an abstract class that is inheriting from another abstract class. 首先要指出的是,这是一个从另一个抽象类继承的抽象类。 In other words, this is a class that cannot be instantiated (without another class inheriting from it), but is using inheritence to derive the functionality from another abstract class (which is fine). 换句话说,这是一个无法实例化的类(没有从中继承的另一个类),但是使用继承来从另一个抽象类派生功能(这很好)。

The second thing to point out, is that this is a Template class (or generic class as they call it in C#) which accepts type in it's . 要指出的第二点是,这是一个模板类(或者在C#中称为泛型类),它接受类型。 I would reduce that to T as a convention so that T is always a template, though it is completely up to you what you call things. 我会把它简化为T作为约定,这样T总是一个模板,尽管它完全取决于你所谓的东西。

Lastly there is a constraint on this which is kind of strange. 最后有一个限制,这有点奇怪。 It says that, no matter what, the compiler will not allow any class type to be passed in as a template type, unless it inherits from (somewhere along the inheritance chain) 它说,无论如何,编译器都不允许任何类类型作为模板类型传入,除非它继承自(继承链的某个地方)

 MyClass<TMyClass>

This is shown in the following line 这显示在以下行中

 where TMyClass: MyClass<TMyClass>

basically this prevents anyone from passing in an object that does not follow this rule. 基本上这可以防止任何人传入不遵循此规则的对象。

What is a bit odd is that the constraints tells the implementer that it cannot be a template unless the type passed by template is in fact a type of itself. 有点奇怪的是,约束告诉实现者它不能是模板,除非模板传递的类型实际上是一种类型。 You as the designer of this class (or implementer) has to decide if this is a wise design, though this in itself looks a bit strange. 你作为这个类(或实现者)的设计者必须决定这是否是一个明智的设计,虽然这本身看起来有点奇怪。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM