简体   繁体   English

如何将子类型传递给父 class C# 中的泛型

[英]How to pass child type to generic in parent class C#

I am currently consuming a third party dll and have no option to switch off of it or not use it.我目前正在使用第三方 dll 并且无法选择关闭它或不使用它。 I have a class that looks like this:我有一个看起来像这样的 class:

public abstract class ParentClass<T> : ApiClass<T> where T : ApiClass<T>
{
    //...stuff
}

This causes a few problems if I want to make a Dictionary or return the ParentClass type so that I don't need to know which child class it is beforehand.如果我想创建一个 Dictionary 或返回 ParentClass 类型,这会导致一些问题,这样我就不需要事先知道它是哪个子 class。 To make it easier to develop around this I would like to do something like this:为了更容易围绕这个开发,我想做这样的事情:

//ChildClass should be what is passed to the generic, without directly referencing it
public abstract class ParentClass : ApiClass<InheritedClass>
{
    //...stuff
}

public class ChildClass : ParentClass
{

}

//Now I could define a dictionary like
Dictionary<KeyClass, ParentClass> Map;

Defining it like the second example would allow me to create a Dictionary as where the first one I'm not sure I can define a Dictionary when I don't have a value for the Generic?像第二个示例一样定义它可以让我创建一个字典,因为当我没有通用值时,我不确定第一个字典是否可以定义? A bit more info about the ApiClass, the definition for the ApiClass looks like this:关于 ApiClass 的更多信息,ApiClass 的定义如下所示:

public abstract class ApiClass<Wrapper> : OtherApiClass where Wrapper : ApiClass<Wrapper>
{
    //...Stuff
}

So in a scenario like this, how would I define my ParentClass without a Generic, but where the type passed to ApiClass is the child class of the ParentClass (the ApiClass explicitly needs the child type)?因此,在这样的场景中,我将如何定义没有泛型的 ParentClass,但传递给 ApiClass 的类型是 ParentClass 的子 class(ApiClass 明确需要子类型)?

Edit: Clarified a bit on the value of InheritedClass编辑:澄清一点 InheritedClass 的值

Edit2: I am not looking for alternatives, I am asking for how to. Edit2:我不是在寻找替代品,我在问如何。 If I pass anything other than the last inherited class (the current ParentClass I defined at the beginning of the question) the Api will crash.如果我传递除最后一个继承的 class (我在问题开头定义的当前 ParentClass )以外的任何东西,Api 将崩溃。 If the syntax existed it would look something like如果语法存在,它看起来像

public abstract class ParentClass : ApiClass<typeof(this)>

I imagine that the third-party library you're using defines ApiClass like this:我想你正在使用的第三方库定义ApiClass是这样的:

public abstract class ApiClass<T> where T : ApiClass<T>

That's an example of the Curiously recurring template pattern .这是一个奇怪重复出现的模板模式的例子。

Let's turn this in to a concrete example:让我们把它变成一个具体的例子:

public abstract class ApiClass<T> where T : ApiClass<T>
{
    public abstract T GetNewInstance();
}

If I had that code, I could consume it like this:如果我有那个代码,我可以像这样使用它:

public class MyApiClass : ApiClass<MyApiClass>
{
    public override MyApiClass GetNewInstance()
    {
        return new MyApiClass();
    }
}

This allows MyApiClass to have an method, defined as an abstract method in that parent class, that knows about the current instance.这允许MyApiClass有一个方法,定义为父 class 中的抽象方法,它知道当前实例。 Eric Lippert discusses this here . Eric Lippert 在这里讨论了这个问题

It has the downside that it can be abused:它的缺点是可以被滥用:

public class MyNefariousApiClass : ApiClass<MyApiClass>
{
    public override MyApiClass GetNewInstance()
    {
        throw new NotImplementedException();
    }
}

That's legal, but C# doesn't have a way of enforcing that you use class itself as the generic parameter.这是合法的,但 C# 没有办法强制您使用 class 本身作为通用参数。 If we had class MyNefariousApiClass: ApiClass<this> it would, but we don't.如果我们有class MyNefariousApiClass: ApiClass<this>它会,但我们没有。

Now, when you say you have a class public abstract class ParentClass<T>: ApiClass<T> where T: ApiClass<T> that that's your code for consuming the third-party library.现在,当你说你有一个 class public abstract class ParentClass<T>: ApiClass<T> where T: ApiClass<T>这是你使用第三方库的代码。

If so, then that's not the normal way to consume this pattern.如果是这样,那么这不是使用这种模式的正常方式。 If you're overriding the class it should look like this:如果您要覆盖 class 它应该如下所示:

public abstract class ParentClass<T> : ApiClass<T> where T : ParentClass<T>

We can then take this to it's final point and define the ChildClass like so:然后我们可以把它带到最后一点,并像这样定义ChildClass

public class ChildClass : ParentClass<ChildClass>
{ }

Now, if you want a dictionary that can hold any such ChildClass then you are stuck as the parent is generic.现在,如果您想要一个可以容纳任何此类ChildClass的字典,那么您将被卡住,因为父类是通用的。 The only somewhat sensible workaround is to use an interface.唯一有点明智的解决方法是使用接口。

public interface IParent
{ }

public abstract class ParentClass<T> : ApiClass<T>, IParent where T : ParentClass<T> 
{ }

Then you can write Dictionary<KeyClass, IParent> dictionary = new... .然后你可以写Dictionary<KeyClass, IParent> dictionary = new...

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

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