【问题标题】:C# collections type constrained genericsC# 集合类型约束泛型
【发布时间】:2014-06-26 21:02:24
【问题描述】:

我正在尝试使用通配符类型边界在 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# 中提供一个受约束的类型,但我不能让它(至少在语法上)与一个已经扩展另一个类的类一起工作,即 @ 987654328@,似乎没有办法只参数化方法(或属性)的返回值。

我可以创建一个新列表并将所有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&lt;T&gt; 但这只会导致生成 List&lt;ChildClass&lt;T&gt;&gt; 而不是 List&lt;T&gt;

【问题讨论】:

  • 您能否展示您编写的代码以及存在哪些问题?
  • @StriplingWarrior -- 我认为您的解决方案也是一个不错的解决方案,如果您也想在此处发布它可能对其他人有用。如果我自己从头开始编写代码,我可能会尝试这样做。干杯!

标签: c# generics collections covariance type-constraints


【解决方案1】:

我认为您的问题与通用 3rd-party SomeBindingList&lt;T&gt; 类的继承层次结构与用作参数的类型的层次结构之间关系的期望协变有关。

首先,让我给出可以编译的代码:

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# 不为类提供泛型类型协变。但它适用于接口。您必须跳出框框思考并为您的第 3 方 SomeBindingList&lt;T&gt; 实现一个简单的适配器,该适配器仅实现 协变兼容 的提升成员,即:@987654324 的那些成员@ 仅作为输出出现。

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

这将是完整的代码:

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

【讨论】:

  • 非常感谢!我不知道接口。这在我使用预先存在的代码的情况下效果很好。我可以更改的越少越好,这意味着我不必对类进行参数化,这需要在整个代码中进行更改。干杯!
猜你喜欢
  • 1970-01-01
  • 2016-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-21
相关资源
最近更新 更多