আমি সি # তে জেনেরিক তালিকাটি কীভাবে ক্লোন করব?


591

আমার কাছে সি # তে অবজেক্টের জেনেরিক তালিকা রয়েছে এবং আমি তালিকাটি ক্লোন করতে চাই। তালিকার মধ্যে থাকা আইটেমগুলি ক্লোনযোগ্য, তবে এটি করার কোনও বিকল্প বলে মনে হচ্ছে নাlist.Clone()

এই কাছাকাছি কোন সহজ উপায় আছে?


44
আপনার যদি বলা উচিত যে আপনি যদি একটি গভীর অনুলিপি বা অগভীর অনুলিপি খুঁজছেন
10-08 এ orip করুন

10
গভীর এবং অগভীর কপিগুলি কী কী?
কর্নেল আতঙ্ক


3
@ ইউরিপ কি clone()সংজ্ঞা দিয়ে গভীর কপি হয় না? সি # তে আপনি সহজেই = দিয়ে পয়েন্টারগুলি পাস করতে পারেন, আমি ভেবেছিলাম।
ক্রিস

13
@ ক্রিস একটি অগভীর অনুলিপি পয়েন্টার অনুলিপি চেয়ে এক স্তর গভীর অনুলিপি। উদাহরণস্বরূপ একটি তালিকার অগভীর অনুলিপিটিতে একই উপাদান থাকবে তবে এটি ভিন্ন তালিকা হবে।
orip

উত্তর:


384

আপনি একটি এক্সটেনশন পদ্ধতি ব্যবহার করতে পারেন।

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
আমি মনে করি লিস্ট.কন্ট্র্যাটএল দ্রুত সময়ে এটি করতে পারে, যেহেতু এটি তালিকাটির জন্য পুরো অ্যারেটিকে প্রাক-বরাদ্দ করতে পারে, পুরো সময়টিকে পুনরায় আকার দিতে হবে to
মাইকেলজিজি

2
@ মিশেলজিজি, আপনি যদি রূপান্তর করতে না চান তবে কেবল ক্লোন / তালিকার আইটেমগুলি নকল করতে চান? এই কাজ করবে? || var ক্লোনডলিস্ট = তালিকাঅফস্ট্রিংস। কনভার্টএল (p => পি);
ইব্রাহার মমতাজ

29
@ আইব্রার মমতাজ: এটির ক্লোনলিস্ট = নতুন তালিকা <স্ট্রিং> (লিস্টঅফসস্ট্রিংস) এর সমান;
ব্র্যান্ডন আর্নল্ড

4
চমৎকার সমাধান! উপায় দ্বারা আমি সর্বজনীন স্থিতিষ্ট তালিকাকে পছন্দ করি <T> ক্লোন <T> ... এটি এর মতো ক্ষেত্রে আরও কার্যকর, কারণ আর কোনও কাস্টের প্রয়োজন নেই: তালিকা <মাই টাইপ> ক্লোনড = listToClone.Clone ();
প্লুটোজ

2
এটি গভীর ক্লোনিং
জর্জ বীরবিলিস

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
আমি মনে করি তালিকাটি <T> on রূপান্তরকৃত সমস্ত নতুন তালিকা তৈরি করা এবং ভবিষ্যদ্বাণী করা + অ্যাড করার চেয়ে সুন্দর দেখতে পারে।
মাইকেলজিজি

2
@ দিমিত্রি: না, এটি সত্য নয়। সমস্যাটি যখন ICloneableসংজ্ঞায়িত করা হয় তখন সংজ্ঞাটি কখনও বলেনি যে ক্লোনটি গভীর বা অগভীর ছিল কি না, সুতরাং কোনও বস্তু যখন এটি প্রয়োগ করে তখন কোন ধরণের ক্লোন অপারেশন হবে তা আপনি নির্ধারণ করতে পারবেন না। এর অর্থ হ'ল আপনি যদি একটি গভীর ক্লোন List<T>করতে চান তবে এটি ICloneableএকটি গভীর অনুলিপি তা নিশ্চিত না করে আপনাকে এটি করতে হবে।
জেফ ইয়েটস

5
অ্যাডরেঞ্জ পদ্ধতিটি ব্যবহার করবেন না কেন? ( newList.AddRange(oldList.Select(i => i.Clone())বা newList.AddRange(oldList.Select(i => new YourType(i))
ফুগ

5
@ ফুগ: আমি মনে করি যে কোডটি স্ক্যান করার সময় এটি কিছুটা কম পঠনযোগ্য / বোধগম্য, এগুলিই। পঠনযোগ্যতা আমার জন্য জয়ী।
জেফ ইয়েটস

1
@ জেফইটস: একটি অপ্রতুলতার সাথে বিবেচিত রিঙ্কেলটি হ'ল সাধারণত যদি কিছু কার্যকর করার পথ থাকে যা তাদের পরিবর্তন করতে পারে তবে সাধারণত অনুলিপি করা উচিত। এটা খুব অপরিবর্তনীয় ধরনের চপল ধরনের একটি দৃষ্টান্ত একটি রেফারেন্স রাখা আছে, কিন্তু কিছু এটি পরিবর্তন ঘটান হবে যে দৃষ্টান্ত প্রকাশ করে সাধারণ। কখনও পরিবর্তন হয় না এমন জিনিসগুলির অনুলিপি অনুলিপি করা কখনও কখনও একটি বড় পারফরম্যান্স ড্রেন হতে পারে , আকারের ক্রম অনুসারে মেমরির ব্যবহার বৃদ্ধি করে।
সুপারক্যাট

84

অগভীর অনুলিপির জন্য, আপনি পরিবর্তে জেনেরিক তালিকা শ্রেণীর getRange পদ্ধতিটি ব্যবহার করতে পারেন।

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

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

উদ্ধৃত: জেনারিক্স রেসিপি


43
আপনি তালিকাটি <T> 'র কন্ট্রাক্টর ব্যবহার করে একটি তালিকা <T> যেখান থেকে অনুলিপি করতে চান তা ব্যবহার করে এটি অর্জন করতে পারেন। যেমন var shallowClonedList = নতুন তালিকা <মাইবজেক্ট> (আসললিস্ট);
আরকিলিকনাম

9
আমি প্রায়শই ব্যবহার করি List<int> newList = oldList.ToList()। একই প্রভাব। যাইহোক, আরকিলিকনমের সমাধানটি আমার মতে পাঠযোগ্যতার জন্য সেরা।
ড্যান বেচার্ড

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

এটি সি # এবং .NET 2.0 দিয়ে করার এক উপায়। আপনার অবজেক্ট হওয়া দরকার [Serializable()]। লক্ষ্যটি হ'ল সমস্ত রেফারেন্স হারাতে এবং নতুন তৈরি করা।


11
+1 - আমি এই উত্তরটি পছন্দ করি - এটি দ্রুত, নোংরা, দুষ্টু এবং খুব কার্যকর। আমি সিলভারলাইটে ব্যবহার করেছিলাম এবং বাইনারিশায়ারাইজারটি উপলভ্য না হওয়ায় ডেটা কন্ট্রাক্টসরিশালাইজার ব্যবহার করেছিলাম। আপনি কেবল এটি করতে পারলে অবজেক্ট ক্লোনিং কোডের পৃষ্ঠাগুলি কার লেখা দরকার? :)
স্লাগস্টার

3
আমি এই পছন্দ। জিনিসগুলি "সঠিক" করতে খুব ভাল লাগলেও দ্রুত এবং ময়লা প্রায়শই কাজে আসে।
ওড্রেড

3
কুইক! কিন্তু: কেন নোংরা?
কিসরল

2
এই গভীর ক্লোনগুলি দ্রুত এবং সহজ। এই পৃষ্ঠায় অন্যান্য পরামর্শ যত্নশীল। আমি বেশ কয়েকটি চেষ্টা করেছিলাম এবং তারা গভীর ক্লোন করে না।
র‌্যান্ডালটো

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
সামান্য সতর্কতা এটি একটি অগভীর অনুলিপি ... এটি দুটি তালিকার অবজেক্ট তৈরি করবে, তবে ভিতরে থাকা বস্তুগুলি একই হবে। অর্থাৎ একটি সম্পত্তি পরিবর্তন করলে মূল তালিকার একই জিনিস / সম্পত্তি পরিবর্তন হবে change
জি জি

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

টি সিরিয়ালীকরণযোগ্য হওয়া উচিত তা ভুলে যাবেন না, না হলে আপনি সিস্টেম.আরুনটাইম.সরিয়ালাইজেশন.সিরিয়ালাইজেশন এক্সেক্সেশন পান।
বেনেস ভ্যাজার্ট

ভাল উত্তর. একটি ইঙ্গিত: আপনি যোগ করতে পারেনif (!obj.GetType().IsSerializable) return default(T); প্রথম বিবৃতি হিসাবে যা ব্যতিক্রম প্রতিরোধ করে। এবং যদি আপনি এটি কোনও এক্সটেনশন পদ্ধতিতে পরিবর্তন করেন তবে আপনি এমনকি এলভিস অপারেটর ব্যবহার করতে পারেন var b = a?.DeepClone();( var a = new List<string>() { "a", "b" }; উদাহরণস্বরূপ)।
ম্যাট

15

আপনার ভিতরে প্রতিটি একক বস্তুর প্রকৃত ক্লোন প্রয়োজন না হলে List<T>তালিকার ক্লোন করার সর্বোত্তম উপায় হ'ল সংগ্রহের প্যারামিটার হিসাবে পুরানো তালিকা সহ একটি নতুন তালিকা তৈরি করা।

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

myListসন্নিবেশ করা বা সরানোর মতো পরিবর্তনগুলি প্রভাবিত করবে না cloneOfMyListএবং বিপরীত হবে।

দুটি তালিকাগুলি থাকা প্রকৃত অবজেক্টগুলি এখনও একইরকম।


আমি ব্যবহারকারী 49126 এর সাথে একমত, আমি দেখছি এটি একটি অগভীর অনুলিপি এবং একটি তালিকায় করা পরিবর্তনগুলি অন্য তালিকায় প্রতিফলিত হয়েছে।
সিডলেরোনি

1
@ সিডলেরোনি, আপনি ভুল বলেছেন তালিকার এটিতে করা পরিবর্তনগুলি অন্য তালিকার সাথে সংযুক্ত রয়েছে, তালিকার নিজেই পরিবর্তনগুলি নেই।
ওয়েলিংটন জ্যানেলি

এটি অগভীর অনুলিপি।
এলিয়ট চেন

এটি কেমন অগভীর কপি?
mko


13

ক্লোন করতে অটোম্যাপার (বা আপনি যে কোনও ম্যাপিং লিব পছন্দ করেন) ব্যবহার করুন সহজ এবং অনেকগুলি রক্ষণাবেক্ষণযোগ্য।

আপনার ম্যাপিং সংজ্ঞা দিন:

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
এটি উপাদানগুলির ক্লোন করে না।
জেফ ইয়েটস

10

আপনি যদি ইতিমধ্যে আপনার প্রকল্পে নিউটনসফট.জসন উল্লেখ করেছেন এবং আপনার অবজেক্টগুলি সিরিয়ালাইজেবল হয় তবে আপনি সর্বদা ব্যবহার করতে পারবেন:

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

সম্ভবত এটি করার সবচেয়ে কার্যকর উপায় নয় তবে আপনি যদি 100s বার এটি না করে থাকেন তবে আপনি গতির পার্থক্যটিও লক্ষ্য করতে পারবেন না।


4
এটি গতির পার্থক্য সম্পর্কে নয়, এটি পঠনযোগ্যতা সম্পর্কে। আমি যদি এই কোডের লাইনে এসে পৌঁছে যাই তবে আমি আমার মাথার উপর চড় মারব এবং ভাবছি কেন তারা সিরিয়াল হিসাবে তৃতীয় পক্ষের লাইব্রেরি চালু করেছিল এবং তারপরে এমন একটি অবজেক্টের deserialize করতে হবে যা কেন ঘটছে তা সম্পর্কে আমার কোনও ধারণা নেই। এছাড়াও, এটি বিজ্ঞপ্তিযুক্ত কাঠামোযুক্ত বস্তুগুলির সাথে মডেল তালিকার জন্য কাজ করবে না।
জোনাথন সিভিক

1
এই কোডটি গভীর ক্লোনিংয়ের জন্য আমার পক্ষে দুর্দান্তভাবে কাজ করেছে। অ্যাপ্লিকেশনটি ডকুমেন্টের বয়লারপ্লেটকে দেব থেকে কিউএ থেকে প্রোডে স্থানান্তরিত করছে। প্রতিটি বস্তু হ'ল বেশ কয়েকটি নথি টেম্পলেট অবজেক্টের একটি প্যাকেট এবং প্রতিটি ডকুমেন্টটি অনুচ্ছেদে বস্তুর একটি তালিকা নিয়ে গঠিত। এই কোডটি আমাকে .NET "উত্স" অবজেক্টগুলিকে সিরিয়ালাইজ করতে দেয় এবং তত্ক্ষণাত্ তাদের নতুন "টার্গেট" অবজেক্টগুলিতে ডিসায়ারাইজ করতে দেয়, যা পরে কোনও ভিন্ন পরিবেশে একটি এসকিউএল ডাটাবেসে সংরক্ষণ হয়। প্রচুর গবেষণার পরে, আমি প্রচুর স্টাফ পেয়েছি, যার মধ্যে বেশিরভাগ জটিল ছিল এবং এটি চেষ্টা করার সিদ্ধান্ত নিয়েছি। এই সংক্ষিপ্ত এবং নমনীয় পদ্ধতিটি ছিল "ঠিক ঠিক"!
বিকাশকারী

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

আমার বন্ধু গ্রেগর মার্টিনোভিচ এবং আমি একটি জাভাস্ক্রিপ্ট সিরিয়ালাইজার ব্যবহার করে এই সহজ সমাধানটি নিয়ে এসেছি। বাইনারিফর্মেটর ব্যবহার করার চেয়ে নিউটোনসফট জসনসিরাইজার ব্যবহার করে এমনকি দ্রুততর সিরিয়ালাইজেবল হিসাবে এবং আমাদের পরীক্ষায় ক্লাসগুলিকে পতাকাঙ্কিত করার প্রয়োজন নেই। প্রতিটি বস্তুর জন্য ব্যবহারযোগ্য এক্সটেনশন পদ্ধতিগুলি।

স্ট্যান্ডার্ড। নেট নেট জাভাস্ক্রিপ্টসিরাইজার বিকল্প:

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

    string json = js.Serialize(value);

    return js.Deserialize<T>(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

আমি যদি ভাগ্যবান হয়ে থাকি যদি কেউ কখনও এটি পড়ে থাকে ... তবে আমার ক্লোন পদ্ধতিতে টাইপ অবজেক্টের একটি তালিকা ফেরত না দেওয়ার জন্য, আমি একটি ইন্টারফেস তৈরি করেছি:

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

এবং আমার এ / ভি চিহ্নিতকরণ সফ্টওয়্যারটিতে ইন্টারফেসটির একটি বাস্তবায়ন এখানে রয়েছে। আমি আমার ক্লোন () পদ্ধতিটি ভিডমার্কের একটি তালিকা ফিরিয়ে আনতে চেয়েছিলাম (যখন আইক্লোননেবল ইন্টারফেসটি আমার পদ্ধতিটি অবজেক্টের একটি তালিকা ফেরত দিতে চেয়েছিল):

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(...)। আপনার প্রয়োজনের উপর নির্ভর করে অ্যারে শ্রেণিতে অন্তর্ভুক্ত পদ্ধতিগুলি আপনার প্রয়োজনগুলি পূরণ করতে পারে।


এটা কাজ করে না; ক্লোন করা অ্যারের মানগুলিতে পরিবর্তন এখনও মূল তালিকার মান পরিবর্তন করে।
বার্নোল্লি টিকটিকি

আপনি var ক্লোনডলিস্ট = listOfStrings.ConvertAll (p => p) ব্যবহার করতে পারেন; @ ইবরার মমতাজ প্রদত্ত .... কার্যকরভাবে কাজ করে ... একটি তালিকার পরিবর্তনগুলি নিজের কাছে রাখা হয় এবং অন্যটিতে প্রতিফলিত হয় না
জয়নুল

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

আমি আমার নিজস্ব কিছু এক্সটেনশন তৈরি করেছি যা আইক্লোননেবল প্রয়োগ করে না এমন আইটেমের আইকোলিকেশনকে রূপান্তর করে

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

কিছু সংগ্রহ মনে হয় (যেমন সিলভারলাইটে ডেটাগ্রিডের সিলেক্টড আইটেমস) কপিরাইটোর প্রয়োগটি এড়িয়ে যা যা এই পদ্ধতির সাথে সমস্যা
জর্জ বীরবিলিস

1

আমি কোনও বস্তু অনুলিপি করতে অটোম্যাপার ব্যবহার করি। আমি কেবল একটি ম্যাপিং সেটআপ করি যা একটি বস্তু নিজেই ম্যাপ করে। আপনি নিজের পছন্দ মতো এই অপারেশনটি গুটিয়ে রাখতে পারেন।

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

একটি গভীর অনুলিপিটির জন্য, আইসি্লোনেবল হ'ল সঠিক সমাধান, তবে এখানে আইসিলোনিয়েবল ইন্টারফেসের পরিবর্তে কনস্ট্রাক্টর ব্যবহার করে আইসি্লোনেবলের সাথে একই রকম দৃষ্টিভঙ্গি দেওয়া হয়েছে।

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 এর পরিবর্তে লুপের জন্যও ব্যবহার করতে পারেন তবে লিনক এটিকে সংক্ষিপ্ত এবং পরিষ্কার করে তোলে। একইভাবে আপনি অন্যান্য উত্তরগুলির পরামর্শ অনুসারে এবং এক্সটেনশন পদ্ধতিগুলি তৈরি করতে পারেন ইত্যাদি etc. তবে এর কোনওটিই প্রয়োজনীয় নয়।


এটিকে "অনুলিপি নির্মাণকারী" বলা হয়। এটি এভ ত্রুটিযুক্ত প্রবণতা, আপনি যখনই শিক্ষার্থীর সাথে কোনও নতুন ক্ষেত্র যুক্ত করেন, তখন আপনাকে এটি অনুলিপি নির্মাণকারীর সাথে যুক্ত করতে হবে। "ক্লোন" এর পিছনে মূল ধারণাটি হ'ল সমস্যাটি এড়ানো।
কেনে

2
এমনকি আইক্লোনেবলের সাথেও, আপনার ক্লাসে আপনার একটি "ক্লোন" পদ্ধতি থাকতে হবে। আপনি যদি প্রতিবিম্বটি না ব্যবহার করেন (যা আপনি উপরের পদ্ধতির ক্ষেত্রেও ব্যবহার করতে পারেন), ক্লোন পদ্ধতিটি উপরের অনুলিপি নির্মাণকারীর পদ্ধতির সাথে সত্যই মিল দেখাচ্ছে এবং নতুন / পরিবর্তিত ক্ষেত্রগুলির জন্য আপডেট করার একই সমস্যা থেকে ভুগবেন। তবে এটি বলছে "শ্রেণীর ক্ষেত্রগুলি পরিবর্তনের সাথে সাথে ক্লাসটি আপডেট করতে হবে"। অবশ্যই এটি করে;)
ztorstri

0

নিম্নলিখিত কোডটি সর্বনিম্ন পরিবর্তন সহ একটি তালিকায় স্থানান্তর করা উচিত।

মূলত এটি প্রতিটি ধারাবাহিক লুপের সাথে একটি বৃহত্তর পরিসীমা থেকে একটি নতুন এলোমেলো সংখ্যা সন্নিবেশ করে কাজ করে। ইতিমধ্যে যদি এর চেয়ে বেশি একই বা উচ্চতর সংখ্যা উপস্থিত থাকে তবে সেই এলোমেলো সংখ্যাগুলিকে একের উপরে স্থানান্তর করুন যাতে তারা এলোমেলো সূচকের নতুন বৃহত্তর পরিসরে স্থানান্তর করে।

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

আমি ওয়াচচার ক্লাসটি ব্যবহার করে এটি একটি সহজ উপায়ে পরিমাপ করেছি।

 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;

ফলস্বরূপ : অভ্যন্তরীণ অবজেক্টের সাথে পার্সনআইন্সট্যান্স - ১.4.৪, পার্সোনআইনস্ট্যান্স = নাল - ৫..6

কপিফ্যাক্টরিটি কেবলমাত্র আমার পরীক্ষার ক্লাস যেখানে আমার অভিব্যক্তি ব্যবহার সহ ডজন ডজন পরীক্ষা রয়েছে। আপনি এটি কোনও এক্সটেনশনে বা যাই হোক না কেন অন্য আকারে প্রয়োগ করতে পারেন। ক্যাচিং সম্পর্কে ভুলবেন না

আমি এখনও সিরিয়ালাইজিং পরীক্ষা করিনি, তবে এক মিলিয়ন ক্লাস নিয়ে উন্নতির বিষয়ে সন্দেহ করছি। আমি দ্রুত কিছু প্রোটোবুফ / নিউটন চেষ্টা করব।

PS: সরলতার পড়ার খাতিরে, আমি এখানে কেবল অটো-সম্পত্তি ব্যবহার করেছি। আমি ফিল্ডইনফো দিয়ে আপডেট করতে পারলাম, বা আপনার নিজের দ্বারা এটি সহজেই প্রয়োগ করা উচিত।

আমি সম্প্রতি বক্সের বাইরে ডিপক্লোন ফাংশন দিয়ে প্রোটোকল বাফার সিরিয়ালাইজার পরীক্ষা করেছি । এটি মিলিয়ন সাধারণ বস্তুগুলিতে 4.2 সেকেন্ডের সাথে জয়ী হয়, তবে যখন এটি অভ্যন্তরীণ বস্তুর আসে তখন এটি 7.4 সেকেন্ডের ফলাফলের সাথে জয়ী হয়।

Serializer.DeepClone(personList);

সংক্ষিপ্তসার: আপনার যদি ক্লাসে অ্যাক্সেস না থাকে তবে এটি সাহায্য করবে। অন্যথায় এটি বস্তুর গণনার উপর নির্ভর করে। আমি মনে করি আপনি 10,000 টি অবধি অবধি প্রতিবিম্ব ব্যবহার করতে পারেন (সম্ভবত কিছুটা কম) তবে এর চেয়ে বেশি প্রোটোকল বাফার সিরিয়ালাইজার আরও ভাল সম্পাদন করবে।


0

জেএসএন সিরিয়ালাইজার এবং ডিসরিযালার ব্যবহার করে সি # তে অবজেক্টস ক্লোন করার সহজ উপায় রয়েছে is

আপনি একটি এক্সটেনশন ক্লাস তৈরি করতে পারেন:

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.