具有类的重构方法实现IList<;T>;

本文关键字:lt gt IList 实现 重构 方法 | 更新日期: 2023-09-27 18:25:51

我们用.NET Framework 3.5制作了一些类,它们如下所示:

public class A 
{
    public override string ID { get; set; }
    public override string Name { get; set; }
    private List<B> versionen = new List<B>();
    public List<B> Versionen
    {
        get { return versionen; }
        set { versionen = value; }
    }
}

由等其他类中的方法使用

private static void DoSomething(List<A> versioningObj)
{
    foreach (A concretClassAObject in versioningObj)
    {
        foreach (B concretClassAVersionObject in concretClassAObject.Versionen)
        {
        }
    }
}

为了重构这些代码并开发一个通用方法,我尝试实现以下接口:

public interface VersioningObject<T> : IIDIdentifiable where T : IIDIdentifiable
{
    string Name { get; set; }
    List<T> Versionen { get; set; }
}
public interface IIDIdentifiable
{
    string ID { get; set; }
}

类A实现"VersioningObject",类B实现"IIDDIdentifiable"。新方法如下:

private static void DoSomething(List<VersioningObject<IIDIdentifiable>> versioningObj)
{
    foreach (VersioningObject<IIDIdentifiable> concretClassAObject in versioningObj)
    {
        foreach(IIDIdentifiable concretClassAVersionObject in concretClassAObject.Versionen) {
        }
    }
}

我试着把这种方法称为"DoSomething",比如:

List<A> myList = new List<A>() {new A()};
DoSomething(myList);

并得到以下错误:

  • 无法将"System.Collection.Generic.List"转换为"System.Collection.Generic.List>"
    • DoSomeThing(System.Collections.Generic.List>)的最佳重载方法匹配包含一些无效参数

我该如何解决这个问题。提前非常感谢!

具有类的重构方法实现IList<;T>;

ListVersioningObject相对于它们的泛型参数都不是协变的。因此,VersioningObject<Child>不能隐式地转换为VersioningObject<Parent>(其中Child扩展了Parent)。即使它是(目前它不能是协变的,因为它接受泛型参数作为输入),List<VersioningObject<Child>>仍然不能隐式转换为List<VersioningObject<Parent>>

要做到这一切,您需要进行几个相当基本的重构。

1) VersioningObject只需要公开如何读取值,而不需要写入值,从而使其在概念上变为协变:

public interface VersioningObject<out T> : IIDIdentifiable where T : IIDIdentifiable
{
    string Name { get; }
    List<T> Versionen { get; }
}

2) DoSomething将需要接受IEnumerable,而不是ListIEnumerable是协变的,因为它只允许使用泛型参数读取数据。DoSomething只需要迭代您所展示的数据,所以这应该很好。如果您需要实际使用List特定的成员,那么这是不可能的。

private static void DoSomething(
    IEnumerable<VersioningObject<IIDIdentifiable>> versioningObj)
{
   //...
}

此外,通用协方差仅在.NET4.0中添加,因此您需要使用该版本的框架才能将其作为选项。