使用实现IList <t> </t>的类重构方法

时间:2014-10-08 08:21:57

标签: c# .net-3.5

我们使用.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类实现&#39; VersioningObject&#39; B类实现&#39; IIDDIdentifiable&#39;。新方法如下所示:

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

我尝试将此方法称为“DoSomething&#39;像:

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

并收到以下错误:

  • 无法转换&#34; System.Collection.Generic.List&#34;到&#34; System.Collection.Generic.List&gt;&#34;
    • DoSomeThing(System.Collections.Generic.List&gt;)的最佳重载方法匹配包含一些无效参数

我怎么能解决这个问题。非常感谢你提前!

1 个答案:

答案 0 :(得分:0)

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)
{
   //...
}

此外,通用协方差仅在.NET 4.0中添加,因此您需要将该版本的框架用于任何选项。