开发者

How to merge 2 or more Lists implementing same interface

Let say I have 2 lists

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

Both TypeA and TypeB implements same Interface (let say IBaseRecord)

Now I have a read only property that returns list of all records

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 allR开发者_如何学运维ecs;
    }
}

This works but I am sure there is more effective or just smarter way to do same thing Any ideas?


You can make an iterator that returns the items in the list:

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

This way you don't have to create a new list with all the items, it will just read from the existing lists.

Edit:
As Stan R. suggested, you can use the ToList method to create a copy of the list:

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

This is a bit better than having a property that returns a new list, as the ownership of the list gets clearer. Also, a property should not do such heavy lifting as creating lists, at least not every time the property is read.


Your way.

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

Better way.

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

Best way IMHO.

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


Unless you use the common interface to declare your 2 lists, you can't do this until C# 4 without something similar to what you mentioned (or the linq equivalent).


You can use List.AddRange(), but that's still an O(n) operation, implying that it iterates over all of the members being added, so it's just essentially syntatic sugar for what you're already doing.

Presumably you don't want to modify either ListA or ListB, so you will have to iterate in order to create the new pointers for your new list.


What Blindy means is unless you do

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

Then you can do something like

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


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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜