我将从代码开始,然后是问题。但它是一个比实际代码更简单的版本:
class SettingsItem<T>
{
}
class SettingsItemWhatever: SettingsItem<string>
{
}
现在问题是我想要一个类,比方说:
class abstract SettingsContainer
{
}
那将存储SettingsItem类型的对象及其后代,无论每个对象的T是什么,因此它将具有一些Set和Get方法。它也必须是一个抽象类,所以工作将在它的后代完成,而这只会定义那些必须实现的方法。
尝试编写此类方法时会出现问题。到目前为止,尽管我尝试了一些其他方法更加不方便,但我发现的最好的是:
class abstract SettingsContainer
{
public abstract Set<T> (T item);
public abstract Get<T> (string key);
}
这种方法的问题在于你可以使用你想要的任何参数来调用这些函数,并且只要它们是抽象的,它们就不能对参数类型进行任何测试,这留给了后代它不是最理想的,因为T必须是任何SettingsContainer派生类中的SettingsItem或其后代。
除此之外,我认为应该有一种方法告诉编译器参数必须是SettingsItem的后代,因此它可以在编译时检查参数类型是否正常,而不必在运行时检查类型
答案 0 :(得分:2)
您可以使用SettingsItem
关键字为where
创建非通用基类并在约束中指定它:
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;
}
或者,您可以添加另一个类型参数,以便在约束中包含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>;
}
除非您的实际用例需要将类型作为参数,否则您也可以将其包含在方法签名中:
abstract class SettingsContainer {
public abstract void Set<T>(SettingsItem<T> item);
public abstract SettingsItem<T> Get<T> (string key);
}