[英]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.