我在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();
}

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

其他回答

public static object DeepClone(object obj) 
{
    object objResult = null;

    using (var ms = new MemoryStream())
    {
        var bf = new BinaryFormatter();
        bf.Serialize(ms, obj);

        ms.Position = 0;
        objResult = bf.Deserialize(ms);
     }

     return objResult;
}

这是用c#和。net 2.0实现的一种方法。你的对象必须是[Serializable()]。我们的目标是丢失所有的引用,并建立新的引用。

如果有人读到这篇文章,我就很幸运了……但是为了在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();
}

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

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;
  }
}

下面的代码应该以最小的更改转移到列表中。

基本上,它的工作原理是在每个连续的循环中插入一个更大范围的新随机数。如果已经存在与它相同或更高的数字,则将这些随机数向上移动1,以便它们转移到新的更大范围的随机索引中。

// Example Usage
int[] indexes = getRandomUniqueIndexArray(selectFrom.Length, toSet.Length);

for(int i = 0; i < toSet.Length; i++)
    toSet[i] = selectFrom[indexes[i]];


private int[] getRandomUniqueIndexArray(int length, int count)
{
    if(count > length || count < 1 || length < 1)
        return new int[0];

    int[] toReturn = new int[count];
    if(count == length)
    {
        for(int i = 0; i < toReturn.Length; i++) toReturn[i] = i;
        return toReturn;
    }

    Random r = new Random();
    int startPos = count - 1;
    for(int i = startPos; i >= 0; i--)
    {
        int index = r.Next(length - i);
        for(int j = startPos; j > i; j--)
            if(toReturn[j] >= index)
                toReturn[j]++;
        toReturn[i] = index;
    }

    return toReturn;
}

对于深度复制,ICloneable是正确的解决方案,但这里有一个类似的ICloneable方法,使用构造函数而不是ICloneable接口。

public class Student
{
  public Student(Student student)
  {
    FirstName = student.FirstName;
    LastName = student.LastName;
  }

  public string FirstName { get; set; }
  public string LastName { get; set; }
}

// wherever you have the list
List<Student> students;

// and then where you want to make a copy
List<Student> copy = students.Select(s => new Student(s)).ToList();

您需要在以下库中进行复制

using System.Linq

你也可以用for循环代替System。Linq,但是Linq使它简洁干净。同样地,你也可以像其他答案所建议的那样,创建扩展方法等等,但这些都不是必需的。