2017-02-02 2 views
2

MemberwiseClone의 좀 더 제한된 버전을 만들고 싶었지만 내 자신의 C# 코드가 객체에 속성을 추가하는 유일한 방법은 dynamic을 사용하는 것이지만 객체에 원본과 동일한 유형을 부여 할 수는 없다는 것을 깨달았습니다. 내 다른, 끔찍한 선택은 새로운 복제본에 대한 소스를 방출하고 런타임 동안 그것을 컴파일하는 것입니다, 그러나 그것은 복잡성을 다시 운반합니다. 어셈블리 참조 등 내가 물건을 간단하게 유지에 대한 상관 없어.MemberWiseClone은 복제 된 속성을 사용하여 새 객체를 어떻게 만듭니 까?

지금은 단지 MemberwiseClone을 사용하고 있지만 실제로 어떻게 작동하는지 궁금합니다. 디 컴파일 된 소스를 찾을 수 없습니다.

+1

요즘에는 디 컴파일러가 필요하지 않습니다. [참조 소스] (https://referencesource.microsoft.com/#mscorlib/system/object.cs,1556d8bb3f97be20)는 메소드가 런타임 자체 (MethodImplOptions.InternalCall)에 의해 구현되었음을 알려줍니다. 여기에서 CoreClr github repo로 이동하여 통화를 검색하십시오. 귀하의 경우에는 원하는 구현이 포함 된 [이 파일] (https://github.com/dotnet/coreclr/blob/master/src/classlibnative/bcltype/objectnative.cpp)을 찾을 수 있습니다 (ObjectNative : : 복제). – thehennyy

+0

감사합니다, @thehennyy, 이제 참조 코드에서 물건을 찾는 방법에 대해 더 많이 알고 있지만 C++은 10 년 뒤에 있습니다. 그리고 나는'ObjectNative :: Clone'이 무엇을하는지 전혀 모릅니다. 이 질문을 통해 내가 알고 싶은 것은 그 사물을 복제하는 데 어떤 원리가 사용되는지입니다. 그것을 C++로 보는 것은 바이트 복사를위한 직접 바이트를 수행하는 것입니까? – ProfK

+0

세계에서이 질문을 "너무 광범위하게"찾아 투표를 종료 할 수 있습니까? 매우 구체적인 질문을 하나만하고 있습니다. 대답은 매우 제한되어 있습니다. 제목은 질문입니다. 그것을 더미로 읽으십시오. – ProfK

답변

8

그것은 기본적으로 MemberwiseClone MSDN documentation에 설명 된 것 :

MemberwiseClone 방법은 새로운 객체를 생성 한 다음 새 객체에 현재 객체의 비 정적 필드를 복사하여 단순 복사본을 만듭니다. 필드가 값 유형이면 필드의 비트 별 사본이 수행됩니다. 필드가 참조 유형 인 경우 참조가 복사되지만 참조 된 객체는 복사되지 않습니다. 따라서 원래 개체와 해당 개체의 복제본은 동일한 개체를 참조합니다.

위의 실제 구현은 CLR에 의해 내부적으로 구현됩니다. 당신은 다음과 같은 표준 C# 코드의 최적화 된 변종으로 생각 할 수 있습니다

using System.Reflection; 
using System.Runtime.Serialization; 

public static object CustomMemberwiseClone(object source) 
{ 
    var clone = FormatterServices.GetUninitializedObject(source.GetType()); 
    for (var type = source.GetType(); type != null; type = type.BaseType) 
    { 
     var fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly); 
     foreach (var field in fields) 
      field.SetValue(clone, field.GetValue(source)); 
    } 
    return clone; 
} 

즉, 실제의 형태를 얻을 수있는 생성자를 호출하지 않고 해당 유형 의 새로운 인스턴스를 생성하고 각 인스턴스 필드의 값을 복사 소스 객체.

다시 말하면, 실제 내부 구현은 (주석에서 지적한 바와 같이) 위의 스 니펫은 원리를 보여 주며 반사를 통해 동일한 의미론으로 메소드를 구현하는 방법입니다 (물론 훨씬 느릴 것입니다 CLR 방법보다).

영업 시간에 추가 : 자세한 내용은 아래에서 Ivan의 의견을 참조하십시오. 나는이 부분을 그의 대답으로 생각하고 그것을 바탕으로 받아 들일 것이다.

+0

그래도 필자는 필자가 직접 작성한 코드를 작성하여 필드가 아닌 선언 된 공개 및 비 컬렉션 속성이 복사되도록했습니다. 자세한 뷰 모델은 간단한 속성 만 가져야하며, 하지만 고차원 적으로 CLR 메서드가 내부적으로 어떻게 처리할까요? 즉, 이진 바이트, 바이트 복사 용 바이트 또는 무엇입니까? – ProfK

+1

기본적으로 저수준 복사 메모리 (바이트)를 사용합니다. 'struct' 변수 할당과 비슷합니다. –

+2

GC Refs (포인터) 내부에 특별한주의를 기울 였지만, 다시 한번'string'을 내부에'struct'를 복사하는 것과 다른 점이 없습니다. 어쨌든, 이제는 내 대답이 귀하의 질문을 다루지 않는 것을 보았습니다. 그래서 나는 그것을 삭제할 것입니다. –

관련 문제