繁体   English   中英

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

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

我目前正在使用第三方 dll 并且无法选择关闭它或不使用它。 我有一个看起来像这样的 class:

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

如果我想创建一个 Dictionary 或返回 ParentClass 类型,这会导致一些问题,这样我就不需要事先知道它是哪个子 class。 为了更容易围绕这个开发,我想做这样的事情:

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

像第二个示例一样定义它可以让我创建一个字典,因为当我没有通用值时,我不确定第一个字典是否可以定义? 关于 ApiClass 的更多信息,ApiClass 的定义如下所示:

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

因此,在这样的场景中,我将如何定义没有泛型的 ParentClass,但传递给 ApiClass 的类型是 ParentClass 的子 class(ApiClass 明确需要子类型)?

编辑:澄清一点 InheritedClass 的值

Edit2:我不是在寻找替代品,我在问如何。 如果我传递除最后一个继承的 class (我在问题开头定义的当前 ParentClass )以外的任何东西,Api 将崩溃。 如果语法存在,它看起来像

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

我想你正在使用的第三方库定义ApiClass是这样的:

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

这是一个奇怪重复出现的模板模式的例子。

让我们把它变成一个具体的例子:

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

如果我有那个代码,我可以像这样使用它:

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

这允许MyApiClass有一个方法,定义为父 class 中的抽象方法,它知道当前实例。 Eric Lippert 在这里讨论了这个问题

它的缺点是可以被滥用:

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

这是合法的,但 C# 没有办法强制您使用 class 本身作为通用参数。 如果我们有class MyNefariousApiClass: ApiClass<this>它会,但我们没有。

现在,当你说你有一个 class public abstract class ParentClass<T>: ApiClass<T> where T: ApiClass<T>这是你使用第三方库的代码。

如果是这样,那么这不是使用这种模式的正常方式。 如果您要覆盖 class 它应该如下所示:

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

然后我们可以把它带到最后一点,并像这样定义ChildClass

public class ChildClass : ParentClass<ChildClass>
{ }

现在,如果您想要一个可以容纳任何此类ChildClass的字典,那么您将被卡住,因为父类是通用的。 唯一有点明智的解决方法是使用接口。

public interface IParent
{ }

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

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

暂无
暂无

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

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