C#集合类型约束泛型

时间:2014-06-26 21:02:25

标签: c# generics collections covariance type-constraints

我正在尝试使用通配符类型边界在C#中做一些非常简单的事情。我试图将其归结为说明问题所必需的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所以我无法更改它。它已参数化,不能用非参数化版本替换。

问题当然是如何在parentList()中实现ChildClass方法,以返回可用作ParentClass对象列表的列表。

似乎应该有一些方法可以使用where关键字在C#中提供约束类型,但我不能使它(在语法上至少)使用已经扩展另一个类的类,即ChildClass,似乎没有办法仅仅参数化方法(或属性)的返回值。

我可以创建一个新列表并将所有ChildClass项目放在新列表中作为ParentClass个项目,但是(除了是kludgy)我害怕会干扰{{{{ 1}}。

我不是C#专家,所以我确信更熟悉该语言的人知道答案。谢谢!

@CodeCaster - 我尝试了很多C#代码的变体(这不能编译,我找不到一个变体):

SomeBindingList

我已尝试参数化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>>

1 个答案:

答案 0 :(得分:1)

我认为您的问题与通用第三方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;
    }
}