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


592

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

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


44
깊은 사본이나 얕은 사본을 찾고 있다면
orip

10
깊고 얕은 사본은 무엇입니까?
대령 패닉


3
@orip clone()정의상 깊은 사본이 아닙니까? C #에서는 =로 포인터를 쉽게 전달할 수 있다고 생각했습니다.
Chris

13
@Chris 얕은 사본은 포인터 사본보다 한 수준 깊게 복사합니다. 예를 들어 목록의 얕은 사본은 동일한 요소를 갖지만 다른 목록이됩니다.
orip

답변:


385

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

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

71
List.ConvertAll은 항상 크기를 조정 해야하는 것보다 목록의 전체 배열을 미리 할당 할 수 있기 때문에 더 빠른 시간 에이 작업을 수행 할 수 있다고 생각합니다.
MichaelGG

2
@MichaelGG, 변환하고 싶지 않고 목록의 항목을 복제 / 복제하려면 어떻게해야합니까? 이게 효과가 있을까요? || var clonedList = ListOfStrings.ConvertAll (p => p);
IbrarMumtaz

29
@IbrarMumtaz : 이는 var clonedList = new List <string> (ListOfStrings)와 동일합니다.
Brandon Arnold

4
좋은 해결책! 그건 그렇고 나는 공개 정적 List <T> CLone <T>을 선호합니다. 더 이상 캐스트가 필요하지 않기 때문에 이와 같은 경우에 더 유용합니다. List <MyType> cloned = listToClone.Clone ();
Plutoz

2
이것은 깊은 복제입니다
George Birbilis

511

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

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.

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


1
List <T> .ConvertAll은 새 목록을 만들고 foreach + add를 수행하는 것보다 멋지게 보일 수 있습니다.
MichaelGG

2
@Dimitri : 아니요, 사실이 아닙니다. 문제는 ICloneable정의 된 시점 에서 정의가 복제가 깊거나 얕 았는지 명시하지 않았기 때문에 개체가 복제 할 때 수행 될 복제 작업 유형을 결정할 수 없다는 것입니다. 즉,의 딥 클론 List<T>을 수행 ICloneable하려면 딥 카피인지 확인 하지 않고 수행해야합니다 .
Jeff Yates

5
AddRange 메소드를 사용하지 않는 이유는 무엇입니까? ( newList.AddRange(oldList.Select(i => i.Clone())또는 newList.AddRange(oldList.Select(i => new YourType(i))
phoog

5
@phoog : 코드를 스캔 할 때 읽기 쉽고 이해할 수있는 것이 아니라고 생각합니다. 가독성이 좋습니다.
Jeff Yates

1
@JeffYates : 불충분하게 고려 된 주름 중 하나는 일반적으로 주름을 변경하는 실행 경로가있는 경우에만 복사해야한다는 것입니다. 그것은이다 매우 불변의 유형 변경 가능한 유형의 인스턴스에 대한 참조를 유지해야하지만 그것을 돌연변이 아무거나에 해당 인스턴스를 노출하지하는 것이 일반적. 절대 변경되지 않는 것들을 복사하는 것은 때때로 성능을 크게 떨어 뜨리고 메모리 사용량을 몇 배나 늘릴 수 있습니다.
supercat

84

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

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

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

인용 : Generics Recipes


43
List <T>의 생성자를 사용하여 복사 할 List <T>를 지정하여이를 수행 할 수도 있습니다. 예 : var shallowClonedList = new List <MyObject> (originalList);
Arkiliknam

9
나는 종종 사용 List<int> newList = oldList.ToList()합니다. 같은 효과. 그러나 Arkiliknam의 솔루션은 내 의견으로는 가독성에 가장 좋습니다.
Dan Bechard

82
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()]합니다. 목표는 모든 참조를 잃어 버리고 새로운 참조를 만드는 것입니다.


11
+1-이 답변이 마음에 듭니다. 빠르고 더럽고 불쾌하며 매우 효과적입니다. Silverlight에서 사용했으며 BinarySerializer를 사용할 수 없으므로 DataContractSerializer를 사용했습니다. 이 작업을 수행 할 수있는 경우 누가 객체 복제 코드 페이지를 작성해야합니까? :)
slugster

3
나는 이것을 좋아한다. "올바른"일을하는 것이 좋지만, 빠르고 더러워진 경우가 종종 있습니다.
Odrade

3
빨리! 하지만 : 왜 더러워?
raiserle

2
이 깊은 복제는 빠르고 쉽습니다. 이 페이지의 다른 제안에주의하십시오. 나는 여러 번 시도했지만 그들은 깊이 복제하지 않았다.
Randall2015 년

2
그것을 부를 수 있다면 부정적인 측면만이 클래스가 작동 가능하도록 직렬화 가능으로 표시되어야한다는 것입니다.
Tuukka Haapaniemi

29

목록을 복제하려면 .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 }
> 

3
가장 간단한 솔루션
curveorzos

28
약간의 경고는 얕은 사본입니다 ... 이것은 두 개의 목록 객체를 생성하지만 내부의 객체는 동일합니다. 즉, 하나의 속성을 변경하면 원본 목록의 동일한 객체 / 속성이 변경됩니다.
Mark G

22

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

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

T는 직렬화 가능해야 함을 잊지 마십시오. 그렇지 않으면 System.Runtime.Serialization.SerializationException이 발생합니다.
Bence Végert

좋은 대답입니다. 힌트 :if (!obj.GetType().IsSerializable) return default(T); 예외를 방지하는 첫 번째 문장으로 추가 할 수 있습니다 . 그리고 확장 방법으로 변경하면 Elvis 연산자를 사용할 수도 있습니다 var b = a?.DeepClone();( var a = new List<string>() { "a", "b" }; 예 : 주어진 ).
Matt

15

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

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

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

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


나는 user49126에 동의합니다. 얕은 사본이며 한 목록의 변경 사항이 다른 목록에 반영됩니다.
Seidleroni

1
@Seidleroni, 당신은 틀 렸습니다. 목록의 변경 내용은 다른 목록에 영향을 미치며 목록 자체의 변경 사항은 적용되지 않습니다.
웰링턴 Zanelli

얕은 사본입니다.
엘리엇 첸

얕은 사본은 어떻습니까?
mko

2
@WellingtonZanelli myList에서 요소를 제거하면 cloneOfMyList에서도 요소가 제거된다는 것을 확인했습니다.
Nick Gallimore

13

AutoMapper (또는 원하는 매핑 라이브러리)를 사용하여 복제하는 것은 간단하고 유지 관리가 쉽습니다.

맵핑을 정의하십시오.

Mapper.CreateMap<YourType, YourType>();

마술을하십시오 :

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

13

가치 유형에만 관심이 있다면 ...

그리고 당신은 유형을 알고 있습니다 :

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

이전에 유형을 모르는 경우 도우미 기능이 필요합니다.

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

그냥 :

List<string> myNewList = Clone(myOldList);

15
이것은 요소를 복제하지 않습니다.
Jeff Yates

10

프로젝트에서 Newtonsoft.Json을 이미 참조했고 객체를 직렬화 할 수 있다면 항상 다음을 사용할 수 있습니다.

List<T> newList = JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(listToCopy))

아마도 가장 효율적인 방법은 아니지만 100 ~ 1000 번을 수행하지 않으면 속도 차이를 알지 못할 수도 있습니다.


4
속도 차이가 아니라 가독성에 관한 것입니다. 이 코드 줄에 와서 머리를 때리고 왜 왜 타사 라이브러리를 도입하여 직렬화 한 다음 직렬화 해제했는지 궁금해 할 것입니다. 또한 원형 구조를 가진 객체가있는 모델 목록에서는 작동하지 않습니다.
Jonathon Cwik

1
이 코드는 딥 클로닝을 위해 훌륭하게 작동했습니다. 앱이 문서 상용구를 Dev에서 QA로 마이그레이션하고 있습니다. 각 개체는 여러 문서 템플릿 개체의 패킷이며 각 문서는 단락 개체 목록으로 구성됩니다. 이 코드를 사용하면 .NET "소스"개체를 직렬화하고 즉시 새 "대상"개체로 직렬화 해제 한 다음 다른 환경의 SQL 데이터베이스에 저장합니다. 많은 연구 끝에, 나는 많은 것들을 발견했는데, 그 중 많은 것이 너무 번거롭고 이것을 시도하기로 결정했습니다. 이 짧고 유연한 접근 방식은 "맞습니다"!
개발자

3
public static Object CloneType(Object objtype)
{
    Object lstfinal = new Object();

    using (MemoryStream memStream = new MemoryStream())
    {
        BinaryFormatter binaryFormatter = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.Clone));
        binaryFormatter.Serialize(memStream, objtype); memStream.Seek(0, SeekOrigin.Begin);
        lstfinal = binaryFormatter.Deserialize(memStream);
    }

    return lstfinal;
}

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

3
    public List<TEntity> Clone<TEntity>(List<TEntity> o1List) where TEntity : class , new()
    {
        List<TEntity> retList = new List<TEntity>();
        try
        {
            Type sourceType = typeof(TEntity);
            foreach(var o1 in o1List)
            {
                TEntity o2 = new TEntity();
                foreach (PropertyInfo propInfo in (sourceType.GetProperties()))
                {
                    var val = propInfo.GetValue(o1, null);
                    propInfo.SetValue(o2, val);
                }
                retList.Add(o2);
            }
            return retList;
        }
        catch
        {
            return retList;
        }
    }

3

내 친구 Gregor Martinovic와 저는 JavaScript Serializer를 사용하여이 쉬운 솔루션을 생각해 냈습니다. 클래스를 Serializable로 플래그 지정할 필요가 없으며 Newtonsoft JsonSerializer를 사용한 테스트에서 BinaryFormatter를 사용하는 것보다 훨씬 빠릅니다. 모든 객체에 사용할 수있는 확장 방법.

표준 .NET JavascriptSerializer 옵션 :

public static T DeepCopy<T>(this T value)
{
    JavaScriptSerializer js = new JavaScriptSerializer();

    string json = js.Serialize(value);

    return js.Deserialize<T>(json);
}

Newtonsoft JSON을 사용하는 더 빠른 옵션 :

public static T DeepCopy<T>(this T value)
{
    string json = JsonConvert.SerializeObject(value);

    return JsonConvert.DeserializeObject<T>(json);
}

2
비공개 멤버는 JSON 방법을 사용하여 복제되지 않습니다. stackoverflow.com/a/78612/885627
himanshupareek66

3
 //try this
 List<string> ListCopy= new List<string>(OldList);
 //or try
 List<T> ListCopy=OldList.ToList();

3

아무도 이것을 읽지 않으면 운이 좋을 것입니다 ...하지만 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();
}

그것을 좋아하는 사람? 개선 사항이 있습니까?


2

을 사용하여 간단히 목록을 배열로 변환 한 다음을 사용하여 배열 ToArray을 복제 할 수도 있습니다 Array.Clone(...). 필요에 따라 Array 클래스에 포함 된 메소드가 요구를 충족시킬 수 있습니다.


이것은 작동하지 않습니다. 복제 된 배열의 값을 변경해도 여전히 원래 목록의 값이 변경됩니다.
Bernoulli Lizard

var clonedList = ListOfStrings.ConvertAll (p => p);을 사용할 수 있습니다. @IbrarMumtaz에 의해 주어진 .... 효과적으로 작동 ... 한 목록에 대한 변경 사항은 그 자체로 유지되고 다른 목록에 반영되지 않습니다
zainul

2

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

namespace extension
{
    public class ext
    {
        public static List<double> clone(this List<double> t)
        {
            List<double> kop = new List<double>();
            int x;
            for (x = 0; x < t.Count; x++)
            {
                kop.Add(t[x]);
            }
            return kop;
        }
   };

}

값 유형 멤버를 사용하여 모든 오브젝트를 복제 할 수 있습니다. 예를 들어 다음 클래스를 고려하십시오.

public class matrix
{
    public List<List<double>> mat;
    public int rows,cols;
    public matrix clone()
    { 
        // create new object
        matrix copy = new matrix();
        // firstly I can directly copy rows and cols because they are value types
        copy.rows = this.rows;  
        copy.cols = this.cols;
        // but now I can no t directly copy mat because it is not value type so
        int x;
        // I assume I have clone method for List<double>
        for(x=0;x<this.mat.count;x++)
        {
            copy.mat.Add(this.mat[x].clone());
        }
        // then mat is cloned
        return copy; // and copy of original is returned 
    }
};

참고 : 복사 (또는 복제)를 변경해도 원래 개체에는 영향을 미치지 않습니다.


2

동일한 용량의 복제 된 목록이 필요한 경우 다음을 시도해보십시오.

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

1

IClonable을 구현하지 않는 항목의 ICollection을 변환하는 확장 기능을 직접 만들었습니다.

static class CollectionExtensions
{
    public static ICollection<T> Clone<T>(this ICollection<T> listToClone)
    {
        var array = new T[listToClone.Count];
        listToClone.CopyTo(array,0);
        return array.ToList();
    }
}

일부 컬렉션 (실버 라이트에서 예를 들어, 데이터 그리드의 selectedItems를)이 접근 방식에 문제가하는 CopyTo의 구현 건너 뛸 것 같다
조지 Birbilis

1

automapper를 사용하여 객체를 복사합니다. 방금 하나의 객체를 자체에 매핑하는 매핑을 설정했습니다. 이 작업을 원하는 방식으로 감쌀 수 있습니다.

http://automapper.codeplex.com/


1

이 경우 캐스트를 사용하면 얕은 사본에 도움이 될 수 있습니다.

IList CloneList(IList list)
{
    IList result;
    result = (IList)Activator.CreateInstance(list.GetType());
    foreach (object item in list) result.Add(item);
    return result;
}

일반 목록에 적용 :

List<T> Clone<T>(List<T> argument) => (List<T>)CloneList(argument);

1

딥 카피의 경우 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

System.Linq 대신 for 루프를 사용할 수도 있지만 Linq는 간결하고 깨끗합니다. 마찬가지로 다른 답변이 제안하고 확장 방법 등을 만들 수 있지만 그렇게 할 필요는 없습니다.


이것을 "복사 생성자"라고합니다. 그것은 학생에게 새로운 필드를 추가 할 때마다 복사 생성자에 추가해야한다는 것을 기억해야합니다. "복제본"의 기본 아이디어는 그러한 문제를 피하는 것입니다.
kenno

2
ICloneable을 사용하더라도 클래스에 "Clone"메소드가 있어야합니다. 리플렉션을 사용하지 않는 한 (위의 접근 방식에서도 사용할 수 있음) 해당 복제 방법은 위의 복사 생성자 접근 방식과 비슷하게 보이고 새 필드 / 변경된 필드를 업데이트 해야하는 것과 동일한 문제가 발생합니다. 그러나 "클래스의 필드가 변경되면 클래스를 업데이트해야합니다"라고 말합니다. 물론 그것은;)
ztorstri

0

다음 코드는 최소한의 변경으로 목록으로 전송해야합니다.

기본적으로 각 연속 루프마다 더 큰 범위의 새로운 난수를 삽입하여 작동합니다. 이미 동일하거나 더 높은 숫자가 존재하는 경우, 그 임의의 숫자를 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;
}

0

또 다른 것은 : 당신은 반사를 사용할 수 있습니다. 이를 올바르게 캐시하면 5.6 초 안에 1,000,000 개의 객체를 복제 할 수 있습니다 (내부 객체의 경우 16.4 초).

[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)]
public class Person
{
       ...
      Job JobDescription
       ...
}

[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)]
public class Job
{...
}

private static readonly Type stringType = typeof (string);

public static class CopyFactory
{
    static readonly Dictionary<Type, PropertyInfo[]> ProperyList = new Dictionary<Type, PropertyInfo[]>();

    private static readonly MethodInfo CreateCopyReflectionMethod;

    static CopyFactory()
    {
        CreateCopyReflectionMethod = typeof(CopyFactory).GetMethod("CreateCopyReflection", BindingFlags.Static | BindingFlags.Public);
    }

    public static T CreateCopyReflection<T>(T source) where T : new()
    {
        var copyInstance = new T();
        var sourceType = typeof(T);

        PropertyInfo[] propList;
        if (ProperyList.ContainsKey(sourceType))
            propList = ProperyList[sourceType];
        else
        {
            propList = sourceType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
            ProperyList.Add(sourceType, propList);
        }

        foreach (var prop in propList)
        {
            var value = prop.GetValue(source, null);
            prop.SetValue(copyInstance,
                value != null && prop.PropertyType.IsClass && prop.PropertyType != stringType ? CreateCopyReflectionMethod.MakeGenericMethod(prop.PropertyType).Invoke(null, new object[] { value }) : value, null);
        }

        return copyInstance;
    }

Watcher 클래스를 사용하여 간단한 방법으로 측정했습니다.

 var person = new Person
 {
     ...
 };

 for (var i = 0; i < 1000000; i++)
 {
    personList.Add(person);
 }
 var watcher = new Stopwatch();
 watcher.Start();
 var copylist = personList.Select(CopyFactory.CreateCopyReflection).ToList();
 watcher.Stop();
 var elapsed = watcher.Elapsed;

결과 : 내부 인스턴스 PersonInstance-16.4, PersonInstance = null-5.6

CopyFactory는 표현식 사용을 포함하여 수십 가지 테스트를 수행 한 테스트 클래스입니다. 이것을 확장 또는 다른 형태로 다른 형태로 구현할 수 있습니다. 캐싱을 잊지 마십시오.

아직 직렬화를 테스트하지는 않았지만 백만 개의 클래스로 개선하는 데는 의문의 여지가 있습니다. 빠른 protobuf / newton을 시도하겠습니다.

추신 : 읽기 간단 성을 위해 여기서는 자동 속성 만 사용했습니다. FieldInfo로 업데이트하거나 직접 구현할 수 있습니다.

최근 에 DeepClone 기능을 사용 하여 프로토콜 버퍼 직렬 변환기를 즉시 테스트했습니다 . 백만 개의 단순한 물체에서 4.2 초가 걸리지 만 내부 물체의 경우 7.4 초로 이깁니다.

Serializer.DeepClone(personList);

요약 : 수업에 액세스 할 수 없으면 도움이됩니다. 그렇지 않으면 개체의 수에 따라 다릅니다. 최대 10,000 개의 객체 (약간 작을 수도 있음)를 사용할 수 있다고 생각하지만 이보다 많은 경우 프로토콜 버퍼 직렬 변환기의 성능이 향상됩니다.


0

JSON 시리얼 라이저 및 디시리얼라이저를 사용하여 C #에서 객체를 복제하는 간단한 방법이 있습니다.

확장 클래스를 만들 수 있습니다 :

using Newtonsoft.Json;

static class typeExtensions
{
    [Extension()]
    public static T jsonCloneObject<T>(T source)
    {
    string json = JsonConvert.SerializeObject(source);
    return JsonConvert.DeserializeObject<T>(json);
    }
}

복제하고 반대하려면 :

obj clonedObj = originalObj.jsonCloneObject;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.