[C#] C #에서 일반 목록을 어떻게 복제합니까?

C #에 일반 객체 목록이 있고 목록을 복제하려고합니다. 목록 내의 항목은 복제 가능하지만 수행 할 수있는 옵션이없는 것 같습니다 list.Clone().

이 문제를 해결하는 쉬운 방법이 있습니까?



답변

확장 방법을 사용할 수 있습니다.

static class Extensions
{
    public static IList<T> Clone<T>(this IList<T> listToClone) where T: ICloneable
    {
        return listToClone.Select(item => (T)item.Clone()).ToList();
    }
}


답변

요소가 값 유형 인 경우 다음을 수행 할 수 있습니다.

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

그러나 참조 유형이고 딥 카피를 원한다면 (요소가 올바르게 구현되었다고 가정 ICloneable) 다음과 같이 할 수 있습니다.

List<ICloneable> oldList = new List<ICloneable>();
List<ICloneable> newList = new List<ICloneable>(oldList.Count);

oldList.ForEach((item) =>
    {
        newList.Add((ICloneable)item.Clone());
    });

분명히 ICloneable위의 제네릭을 바꾸고 구현하는 요소 유형으로 캐스팅하십시오 ICloneable.

요소 유형이 지원하지 않지만 ICloneable복사 생성자가있는 경우 대신 다음을 수행 할 수 있습니다.

List<YourType> oldList = new List<YourType>();
List<YourType> newList = new List<YourType>(oldList.Count);

oldList.ForEach((item)=>
    {
        newList.Add(new YourType(item));
    });

개인적으로, 나는 ICloneable모든 회원의 깊은 사본을 보장 할 필요가 있기 때문에 피할 것 입니다. 대신, 복사 생성자 또는 이와 같은 팩토리 메소드 YourType.CopyFrom(YourType itemToCopy)가의 새로운 인스턴스를 반환하도록 제안합니다 YourType.

이러한 옵션은 메소드 (확장 또는 기타)로 랩핑 할 수 있습니다.


답변

얕은 복사본의 경우 대신 일반 List 클래스의 GetRange 메서드를 사용할 수 있습니다.

List<int> oldList = new List<int>( );
// Populate oldList...

List<int> newList = oldList.GetRange(0, oldList.Count);

인용 : Generics Recipes


답변

public static object DeepClone(object obj)
{
  object objResult = null;
  using (MemoryStream  ms = new MemoryStream())
  {
    BinaryFormatter  bf =   new BinaryFormatter();
    bf.Serialize(ms, obj);

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

이것은 C # 및 .NET 2.0으로 수행하는 한 가지 방법입니다. 귀하의 개체는이어야 [Serializable()]합니다. 목표는 모든 참조를 잃어 버리고 새로운 참조를 만드는 것입니다.


답변

목록을 복제하려면 .ToList ()를 호출하십시오. 얕은 사본을 만듭니다.

Microsoft (R) Roslyn C# Compiler version 2.3.2.62116
Loading context from 'CSharpInteractive.rsp'.
Type "#help" for more information.
> var x = new List<int>() { 3, 4 };
> var y = x.ToList();
> x.Add(5)
> x
List<int>(3) { 3, 4, 5 }
> y
List<int>(2) { 3, 4 }
> 


답변

약간 수정 한 후 다음을 복제 할 수도 있습니다.

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


답변

에있는 모든 단일 객체의 실제 복제가 필요하지 않은 경우 List<T>목록을 복제하는 가장 좋은 방법은 이전 목록을 collection 매개 변수로 사용하여 새 목록을 만드는 것입니다.

List<T> myList = ...;
List<T> cloneOfMyList = new List<T>(myList);

myList삽입 또는 제거와 같은 변경 은 영향을 미치지 cloneOfMyList않으며 그 반대도 마찬가지입니다.

그러나 두 목록에 포함 된 실제 개체는 여전히 동일합니다.