System.Array.CopyTo () और System.Array.Clone () के बीच अंतर


83

बीच क्या अंतर है System.Array.CopyTo()और System.Array.Clone()?


31
एक गूंगा साक्षात्कार प्रश्न की तरह। "मैं इसी समय याद नहीं है, मुझे प्रलेखन जाँच करें ..."
कोड़ी ग्रे

@MisterDev इनमें से कोई भी आपके द्वारा कॉपी किए गए मूल सरणी का कोई संदर्भ नहीं रखेगा, नहीं।
Nyerguds

@Nyerguds मुझे लगता है कि उनका मतलब है कि वे दोनों मूल सरणी तत्व ऑब्जेक्ट्स का संदर्भ रखते हैं, न कि मूल सरणी ऑब्जेक्ट के लिए।
16:16

1
@reirab ओह, मुझे पता है कि उसका क्या मतलब था। लेकिन मैंने यह बताना जरूरी समझा कि उन्होंने इसे गलत कहा।
Nyerguds

जवाबों:


64

क्लोन () विधि एक नई सरणी (एक उथले प्रतिलिपि) वस्तु मूल सरणी में सभी तत्वों वाली देता है। CopyTo () विधि प्रतियां एक और मौजूदा सरणी में तत्वों। दोनों उथली नकल करते हैं। उथली प्रतिलिपि का अर्थ है कि सामग्री (प्रत्येक सरणी तत्व) में मूल सरणी में तत्वों के समान ऑब्जेक्ट के संदर्भ होते हैं। एक गहरी प्रति (जो इन विधियों में से कोई भी प्रदर्शन नहीं करती है) प्रत्येक तत्व की वस्तु का एक नया उदाहरण बनाएगी, जिसके परिणामस्वरूप एक अलग, फिर भी समान वस्तु होगी।

तो अंतर हैं:

1- CopyTo require to have a destination array when Clone return a new array.
2- CopyTo let you specify an index (if required) to the destination array.
संपादित करें:

गलत उदाहरण निकालें।


6
आपका उदाहरण गलत है। पहले एक में, numbersCopyकेवल सौंपे गए सरणी के लिए एक और संदर्भ है numbers। यह विधि का उपयोग करने के समान नहीं हैCopyTo() । यदि आप उपयोग करते हैं CopyTo(), तो आपको अपने Clone()उदाहरण के समान परिणाम प्राप्त होंगे । इसके अलावा, यह C # है - System.out.printlnहोना चाहिए Console.WriteLine
ग्राहम क्लार्क

6
यह उत्तर, जो अन्य के रूप में भ्रामक है, यहां से कॉपी-पेस्ट है: geekswithblogs.net/dforhan/archive/2005/12/01/61852.aspx
मिखाइल

GenZiy के उदाहरण के अनुसार, वे दोनों उथली प्रति हैं। एक ऐरे की उथली प्रतिलिपि केवल एरे के तत्वों को कॉपी करती है, चाहे वे संदर्भ प्रकार या मूल्य प्रकार हों, लेकिन यह उन वस्तुओं को कॉपी नहीं करता है जो संदर्भ संदर्भित करते हैं। नए ऐरे में संदर्भ उन्हीं वस्तुओं की ओर इशारा करते हैं जो मूल ऐरे में संदर्भ इंगित करते हैं। इसके विपरीत, एक ऐरे की गहरी प्रतिलिपि तत्वों और हर चीज को प्रत्यक्ष या अप्रत्यक्ष रूप से तत्वों द्वारा संदर्भित करती है। msdn.microsoft.com/en-us/library/system.array.clone.aspx
माइक

@PatrickDesjardins। यह मेरे लिए बहुत स्पष्ट नहीं है। यदि दोनों उथली प्रति हैं तो क्या गहरी प्रतिलिपि है। क्यों CopyTo () उथले प्रति है।
कुमारहर्ष

1
.Net 3.5 में, Linq की ToArray()विधि किसी भी तरह से उथले-क्लोनिंग का एक बहुत सरल (और टाइप किया हुआ ) तरीका प्रदान करती है। चूंकि एरे वह IENumerable<T>इस पर काम करता है।
Nyerguds

28

अभी तक उल्लेखित एक अन्य अंतर यह नहीं है

  • Clone()गंतव्य सरणी के साथ अभी तक मौजूद होने की आवश्यकता नहीं है क्योंकि एक नया खरोंच से बनाया गया है।
  • साथ CopyTo()न केवल गंतव्य सरणी की जरूरत पहले से मौजूद हैं करता है, यह बड़ा पर्याप्त सूचकांक आप गंतव्य के रूप में निर्दिष्ट से स्रोत सरणी में सभी तत्वों को धारण करने के लिए की जरूरत है।

23

जैसा कि कई अन्य उत्तरों में कहा गया है कि दोनों विधियाँ सरणी की उथली प्रतियां हैं । हालांकि ऐसे मतभेद और सिफारिशें हैं जिन्हें अभी तक संबोधित नहीं किया गया है और जिन्हें निम्नलिखित सूचियों में दर्शाया गया है।

के लक्षण System.Array.Clone:

  • .NET 4.0 का उपयोग करते हुए टेस्ट, यह दर्शाता है कि यह शायद धीमी हैCopyTo क्योंकि यह उपयोग करता है Object.MemberwiseClone;
  • परिणाम को उपयुक्त प्रकार में डालने की आवश्यकता होती है ;
  • परिणामी सरणी में स्रोत के समान लंबाई है।

के लक्षण System.Array.CopyTo:

  • Cloneएक ही प्रकार के सरणी में कॉपी करते समय तेजी से होता है;
  • यह Array.Copyइनहेरिट करने की क्षमता है , जो सबसे उपयोगी है:
    • क्या संदर्भ प्रकार के तत्वों में बॉक्स प्रकार के तत्वों को रखा जा सकता है, उदाहरण के लिए, int[]सरणी को एक में कॉपी करना object[];
    • मान प्रकार के तत्वों में संदर्भ प्रकारों को अनबॉक्स कर सकते हैं, उदाहरण के लिए, object[]बॉक्सिंग के एक सरणी को एक में कॉपी intकरना int[];
    • मूल्य प्रकारों पर व्यापक रूपांतरण कर सकते हैं, उदाहरण के लिए, एक int[]में कॉपी करना long[]
    • तत्वों को डाउनकास्ट कर सकते हैं, उदाहरण के लिए, एक Stream[]सरणी को एक में कॉपी करना MemoryStream[](यदि स्रोत सरणी में कोई भी तत्व MemoryStreamअपवाद के लिए परिवर्तनीय नहीं है)।
  • स्रोत को लक्ष्य सरणी में कॉपी करने देता है, जिसकी लंबाई स्रोत से अधिक होती है।

यह भी ध्यान रखें इन तरीकों का समर्थन करने के लिए उपलब्ध कराया जाता, ICloneableऔर ICollection, इसलिए यदि आप सरणी प्रकार आप उपयोग नहीं करना चाहिए की चर के साथ काम कर रहे हैं Cloneया CopyToऔर इसके बजाय का उपयोग Array.Copyया Array.ConstrainedCopy। विवश प्रतिलिपि ने आश्वासन दिया कि यदि प्रतिलिपि कार्रवाई पूर्ण नहीं हो सकती है, तो लक्ष्य सरणी स्थिति दूषित नहीं है।


यह ठोस जानकारी है। तो हम क्लोन का एक तेज़, सामान्य संस्करण क्यों नहीं लिखते हैं? कुछ इस तरह से: पूर्व: सार्वजनिक स्थैतिक टी [] एक्सटैस्ट क्लोन <टी> (यह टी [] गिरफ्तारी) {अगर (अशक्त == गिरफ्तारी) {वापसी शून्य; } T [] arr2 = new T [arr.Length]; arr.CopyTo (arr2, 0); वापसी arr2; सार्वजनिक स्थिर टाउट [] ExtFastClone <टिन, टाउट> (यह टिन [] आगमन): जैसे -} या आप एक कास्टिंग संस्करण कर सकता है (> लंबे पूर्णांक अनुमति देने के लिए)
kevinarpe

.Net 3.5 या उच्चतर पर नंगे उथले क्लोनिंग के लिए, आप बस Linq की .ToArray()विधि का उपयोग कर सकते हैं । यह वैसे भी एक प्रतिलिपि बनाता है, और इसे किसी भी पर निष्पादित किया जा सकता है IEnumerable<>, जिसमें सरणियाँ भी शामिल हैं। और इसके विपरीत .Clone(), यह टाइप किया गया है, इसलिए कोई कास्टिंग की आवश्यकता नहीं है।
Nyerguds

22

दोनों उथली प्रतियों का प्रदर्शन @PatrickDesjardins के रूप में करते हैं (कई गुमराह आत्माओं के बावजूद जो सोचते हैं कि CopyToएक गहरी नकल करता है)।

हालाँकि, CopyToआपको गंतव्य सरणी में निर्दिष्ट सरणी में एक सरणी की प्रतिलिपि बनाने की अनुमति देता है, जिससे यह काफी अधिक लचीलापन देता है।


8
object[] myarray = new object[] { "one", 2, "three", 4, "really big number", 2324573984927361 };

//create shallow copy by CopyTo
//You have to instantiate your new array first
object[] myarray2 = new object[myarray.Length];
//but then you can specify how many members of original array you would like to copy 
myarray.CopyTo(myarray2, 0);

//create shallow copy by Clone
object[] myarray1;
//here you don't need to instantiate array, 
//but all elements of the original array will be copied
myarray1 = myarray.Clone() as object[];

//if not sure that we create a shalow copy lets test it
myarray[0] = 0;
Console.WriteLine(myarray[0]);// print 0
Console.WriteLine(myarray1[0]);//print "one"
Console.WriteLine(myarray2[0]);//print "one"

स्रोत


1
मुझे लगता है, शालो कॉपी का मतलब केवल संदर्भ की नकल है, मूल्य नहीं। इसलिए अगर आप मायार्रे [0] का मान "एक" से बदलकर 0 कर रहे हैं तो myarray1 का मूल्य नहीं होना चाहिए [0] और मायार्रे [1] का भी 0. होना चाहिए
आदर्श कुमार

1
क्षमा करें, लेकिन आपका अनुमान गलत है। उथला प्रतिलिपि संदर्भों की एक प्रति नहीं है: "मेंबरवाइज़ क्लोन विधि एक नई वस्तु बनाकर उथली प्रतिलिपि बनाता है, और फिर वर्तमान ऑब्जेक्ट के नॉनस्टैटिक फ़ील्ड को नई ऑब्जेक्ट में कॉपी करता है।" देख msdn.microsoft.com/en-us/library/...
GenZiy

1
यदि आप अपने सरणी में लगाए गए प्रकार आदिम / अपरिवर्तनीय हैं तो उथला या गहरी प्रतिलिपि अप्रासंगिक है । स्ट्रिंग्स और पूर्णांक हमेशा एक नई प्रति उत्पन्न करते हैं जब वे किसी और चीज में डालते हैं। गहरी प्रतिलिपि का परीक्षण करने के लिए, स्पॉट में से एक पर एक जटिल वस्तु (एक सरणी की तरह) डालें।
Nyerguds

2

दोनों CopyTo () और क्लोन () उथले प्रतिलिपि बनाते हैं। क्लोन () विधि मूल सरणी का क्लोन बनाती है। यह एक सटीक लंबाई सरणी देता है।

दूसरी ओर, CopyTo () मूल सरणी से गंतव्य सरणी तक तत्वों को निर्दिष्ट गंतव्य सरणी सूचकांक पर शुरू करते हुए कॉपी करता है। ध्यान दें, यह पहले से मौजूद सरणी में तत्वों को जोड़ता है।

निम्न कोड पोस्टिंग के विपरीत कहेगा कि CopyTo () एक गहरी प्रतिलिपि बनाता है:

public class Test
{
public string s;
}

// Write Main() method and within it call test()

private void test()
{
Test[] array = new Test[1];
array[0] = new Test();
array[0].s = "ORIGINAL";

Test[] copy = new Test[1];
array.CopyTo(copy, 0);

// Next line displays "ORIGINAL"
MessageBox.Show("array[0].s = " + array[0].s);
copy[0].s = "CHANGED";

// Next line displays "CHANGED", showing that
// changing the copy also changes the original.
MessageBox.Show("array[0].s = " + array[0].s);
}

इसे मैं थोड़ा समझाता हूं। यदि ऐरे के तत्व संदर्भ प्रकार के हैं, तो पहले (शीर्ष) स्तर तक की प्रतिलिपि (दोनों क्लोन और) के लिए बनाई जाएगी। लेकिन निचले स्तर की नकल नहीं होती है। यदि हमें निचले स्तर की प्रति भी चाहिए, तो हमें यह स्पष्ट रूप से करना होगा। इसीलिए संदर्भ प्रकार के तत्वों की क्लोनिंग या प्रतिलिपि बनाने के बाद, क्लोन या कोपीड सरणी में प्रत्येक तत्व उसी मेमोरी स्थान को संदर्भित करता है, जो मूल सरणी में संबंधित तत्व द्वारा संदर्भित होता है। यह स्पष्ट रूप से इंगित करता है कि निचले स्तर के लिए कोई अलग उदाहरण नहीं बनाया गया है। और यदि ऐसा था तो कोपिड या क्लोन सरणी में किसी भी तत्व के मूल्य को बदलने से मूल सरणी के संबंधित तत्व में प्रभाव नहीं होगा।

मुझे लगता है कि मेरी व्याख्या संपूर्ण है लेकिन मुझे इसे समझने लायक कोई और रास्ता नहीं मिला।


1

Array.Clone()जब intसंदर्भ के रूप में किसी विधि के लिए स्ट्रिंग या स्ट्रिंग की सरणी पास करें, तो तकनीकी रूप से गहरी प्रति प्रदर्शित होगी ।

उदाहरण के लिए

int[] numbers = new int[] { -11, 12, -42, 0, 1, 90, 68, 6, -9 }; 

SortByAscending(numbers); // Sort the array in ascending order by clone the numbers array to local new array.
SortByDescending(numbers); // Same as Ascending order Clone

भले ही विधियाँ संख्याओं के प्रकार को क्रमबद्ध करती हों, लेकिन यह छँटाई विधियों को पारित वास्तविक संदर्भ को प्रभावित नहीं करती हैं। संख्या सरणी पंक्ति संख्या 1 में एक ही अनारक्षित प्रारंभिक प्रारूप में होगी।

नोट: क्लोन को छंटाई के तरीकों में किया जाना चाहिए।


0

Clone()विधि लक्ष्य उदाहरण के संदर्भ देना नहीं है केवल आपके एक प्रति दे। CopyTo()विधि प्रतियां एक मौजूदा उदाहरण में तत्वों।

दोनों ही लक्ष्य उदाहरण का संदर्भ नहीं देते हैं और जैसा कि कई सदस्य कहते हैं कि वे संदर्भ के बिना उथली प्रति (भ्रम की नकल) देते हैं यह महत्वपूर्ण है।


0

जवाब मुझे भ्रमित कर रहे हैं। जब आप उथली प्रति कहते हैं, तो इसका मतलब है कि वे अभी भी उसी पते की ओर इशारा कर रहे हैं। जिसका मतलब है, एक को बदलने के साथ-साथ दूसरे को भी बदलना होगा।

इसलिए यदि मेरे पास A = [1,2,3,4] है और मैं इसे क्लोन करता हूं और B = [1,2,3,4] प्राप्त करता हूं। अब, अगर मैं B [0] = 9. को बदलता हूं तो इसका मतलब है कि A अब A = [9,2,3,4] होगा। क्या वो सही है?


नहीं। अगर हम b सरणी का मान बदलते हैं तो यह उस b सरणी को ही प्रभावित करता है। ए सरणी नहीं।
गोमतीप्रिया

इंटेगर, स्ट्रिंग्स, डेट्स इत्यादि कभी भी संदर्भ, लोगों द्वारा कॉपी नहीं किए जाते हैं । शैलो का अर्थ है "केवल एक स्तर गहरा"। इसका मतलब है कि संदर्भ प्रकार (सरणियाँ या अन्य जटिल वस्तुएं) अभी भी उसी वस्तुओं को इंगित करेंगे। आदिम / अपरिवर्तनीय प्रकार नहीं; उन संदर्भों के रूप में इस्तेमाल नहीं किया जा सकता है।
Nyerguds

उथली प्रतियां केवल जटिल वस्तुओं पर लागू होती हैं, जैसे कि संरचना, तार, सूची, आदि। एक इंट या डबल सरणी में हमेशा एक गहरी प्रतिलिपि होगी।
ज़ुब्रोस

0

दोनों उथली प्रतियां हैं। CopyTo विधि एक गहरी प्रतिलिपि नहीं है। निम्नलिखित कोड की जाँच करें:

public class TestClass1
{
    public string a = "test1";
}

public static void ArrayCopyClone()
{
    TestClass1 tc1 = new TestClass1();
    TestClass1 tc2 = new TestClass1();

    TestClass1[] arrtest1 = { tc1, tc2 };
    TestClass1[] arrtest2 = new TestClass1[arrtest1.Length];
    TestClass1[] arrtest3 = new TestClass1[arrtest1.Length];

    arrtest1.CopyTo(arrtest2, 0);
    arrtest3 = arrtest1.Clone() as TestClass1[];

    Console.WriteLine(arrtest1[0].a);
    Console.WriteLine(arrtest2[0].a);
    Console.WriteLine(arrtest3[0].a);

    arrtest1[0].a = "new";

    Console.WriteLine(arrtest1[0].a);
    Console.WriteLine(arrtest2[0].a);
    Console.WriteLine(arrtest3[0].a);
}

/* Output is 
test1
test1
test1
new
new
new */

0

Array.Clone को फ़ंक्शन को कॉल करते समय उपलब्ध होने के लिए लक्ष्य / गंतव्य सरणी की आवश्यकता नहीं होती है, जबकि Array.CopyTo को गंतव्य सरणी और एक इंडेक्स की आवश्यकता होती है।


-1

Clone() इसका उपयोग केवल डेटा / सरणी की संरचना को कॉपी करने के लिए किया जाता है यह वास्तविक डेटा की प्रतिलिपि नहीं करता है।

CopyTo() संरचना के साथ-साथ वास्तविक डेटा की प्रतिलिपि बनाता है।


-2

कृपया ध्यान दें: स्ट्रिंग [] से स्ट्रिंगब्यूलर [] का उपयोग करने के बीच अंतर है।

स्ट्रिंग में - यदि आप स्ट्रिंग को बदलते हैं, तो हमने जो अन्य सरणियों की प्रतिलिपि बनाई है (CopyTo या क्लोन द्वारा) जो एक ही स्ट्रिंग की ओर इशारा करती है, वह नहीं बदलेगी, लेकिन मूल स्ट्रिंग सरणी एक नए स्ट्रिंग को इंगित करेगी, हालाँकि, अगर हम स्ट्रिंग स्ट्रिंग का उपयोग करते हैं एक सरणी में, स्ट्रिंग सूचक नहीं बदलेगा, इसलिए, यह इस सरणी के लिए हमारे द्वारा बनाई गई सभी प्रतियों को प्रभावित करेगा। उदाहरण के लिए:

public void test()
{
    StringBuilder[] sArrOr = new StringBuilder[1];
    sArrOr[0] = new StringBuilder();
    sArrOr[0].Append("hello");
    StringBuilder[] sArrClone = (StringBuilder[])sArrOr.Clone();
    StringBuilder[] sArrCopyTo = new StringBuilder[1];
    sArrOr.CopyTo(sArrCopyTo,0);
    sArrOr[0].Append(" world");

    Console.WriteLine(sArrOr[0] + " " + sArrClone[0] + " " + sArrCopyTo[0]);
    //Outputs: hello world hello world hello world

    //Same result in int[] as using String[]
    int[] iArrOr = new int[2];
    iArrOr[0] = 0;
    iArrOr[1] = 1;
    int[] iArrCopyTo = new int[2];
    iArrOr.CopyTo(iArrCopyTo,0);
    int[] iArrClone = (int[])iArrOr.Clone();
    iArrOr[0]++;
    Console.WriteLine(iArrOr[0] + " " + iArrClone[0] + " " + iArrCopyTo[0]);
   // Output: 1 0 0
}

1
यह CopyToबनाम से संबंधित नहीं है Clone। यह सिर्फ संदर्भ शब्दार्थ बनाम मूल्य शब्दार्थ है। int एक मूल्य प्रकार है, इसलिए आपको हर बार एक नई प्रतिलिपि मिलती है। StringBuilder में संदर्भ शब्दार्थ हैं, इसलिए आप उसी प्रति पर काम कर रहे हैं।
नवफाल

@nawfal - मुझे पता है, इसीलिए मैंने 'कृपया ध्यान दें' लिखा था ... कॉपीरंग और क्लोन में स्ट्रिंग, स्ट्रिंगबर्ल और इंट के बीच व्यवहार का अंतर है, और यह किसी ऐसे व्यक्ति के लिए भ्रम हो सकता है जिसे इसके बारे में जानकारी नहीं है।
inbaly
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.