我在c#中有一个对象的通用列表,并希望克隆列表。列表中的项是可克隆的,但似乎没有做list. clone()的选项。

有什么简单的办法吗?


当前回答

如果有人读到这篇文章,我就很幸运了……但是为了在Clone方法中不返回类型对象的列表,我创建了一个接口:

public interface IMyCloneable<T>
{
    T Clone();
}

然后我指定了扩展名:

public static List<T> Clone<T>(this List<T> listToClone) where T : IMyCloneable<T>
{
    return listToClone.Select(item => (T)item.Clone()).ToList();
}

这里是我的A/V标记软件的接口实现。我想让我的Clone()方法返回一个VidMark列表(而ICloneable接口希望我的方法返回一个对象列表):

public class VidMark : IMyCloneable<VidMark>
{
    public long Beg { get; set; }
    public long End { get; set; }
    public string Desc { get; set; }
    public int Rank { get; set; } = 0;

    public VidMark Clone()
    {
        return (VidMark)this.MemberwiseClone();
    }
}

最后,扩展在类中的使用:

private List<VidMark> _VidMarks;
private List<VidMark> _UndoVidMarks;

//Other methods instantiate and fill the lists

private void SetUndoVidMarks()
{
    _UndoVidMarks = _VidMarks.Clone();
}

有人喜欢吗?任何改善吗?

其他回答

使用AutoMapper(或任何您喜欢的映射库)来克隆是简单的,而且易于维护。

定义映射:

Mapper.CreateMap<YourType, YourType>();

施展魔法吧:

YourTypeList.ConvertAll(Mapper.Map<YourType, YourType>);

如果你需要一个具有相同容量的克隆列表,你可以尝试这样做:

public static List<T> Clone<T>(this List<T> oldList)
{
    var newList = new List<T>(oldList.Capacity);
    newList.AddRange(oldList);
    return newList;
}

如果你只关心值类型……

你知道这种类型:

List<int> newList = new List<int>(oldList);

如果你之前不知道类型,你需要一个helper函数:

List<T> Clone<T>(IEnumerable<T> oldList)
{
    return newList = new List<T>(oldList);
}

公正:

List<string> myNewList = Clone(myOldList);

稍加修改后,你也可以克隆:

public static T DeepClone<T>(T obj)
{
    T objResult;
    using (MemoryStream ms = new MemoryStream())
    {
        BinaryFormatter bf = new BinaryFormatter();
        bf.Serialize(ms, obj);
        ms.Position = 0;
        objResult = (T)bf.Deserialize(ms);
    }
    return objResult;
}
public class CloneableList<T> : List<T>, ICloneable where T : ICloneable
{
  public object Clone()
  {
    var clone = new List<T>();
    ForEach(item => clone.Add((T)item.Clone()));
    return clone;
  }
}