我试图在c#中做一些在Java中非常简单的事情,使用通配符类型边界。我试图将其归结为仅说明问题(编译)所需的Java代码:
public abstract class ParentClass {
public abstract SomeBindingList<? extends ParentClass> parentList();
}
public class ChildClass extends ParentClass {
private SomeBindingList<ChildClass> myList;
public ChildClass() {
// this could load from/bind to a database
myList = new SomeBindingList<ChildClass>();
}
public SomeBindingList<? extends ParentClass> parentList() {
return myList;
}
}
也许我需要强调下面一行,因为有人把它标记为重复: SomeBindingList
是第三方BindingList
,所以我不能改变它。它是参数化的,不能用非参数化的版本替换。
当然,问题是如何在ChildClass
中实现parentList()
方法以返回一个可以用作ParentClass
对象列表的列表。
似乎应该有一些方法使用where
关键字来提供c#中的约束类型,但我不能使它工作(至少在语法上)与一个类已经扩展了另一个类,即ChildClass
,并且似乎没有一种方法来参数化方法(或属性)的返回值。
我可以做一个新的列表,把所有的ChildClass
项目放在新的列表中作为ParentClass
项目,但是(除了笨拙)我担心这会干扰SomeBindingList
的行为。
我不是c#专家,所以我相信更熟悉这门语言的人知道答案。谢谢!
@CodeCaster—我已经尝试了许多c#代码的变体(这不能编译,我找不到一个变体):
public abstract class ParentClass {
public abstract List<T> parentList<T>() where T : ParentClass;
}
public class ChildClass {
public List<ChildClass> myList;
public ChildClass() {
myList = new List<ChildClass>();
}
public override List<T> parentList<T>() where T : ParentClass {
return myList;
}
}
我已经尝试参数化ChildClass<T>
,但这只是导致List<ChildClass<T>>
的生成,而不是List<T>
我认为您这里的问题与通用第三方SomeBindingList<T>
类的继承层次结构与用作参数的类型层次结构之间关系的期望协方差有关。
首先,让我给你编译代码:
public interface ISomeBindingList<out T>
{
}
public abstract class ParentClass
{
public abstract ISomeBindingList<ParentClass> parentList();
}
public class ChildClass : ParentClass
{
private ISomeBindingList<ChildClass> myList;
public ChildClass()
{
// this could load from/bind to a database
// myList = new SomeBindingList<ChildClass>(); // <-- we need to figure out this
}
public override ISomeBindingList<ParentClass> parentList()
{
return myList;
}
}
c#不为类提供泛型协方差。但是对于接口来说是这样的。您必须跳出思维定式,为第三方SomeBindingList<T>
实现一个简单的适配器,它只实现协变兼容的提升成员,即:那些T
只作为输出出现的成员。
例如,假设SomeBindingList<T>
包含一个方法T Get()
,您可以将该成员提升到适配器接口,并创建一个平凡的适配器实现。这将是完整的代码:
public interface ISomeBindingList<out T>
{
T Get();
}
public class SomeBindingListAdapter<T> : SomeBindingList<T>, ISomeBindingList<T>
{
}
public abstract class ParentClass
{
public abstract ISomeBindingList<ParentClass> parentList();
}
public class ChildClass : ParentClass
{
private ISomeBindingList<ChildClass> myList;
public ChildClass()
{
// this could load from/bind to a database
myList = new SomeBindingListAdapter<ChildClass>();
}
public override ISomeBindingList<ParentClass> parentList()
{
return myList;
}
}