简体   繁体   English

抽象类中的泛型类型和方法

[英]Generic types and method in an abstract class

I am gonna start with the code and then the question. 我将从代码开始,然后是问题。 It is a more simple version than the actual code, though: 但是,它是比实际代码更简单的版本:

class SettingsItem<T>
{
}

class SettingsItemWhatever: SettingsItem<string>
{
}

Now the problem is that I want to have a class like, let's say: 现在的问题是我想拥有一个像这样的类:

class abstract SettingsContainer
{
}  

That will store objects of type SettingsItem and it's descendants, whatever the T is for each one of them, and so it will have a couple of Set and Get methods for those. 它将存储类型为SettingsItem及其后代的对象,而不管它们每个对象的T是什么,因此它将有几个Set和Get方法。 Also it has to be an abstract class, so the work will be done in its descendants while this will only defined the methods those have to implement. 它还必须是一个抽象类,因此工作将在其后代中完成,而这只会定义那些必须实现的方法。

The problem arises when trying to code such methods. 尝试对此类方法进行编码时会出现问题。 So far, and despite I tried some other approaches that resulted even more inconvenient, the best I found was this: 到目前为止,尽管我尝试了一些其他方法,但这些方法带来了更大的不便,但我发现的最好结果是:

class abstract SettingsContainer
{
    public abstract Set<T> (T item);
    public abstract Get<T> (string key);
}

The problem with this approach is that you can call those functions with whatever parameter you want, and as far as they are abstract, they cannot do any testing on the parameter type, that's left to the descendants what it is suboptimal, since T has to be a SettingsItem or its descendant in any SettingsContainer derivated class. 这种方法的问题是,您可以使用所需的任何参数来调用这些函数,并且就它们的抽象而言,它们不能对参数类型进行任何测试,因为后代必须将其视为次优的,这留给后代在任何SettingsContainer派生类中为SettingsItem或其后代。

Apart from that, I think there should be a way to tell the compiler the parameter has to be a descendant of SettingsItem, so it can check at compile time that the parameter type is OK, without having to check types at runtime instead. 除此之外,我认为应该有一种方法告诉编译器该参数必须是SettingsItem的后代,因此它可以在编译时检查参数类型是否正确,而不必在运行时检查类型。

You can create a non-generic base class for SettingsItem and specifiy it in a constraint, using the where keyword: 您可以使用where关键字为SettingsItem创建一个非通用基类,并在约束中指定它:

abstract class SettingsItem
{
    public string Key {get;}
}

class SettingsItem<T> : SettingsItem {

    public T Value {get;}
}

abstract class SettingsContainer {
    public abstract void Set<T>(T item) where T : SettingsItem;
    public abstract T Get<T> (string key) where T : SettingsItem;
}

Alternatively, you can just add another type parameter for including SettingsItem<T> in the constraint: 或者,您可以仅添加另一个类型参数以在约束中包括SettingsItem<T>

abstract class SettingsContainer {
    public abstract void Set<T,U>(T item) where T : SettingsItem<U>;
    public abstract T Get<T, U> (string key) where T : SettingsItem<U>;
}

Unless your actual use case needs the type to be a parameter, you might as well just include it in the method signature: 除非您的实际用例需要将类型作为参数,否则不妨将其包括在方法签名中:

abstract class SettingsContainer {
    public abstract void Set<T>(SettingsItem<T> item);
    public abstract SettingsItem<T> Get<T> (string key);
}

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

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