I am trying to do something in C# that is pretty straightforward in Java, using wildcard type-bounding. I've tried to boil it down to only the Java code necessary to illustrate the problem (compiles):
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;
}
}
Perhaps I need to emphasize the following line since someone marked this as a duplicate:
SomeBindingList
is a 3rd-party BindingList
so I can't change it. It is parameterized and can't be replaced with a non-parameterized version.
The problem, of course, is how to implement the parentList()
method in the ChildClass
to return a list that can be used as a list of ParentClass
objects.
It seems like there should be some way to use the where
keyword to provide a constrained type in C#, but I can't make it work (syntactically at least) with a class that already extends another class, i.e. ChildClass
, and there doesn't seem to be a way to parameterize just the return value of a method (or a property).
I could make a new list and put all the ChildClass
items in the new list as ParentClass
items, but (aside from being kludgy) I was afraid that would interfere with the behavior of SomeBindingList
.
I'm no C# expert, so I'm sure someone more familiar with the language knows the answer. Thanks!
@CodeCaster -- I've tried many variations of C# code (this does not compile, and I can't find a variation that does):
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;
}
}
I've tried parameterizing ChildClass<T>
but that just causes generation of a List<ChildClass<T>>
which is not a List<T>
I think your issue here is related to the desired co-variance of the relationship between the inheritance hierarchy of the generic 3rd-party SomeBindingList<T>
class and the hierarchy of the types used as parameters.
First, let me give you code that will compile:
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# does not provide generic type co-variance for classes. But it does for interfaces. You will have to think outside the box and implement a trivial adapter for your 3rd-party SomeBindingList<T>
, which implements only the lifted members that are co-variantly compatible, that is: those members where T
only occurs as output.
For example, assuming SomeBindingList<T>
contains a method T Get()
, you would lift this member to an adapter interface, and create a trivial adapter implementation.
This would be the complete code:
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;
}
}