如何合并2个或更多列表实现相同的接口

时间:2009-11-24 19:50:14

标签: c# c#-3.0

假设我有2个列表

public List<TypeA> TypeARecords {get; set;}
public List<TypeB> TypeBRecords {get; set;}

TypeA和TypeB都实现相同的接口(比如说IBaseRecord)

现在我有一个只读属性,它返回所有记录的列表

public List<IBaseRecord> AllRecords
{
    get 
    {
        var allRecs = new List<IBaseRecord>();

        foreach ( var rec in TypeARecords)
            allRecs.Add(rec);

        foreach ( var rec in TypeBRecords)
            allRecs.Add(rec);

        return allRecs;
    }
}

这有效,但我确信有更有效或更智能的方法来做同样的事情 有任何想法吗?

6 个答案:

答案 0 :(得分:7)

您可以创建一个返回列表中项目的迭代器:

public IEnumerable<IBaseRecord> GetAllRecords {
  foreach (var rec in TypeARecords) {
    yield return rec;
  }
  foreach (var rec in TypeBRecords) {
    yield return rec;
  }
}

这样您就不必创建包含所有项目的新列表,只会从现有列表中读取。

编辑:
正如Stan R.建议的那样,您可以使用ToList方法创建列表的副本:

List<IBaseRecord> work = obj.GetAllRecords().ToList();

这比具有返回新列表的属性要好一些,因为列表的所有权变得更清楚。此外,属性不应该像创建列表那样繁重,至少不是每次都读取属性。

答案 1 :(得分:4)

你的方式。

public List<IBaseRecord> AllRecords
{
    get 
    {
        return new List<IBaseRecord>().
            Concat(TypeARecords.OfType<IBaseRecord>()).
            Concat(TypeBRecords.OfType<IBaseRecord>()).
            ToList();
    }
}

更好的方式。

public IEnumerable<IBaseRecord> AllRecords
{
    get 
    {
        foreach (var i in TypeARecords) yield return i;
        foreach (var i in TypeBRecords) yield return i;
    }
}

最好的方式恕我直言。

public IEnumerable<IBaseRecord> AllRecords
{
    get 
    {
        return TypeARecords.Concat<IBaseRecord>(TypeBRecords);
    }
}

答案 2 :(得分:0)

除非你使用公共接口来声明你的2个列表,否则在C#4之前你不能这样做,没有你提到的类似的东西(或linq等价物)。

答案 3 :(得分:0)

你可以使用List.AddRange(),但这仍然是一个O(n)操作,暗示它会迭代所有被添加的成员,所以它只是你已经在做的基本上是合成糖。

据推测,您不想修改ListAListB,因此您必须进行迭代才能为新列表创建新指针。

答案 4 :(得分:0)

Blindy的意思是除非你做

public List<IBaseRecord> TypeARecords {get; set;}
public List<IBaseRecord> TypeBRecords {get; set;}

然后你可以做类似

的事情
public IEnumerable<IBaseRecord> AllRecords
{
    get 
    {
        return Enumerable.Concat(TypeARecords, TypeBRecords);
    }
}

答案 5 :(得分:0)

public List<IBaseRecord> AllRecords
{
    get
    {
        return TypeARecords.Cast<IBaseRecord>()
            .Concat(TypeBRecords.Cast<IBaseRecord>()).ToList();
    }
}