C# 集合类型约束泛型

标签 c# generics collections covariance type-constraints

我正在尝试使用通配符类型绑定(bind)在 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是第 3 方 BindingList所以我不能改变它。它是参数化的,不能用非参数化版本替换。

问题当然是如何实现parentList() ChildClass 中的方法返回可用作 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>

最佳答案

我认为您的问题与通用第 3 方的继承层次结构之间关系的所需协方差有关 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# 不为类提供通用类型协变。但它适用于接口(interface)。您将不得不跳出框框思考并为您的第 3 方实现一个简单的适配器 SomeBindingList<T> ,它仅实现协变兼容的提升成员,即:那些成员 T仅作为输出出现。

例如,假设 SomeBindingList<T>包含一个方法 T Get() ,您将将此成员提升为适配器接口(interface),并创建一个简单的适配器实现

这是完整的代码:

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;
    }
}

关于C# 集合类型约束泛型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24440173/

相关文章:

c# - .NET 字典与类属性

c# - 如何在 C# 中自动化程序集文件版本

c# - 无法使用 VS Debugger Interop 执行语句

c# - 处理通用接口(interface)时的解决方法

Java 泛型异常

java - 实现一组名为 `toJson()` 的 Java 泛型函数

java - 使用 HashMap 和 List 进行嵌套双括号初始化

c# - 如何通过 C# post 请求上传文件?自己的云

C# 调用非托管 C 驱动程序 (dll)

java - 无空 "maps": Is a callback solution slower than tryGet()?